点击主图,触发的是查看产品详情的逻辑

news/2025/1/8 4:57:14 标签: 前端, 开发语言

文章目录

  • 1、点击主图,触发的是查看产品详情的逻辑
  • 2、点击主图,发送的请求是 productDetail 这个方法
  • 3、与主图相关的代码片段

1、点击主图,触发的是查看产品详情的逻辑

点击主图的确不会触发那些物流参数输入框的自动查询。 那些输入框需要用户手动输入数据。

点击主图,触发的是查看产品详情的逻辑,包括了根据产品 ID 查询产品详情数据(其中就包含了物流参数),然后将这些数据显示在对应的只读区域,而非那些输入框中。

让我再更正一下:

  1. 物流参数的来源: 物流参数(如净重、毛重、尺寸、箱规等)是产品的基本属性,需要在产品信息创建或编辑时由用户手动输入保存到数据库。

  2. 输入框的作用: <el-input> 组件在 operateType === 'edit' 模式下,是用来给用户输入或修改这些物流参数的。它们并不会根据你点击主图或其他操作自动去查询并填充数据。

  3. 点击主图的逻辑: 点击主图,触发的是 handleView(row) 方法,该方法执行的是路由跳转到产品详情页:

    public handleView(row: any) {
      this.$router.push({ path: `productDetail/${row.id}/view` })
    }
    
  4. 详情页的数据加载:productDetail 组件 (即 src/views/product/detail.vue) 中,mounted 钩子函数会根据路由参数中的 idoperateType 来决定是查看详情还是编辑。当 operateType === 'view' 时,会调用 getproductDetail() 方法:

    async mounted() {
        // ...
        this.id = parseInt(this.$route.params.id);
        this.operateType = this.$route.params.operateType;
        // ...
        if (this.id > 0) {
          await this.getproductDetail()
          // ...
        }
      }
    
    public async getproductDetail() {
        const res: any = await productDetail({ id: this.id })
        if (res.code === 0) {
          const form = res.data
          // ...
          this.form = { ...form }
          this.formSource = { ...form }
          console.log(this.form)
        }
      }
    

    getproductDetail() 方法会调用 productDetail API (在 src/api/product.ts 中定义) 向后端发送请求,获取产品详情数据。

  5. 数据的显示:productDetail 组件的 template 中,可以看到当 operateType !== 'edit' (即查看模式) 时,物流参数是通过 {{ form.netWeight }}{{ form.grossWeight }} 这种形式直接显示数据的:

     <el-col :span="6">
        <el-form-item label="产品净重(g)" prop="netWeight" label-width="130px">
          <span v-if="operateType !== 'edit'">
            {{ form.netWeight }}
          </span>
          <el-input v-else v-model="form.netWeight" placeholder="产品净重(g)" />
        </el-form-item>
      </el-col>
      <el-col :span="6">
        <el-form-item label="产品毛重(g)" prop="grossWeight" label-width="130px">
          <span v-if="operateType !== 'edit'">
            {{ form.grossWeight }}
          </span>
          <el-input v-else v-model="form.grossWeight" placeholder="产品毛重(g)" />
        </el-form-item>
      </el-col>
    

    也就是说,查看模式下,并不是通过输入框来显示数据,而是直接将数据显示在 <span> 标签中。只有在编辑模式下,才会将数据显示在el-input中,因为这个时候需要双向绑定。

总结:

  • 点击主图不会自动查询并填充物流参数到那些输入框中。
  • 输入框是用来给用户手动输入或修改物流参数的。
  • 点击主图会跳转到产品详情页,详情页会根据产品 ID 查询产品详情数据(包括物流参数),并将数据显示在只读区域,而不是输入框。
  • 物流参数是产品的基本属性,需要在创建或编辑产品信息时,由用户手动输入并保存到数据库。

2、点击主图,发送的请求是 productDetail 这个方法

点击主图,发送的请求是 productDetail 这个方法。

以下是完整的逻辑链条:

  1. 点击事件: 当用户在产品列表页面点击主图时,会触发 handleView(row) 方法。

    <el-image
      style="width: 105px; height: 105px; cursor: pointer;"
      :src="row.image ? oss + row.image + '!commodity_big_350' : require('@/assets/images/main-image-empty.png')"
      fit="contain"
      @click="handleView(row)" 
    >
      <div slot="error" class="image-slot">
        <el-image :src="require('@/assets/images/main-image-empty.png')" />
      </div>
    </el-image>
    
  2. 路由跳转: handleView(row) 方法内部使用 this.$router.push 进行路由跳转,跳转到产品详情页:

    public handleView(row: any) {
      this.$router.push({ path: `productDetail/${row.id}/view` })
    }
    
  3. 组件挂载: 跳转到 productDetail 组件后,该组件会被挂载,执行其 mounted 钩子函数:

    async mounted() {
        this.getStageImageList()
        this.id = parseInt(this.$route.params.id)
        this.operateType = this.$route.params.operateType
        if (this.operateType !== 'view') this.initAllEditor()
        this.getBrands()
        if (this.operateType === 'add') {
          await this.getValidFields()
        }
        this.getQualifyTypes()
        if (this.id > 0) {
          await this.getproductDetail()
          if (this.operateType === 'edit' || this.operateType === 'view') {
            this.getValidFields()
          }
        }
      }
    
  4. 获取详情:mounted 钩子函数中,通过判断 this.id 是否大于 0(即是否为有效的产品ID)以及 this.operateType 是否为 view(即查看模式),决定是否调用 getproductDetail 方法获取产品详情。由于 handleView 传递了 row.idview,所以这两个条件都满足,getproductDetail 方法会被调用。

  5. 发送请求: getproductDetail 方法内部调用了 productDetail API:

    public async getproductDetail() {
        const res: any = await productDetail({ id: this.id })
        if (res.code === 0) {
          const form = res.data
          const res2 = await fieldsById({ categoryId: form.categoryId })
          const ss = res2.data.content
          if (form.fieldList.length > 0) {
            form.fieldList = form.fieldList.map(o => ({ ...ss.find(p => o.id === p.id), ...o, key: Math.random() + '' }))
          }
          if (this.operateType !== 'view') {
            this.editor.txt.html(form.detail || '')
            // this.editor1.txt.html(form.detail1 || '')
            // this.editor2.txt.html(form.detail2 || '')
            // this.editor3.txt.html(form.detail3 || '')
            // this.editor4.txt.html(form.detail4 || '')
            // this.editor5.txt.html(form.detail5 || '')
            // this.editor6.txt.html(form.detail6 || '')
            // this.editor7.txt.html(form.detail7 || '')
            // this.editor8.txt.html(form.detail8 || '')
            // this.editor9.txt.html(form.detail9 || '')
          }
          Object.assign(form, { stageImageIdListx: form.stageImageIdList[0] })
          this.form = { ...form }
          this.formSource = { ...form }
          console.log(this.form)
        }
      }
    
  6. productDetail API 定义:src/api/product.ts 文件中,productDetail 函数负责发送请求:

    export const productDetail = (params: any) =>
      request({
        url: 'product/admin/detail',
        method: 'get',
        params
      })
    

    这个函数发送了一个 GET 请求到 product/admin/detail 接口,并传递了一个 params 参数,其中包含了产品 id

总结:

点击主图触发的请求是 productDetail 方法,它发送一个 GET 请求到 /product/admin/detail 接口,并携带产品 id 作为参数,用于获取指定产品的详细信息。

3、与主图相关的代码片段

以下是与主图相关的代码片段,并附有解释:

1. 列表页 (src/views/product/index.vue)

<template>
  <div class="page-wrap">
    <div class="table">
      <el-table v-loading="loading" :height="tableHeight" :data="list" @selection-change="handleSelectionChange">
        <el-table-column label="主图" align="center">
          <div v-if="row.image + '!commodity_big_350'" slot-scope="{row}" class="el-table-column-image-wrap">
            <el-image
              style="width: 105px; height: 105px; cursor: pointer;"
              :src="row.image ? oss + row.image + '!commodity_big_350' : require('@/assets/images/main-image-empty.png')"
              fit="contain"
              @click="handleView(row)"
            >
              <div slot="error" class="image-slot">
                <el-image :src="require('@/assets/images/main-image-empty.png')" />
              </div>
            </el-image>
          </div>
        </el-table-column>
        <template #empty>
          <div style="display: grid; place-items: center center;"><function-guide-main :type="2" /></div>
        </template>
      </el-table>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { AppModule } from '@/store/modules/app'
import { products } from '@/api/product'
// ... 其他引入

@Component({
  name: 'product-list',
  components: { /* ... */ }
})

export default class extends Vue {
  // ...

  public oss: string = AppModule.oss

  // ...

  public handleView(row: any) {
    this.$router.push({ path: `productDetail/${row.id}/view` })
  }

  // ...

  public async getList() {
    this.loading = true
    const { page, size, field, value } = this.listQuery
    const searchData = { page, size, field, value }
    const res: any = await products(searchData)
    if (res.code === 0) {
      this.list = this.packList(res.data.content)
      // this.list = []
      this.listQuery = { ...this.listQuery, total: res.data.totalElements }
      this.loading = false
    }
  }

  // ...

  created() {
    // ...
    this.getList()
  }

  // ...

  mounted() {
    // ...
    this.getList()
    // ...
  }
}
</script>

代码解释:

  • el-table-column (label=“主图”): 这一列用于显示产品主图。
  • v-if="row.image + '!commodity_big_350'": 判断 row.image 是否存在且加上 !commodity_big_350 后不为空。这里是为了防止 row.imagenull 或空字符串时,oss + row.image 拼接出错。
  • slot-scope="{row}": 作用域插槽,可以获取到当前行的数据 row
  • el-image: 显示图片的组件。
    • style="width: 105px; height: 105px; cursor: pointer;": 设置图片样式,并且鼠标悬停时显示为手型。
    • :src="row.image ? oss + row.image + '!commodity_big_350' : require('@/assets/images/main-image-empty.png')": 设置图片的 src 属性。
      • row.image ? oss + row.image + '!commodity_big_350':如果 row.image 存在,则拼接 oss (图片服务器地址前缀)、row.image (图片文件名或路径) 和 !commodity_big_350 (图片处理参数,例如指定图片尺寸) 作为图片的 URL。
      • require('@/assets/images/main-image-empty.png'):如果 row.image 不存在,则显示默认的空图片。
    • fit="contain": 设置图片适应容器的方式为 contain,保持图片的宽高比。
    • @click="handleView(row)": 绑定点击事件,点击图片时调用 handleView 方法,并传入当前行的数据 row
  • div slot="error": 当图片加载失败时,显示 slot="error" 的内容,这里是一个默认的空图片。
  • handleView(row): 点击主图时触发的方法,跳转到产品详情页。
  • oss: string = AppModule.oss: 从 Vuex 的 AppModule 中获取 oss 变量,通常是图片服务器的地址前缀。
  • getList(): 获取产品列表数据,其中包含了 row.image,即主图的相对路径或文件名。

2. 详情页 (src/views/product/detail.vue)

<template>
  <div class="product-detail">
    <el-form ref="form" :model="form">
      <el-row :gutter="20">
        <el-col :span="18">
          <el-form-item label="主图" label-width="130px">
            <div slot="label">
              <span>主图
                <el-tooltip class="item" effect="dark" content="上传大小不超过3M,支持jpg、jpeg、png格式,建议尺寸:640*640 像素,1:1亦可"
                  placement="bottom-start">
                  <i class="el-icon-warning-outline" />
                </el-tooltip>
              </span>
            </div>
            <el-image v-if="form.image && operateType !== 'edit'" style="width: 80px; height: 80px"
              :src="oss + form.image" :preview-src-list="[`${oss}${form.image}`]" />
            <upload-image v-else ref="uploadImage" :image-path="form.image" folder-name="product-image"
              @upload-success="(e) => handleUploadSucc('image', e)" @handle-remove="handleUploadSucc('image')" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { AppModule } from '@/store/modules/app'
import { productDetail } from '@/api/product'
// ... 其他引入

@Component({
  name: 'detail',
  components: { /* ... */ },
  mixins: [ /* ... */ ]
})
export default class extends Vue {
  public oss: string = AppModule.oss
  // ...
  public form: any = { shelfLifeUnit: 3, region: 9 } // 注意这里初始化了 form,但主图 image 属性是在 getproductDetail 中赋值的
  // ...

  public async getproductDetail() {
    const res: any = await productDetail({ id: this.id })
    if (res.code === 0) {
      const form = res.data
      // ...
      this.form = { ...form }
      // ...
    }
  }

  // ...

  async mounted() {
    // ...
    this.id = parseInt(this.$route.params.id)
    this.operateType = this.$route.params.operateType
    // ...
    if (this.id > 0) {
      await this.getproductDetail()
      // ...
    }
  }

  // ...
}
</script>

代码解释:

  • el-form-item (label="主图"): 表单项,用于显示或编辑主图。
  • v-if="form.image && operateType !== 'edit'": 判断 form.image 是否存在且当前操作类型不是编辑模式,满足条件则显示已有的主图。
  • el-image: 显示图片的组件。
    • style="width: 80px; height: 80px": 设置图片样式。
    • :src="oss + form.image": 设置图片的 src 属性为 oss + form.image,即图片服务器地址前缀加上图片文件名或路径。
    • :preview-src-list="[ o s s {oss} oss{form.image}]": 设置图片预览的 src 列表,这里只有一个图片。
  • v-else: 如果不满足 v-if 的条件(即 form.image 不存在或当前是编辑模式),则显示 upload-image 组件,用于上传图片。
  • upload-image: 自定义的上传图片组件。
    • :image-path="form.image": 传递当前的图片路径给上传组件。
    • folder-name="product-image": 指定上传图片的文件夹名称。
    • @upload-success="(e) => handleUploadSucc('image', e)": 上传成功的回调函数。
    • @handle-remove="handleUploadSucc('image')": 删除图片的回调函数。
  • getproductDetail(): 获取产品详情数据,其中包含了 form.image,即主图的相对路径或文件名。
  • handleUploadSucc(key, res: string = ''): 上传图片成功或删除图片的回调函数,更新form表单中图片的值

总结:

列表页和详情页都涉及到了主图的显示:

  • 列表页: 点击主图会跳转到详情页,并通过 row.image 属性获取主图的相对路径或文件名,然后拼接成完整的 URL 显示图片。
  • 详情页: 通过 form.image 属性获取主图的相对路径或文件名,然后拼接成完整的 URL 显示图片或传递给上传组件。

这两处获取到的 row.imageform.image 都是通过后端 API 获取到的,具体的值取决于后端如何存储和返回图片信息。通常情况下,row.imageform.image 保存的是图片的相对路径或文件名,需要拼接上前缀(如 oss)才能在浏览器中显示。

在这里插入图片描述


http://www.niftyadmin.cn/n/5815669.html

相关文章

一文讲清楚PostgreSQL分区表

文章目录 一、PostgreSQL详细介绍1. 起源与发展2. 核心特性3.社区与企业支持 二、分区的详细介绍1. 分区是什么2. 为什么需要分区3. 怎么分区&#xff08;1&#xff09;范围分区&#xff08;Range Partitioning&#xff09;&#xff08;2&#xff09;列表分区&#xff08;List …

Python中使用正则表达式的场景

正则表达式(Regular Expression)是处理字符串的强大工具。它由一系列字符和特殊符号组成,用于匹配字符串中的模式。Python内置了re模块,可以轻松地使用正则表达式。 引言 正则表达式是一种强大的文本处理工具,广泛应用于各种编程语言中。Python 的 re 模块提供了丰富的功…

流程图(四)利用python绘制漏斗图

流程图&#xff08;四&#xff09;利用python绘制漏斗图 漏斗图&#xff08;Funnel Chart&#xff09;简介 漏斗图经常用于展示生产经营各环节的关键数值变化&#xff0c;以较高的头部开始&#xff0c;较低的底部结束&#xff0c;可视化呈现各环节的转化效率与变动大小。一般重…

深入理解 Qt 中的信号与槽机制:`private` 和 `private slots` 的区别及新旧版本的连接方式

文章目录 问题描述示例代码 private: 和 private slots: 的区别1. private: 访问修饰符2. private slots: 访问修饰符访问权限与信号槽机制为什么 private slots: 中的槽函数可以正常使用&#xff1f;修改后的正确代码 Qt 新旧版本的信号与槽连接方式旧版信号槽连接方式问题&am…

Python编程实例-机器学习中的Hinge Loss编程实现

机器学习中的Hinge Loss编程实现 文章目录 机器学习中的Hinge Loss编程实现1、机器学习中的损失函数是什么?2、什么是 Hinge Loss?3、Hinge Loss如何工作?4、Hinge Loss的优缺点5、Python语言实现6、总结Hinge Loss(铰链损失)在分类任务中至关重要,广泛应用于支持向量机 …

Springboot SAP Docker 镜像打包问题

问题类1&#xff0c;sapjco.jar 未识别到&#xff1a;Caused by: java.lang.NoClassDefFoundError: com/sap/conn/jco/ext/DestinationDataProvider 1./deploy/lib/ 文件下放sapjco3.jar、libsapjco3.so、sapjco3.dll 2.docker文件核心内容&#xff1a; COPY /deploy/lib/sap…

leetcode 1871. 跳跃游戏 VII

题目如下 数据范围 显然n平方的时间复杂度会报超时错误,所以这道题不宜暴力。 这道题可以这么思考:设字符串为s minjump为min maxjump为max当s[i] 0 时考虑 当 i ∈[i - max,i - min](其中i - max &#xff1e; 0)时可达所以这道题实际上就转变为判断当在[i - max,i - min]…

时空遥感影像智能解译软件(基础版)

一、时空遥感影像智能解译软件&#xff08;基础版&#xff09;简概 “时空遥感影像智能解译软件&#xff08;基础版&#xff09;”&#xff0c;该软件基于Python高级编程语言与PyQt5界面设计框架开发&#xff0c;依赖于sys、os系统库以及OpenCV、GDAL、Numpy、Math、Random、Ma…