文章目录
- 1、点击主图,触发的是查看产品详情的逻辑
- 2、点击主图,发送的请求是 productDetail 这个方法
- 3、与主图相关的代码片段
1、点击主图,触发的是查看产品详情的逻辑
点击主图的确不会触发那些物流参数输入框的自动查询。 那些输入框需要用户手动输入数据。
点击主图,触发的是查看产品详情的逻辑,包括了根据产品 ID 查询产品详情数据(其中就包含了物流参数),然后将这些数据显示在对应的只读区域,而非那些输入框中。
让我再更正一下:
-
物流参数的来源: 物流参数(如净重、毛重、尺寸、箱规等)是产品的基本属性,需要在产品信息创建或编辑时由用户手动输入并保存到数据库。
-
输入框的作用:
<el-input>
组件在operateType === 'edit'
模式下,是用来给用户输入或修改这些物流参数的。它们并不会根据你点击主图或其他操作自动去查询并填充数据。 -
点击主图的逻辑: 点击主图,触发的是
handleView(row)
方法,该方法执行的是路由跳转到产品详情页:public handleView(row: any) { this.$router.push({ path: `productDetail/${row.id}/view` }) }
-
详情页的数据加载: 在
productDetail
组件 (即src/views/product/detail.vue
) 中,mounted
钩子函数会根据路由参数中的id
和operateType
来决定是查看详情还是编辑。当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
中定义) 向后端发送请求,获取产品详情数据。 -
数据的显示: 在
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
这个方法。
以下是完整的逻辑链条:
-
点击事件: 当用户在产品列表页面点击主图时,会触发
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>
-
路由跳转:
handleView(row)
方法内部使用this.$router.push
进行路由跳转,跳转到产品详情页:public handleView(row: any) { this.$router.push({ path: `productDetail/${row.id}/view` }) }
-
组件挂载: 跳转到
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() } } }
-
获取详情: 在
mounted
钩子函数中,通过判断this.id
是否大于 0(即是否为有效的产品ID)以及this.operateType
是否为view
(即查看模式),决定是否调用getproductDetail
方法获取产品详情。由于handleView
传递了row.id
和view
,所以这两个条件都满足,getproductDetail
方法会被调用。 -
发送请求:
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) } }
-
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.image
为null
或空字符串时,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.image
和 form.image
都是通过后端 API 获取到的,具体的值取决于后端如何存储和返回图片信息。通常情况下,row.image
和 form.image
保存的是图片的相对路径或文件名,需要拼接上前缀(如 oss
)才能在浏览器中显示。