| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- <template>
- <el-drawer
- :title="'商品详情 · ' + (detail.goodsName || detail.goodsSn || '')"
- :visible.sync="localVisible"
- direction="rtl"
- size="72%"
- append-to-body
- custom-class="detail-drawer"
- >
- <div v-loading="loading" class="drawer-content">
- <h4 class="section-header">基础信息</h4>
- <el-descriptions :column="2" border size="small" class="mb16">
- <el-descriptions-item label="商品编号">{{ detail.goodsSn || '—' }}</el-descriptions-item>
- <el-descriptions-item label="商品状态">
- <el-tag size="small" :type="goodsStatusTag(detail.goodsStatus)">{{ goodsStatusLabel(detail.goodsStatus) }}</el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="商品名称" :span="2">{{ detail.goodsName || '—' }}</el-descriptions-item>
- <el-descriptions-item label="售价">{{ detail.salePrice != null ? detail.salePrice : '—' }}</el-descriptions-item>
- <el-descriptions-item label="库存">{{ detail.stock != null ? detail.stock : '—' }}</el-descriptions-item>
- <el-descriptions-item label="销量">{{ detail.salesCount != null ? detail.salesCount : '—' }}</el-descriptions-item>
- <el-descriptions-item label="主图">
- <image-preview v-if="detail.mainPic" :src="detail.mainPic" :width="80" :height="80" />
- <span v-else>—</span>
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.subPics && detail.subPics.length" label="副图" :span="2">
- <div class="sub-pics-row">
- <image-preview
- v-for="(pic, idx) in detail.subPics"
- :key="idx"
- :src="pic"
- :width="60"
- :height="60"
- class="sub-pic-item"
- />
- </div>
- </el-descriptions-item>
- </el-descriptions>
- <h4 class="section-header">分类信息</h4>
- <el-descriptions :column="1" border size="small" class="mb16">
- <el-descriptions-item label="商品分类">{{ detail.categoryPath || '—' }}</el-descriptions-item>
- <el-descriptions-item label="店铺商品分类">{{ detail.shopCategoryPath || detail.shopCategoryName || '—' }}</el-descriptions-item>
- <el-descriptions-item label="属性模版">{{ detail.attrTemplateName || '—' }}</el-descriptions-item>
- </el-descriptions>
- <h4 v-if="hasAttrList(detail.attributes)" class="section-header">商品属性</h4>
- <el-table v-if="hasAttrList(detail.attributes)" border size="small" :data="detail.attributes" class="mb16">
- <el-table-column label="属性名" prop="itemName" width="120" />
- <el-table-column label="属性值">
- <template slot-scope="scope">
- <span>{{ formatAttrValues(scope.row.values) }}</span>
- </template>
- </el-table-column>
- </el-table>
- <h4 class="section-header">配送运费</h4>
- <el-descriptions :column="2" border size="small" class="mb16">
- <el-descriptions-item label="运费方式">{{ freightTypeLabel(detail.freightType) }}</el-descriptions-item>
- <el-descriptions-item v-if="detail.freightType === '1'" label="固定金额">
- {{ detail.fixedFreightAmount != null ? detail.fixedFreightAmount : '—' }}
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.freightType === '2'" label="运费模版">
- {{ detail.freightTemplateName || '—' }}
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.freightType === '2' && detail.freightDesc" label="运费说明" :span="2">
- {{ detail.freightDesc }}
- </el-descriptions-item>
- </el-descriptions>
- <h4 v-if="hasAttrList(detail.specs)" class="section-header">商品规格</h4>
- <el-table v-if="hasAttrList(detail.specs)" border size="small" :data="detail.specs" class="mb16">
- <el-table-column label="规格名" prop="itemName" width="120" />
- <el-table-column label="规格值">
- <template slot-scope="scope">
- <span>{{ formatAttrValues(scope.row.values) }}</span>
- </template>
- </el-table-column>
- </el-table>
- <h4 class="section-header">状态信息</h4>
- <el-descriptions :column="2" border size="small" class="mb16">
- <el-descriptions-item label="提交时间">{{ parseTime(detail.submitTime) || '—' }}</el-descriptions-item>
- <el-descriptions-item label="审核时间">{{ parseTime(detail.auditTime) || '—' }}</el-descriptions-item>
- <el-descriptions-item v-if="detail.goodsStatus === '3'" label="驳回原因" :span="2">
- <span class="reject-reason">{{ detail.rejectReason || '—' }}</span>
- </el-descriptions-item>
- <el-descriptions-item v-if="detail.goodsStatus === '4'" label="下架时间">{{ parseTime(detail.offShelfTime) || '—' }}</el-descriptions-item>
- </el-descriptions>
- <h4 class="section-header">商品服务快照</h4>
- <el-table v-if="detail.services && detail.services.length" border size="small" :data="detail.services" class="mb16">
- <el-table-column label="服务名称" prop="serviceName" />
- <el-table-column label="简介" prop="serviceIntro" :show-overflow-tooltip="true" />
- <el-table-column label="图标" width="80">
- <template slot-scope="scope">
- <image-preview :src="scope.row.serviceIcon" :width="40" :height="40" />
- </template>
- </el-table-column>
- </el-table>
- <div v-else class="empty-tip mb16">暂无勾选服务项</div>
- <h4 v-if="detail.detailContent" class="section-header">商品详情</h4>
- <div v-if="detail.detailContent" class="detail-content mb16" v-html="detail.detailContent"></div>
- <div class="action-bar">
- <el-button v-if="canShowEdit" type="primary" plain @click="handleEdit" v-hasPermi="['agri:seller:goods:edit']">编辑</el-button>
- <el-button v-if="detail.canSubmit" type="success" @click="handleSubmit" v-hasPermi="['agri:seller:goods:edit']">提交上架</el-button>
- <el-button v-if="detail.canOffShelf" type="warning" plain @click="handleOffShelf" v-hasPermi="['agri:seller:goods:offshelf']">下架</el-button>
- <el-button v-if="detail.canDelete" type="danger" plain @click="handleDelete" v-hasPermi="['agri:seller:goods:remove']">删除</el-button>
- </div>
- </div>
- </el-drawer>
- </template>
- <script>
- import {
- getSellerGoods,
- submitSellerGoods,
- offShelfSellerGoods,
- delSellerGoods
- } from "@/api/agri/seller/goods"
- export default {
- name: "SellerGoodsDetail",
- props: {
- visible: { type: Boolean, default: false },
- goodsId: { type: [Number, String], default: null }
- },
- data() {
- return {
- localVisible: false,
- loading: false,
- detail: {}
- }
- },
- computed: {
- /** 未上架 / 审核失败 / 已下架可编辑;优先用后端 canEdit */
- canShowEdit() {
- if (this.detail.canEdit === true) return true
- if (this.detail.canEdit === false) return false
- const status = this.detail.goodsStatus
- return status === "0" || status === "3" || status === "4"
- }
- },
- watch: {
- visible(val) {
- this.localVisible = val
- if (val && this.goodsId) {
- this.loadDetail()
- }
- },
- localVisible(val) {
- this.$emit("update:visible", val)
- }
- },
- methods: {
- /** 加载商品详情 */
- loadDetail() {
- this.loading = true
- getSellerGoods(this.goodsId).then(response => {
- this.detail = response.data || {}
- this.loading = false
- }).catch(() => {
- this.loading = false
- })
- },
- goodsStatusLabel(status) {
- const map = { "0": "未上架", "1": "待审核", "2": "出售中", "3": "审核失败", "4": "已下架" }
- return map[status] || this.detail.goodsStatusLabel || "—"
- },
- goodsStatusTag(status) {
- const map = { "0": "", "1": "warning", "2": "success", "3": "danger", "4": "info" }
- return map[status] || "info"
- },
- freightTypeLabel(type) {
- const map = { "1": "固定运费", "2": "运费模版" }
- return map[type] || "—"
- },
- /** 是否有属性/规格项 */
- hasAttrList(list) {
- return list && list.length > 0
- },
- /** 格式化属性值列表 */
- formatAttrValues(values) {
- if (!values || !values.length) {
- return "—"
- }
- return values.join("、")
- },
- /** 跳转编辑 */
- handleEdit() {
- if (!this.canShowEdit) {
- this.$modal.msgWarning("当前状态不可编辑;出售中须先下架,待审核须等待平台审核结果")
- return
- }
- this.$emit("edit", this.detail)
- this.localVisible = false
- },
- /** 提交上架 */
- handleSubmit() {
- this.$modal.confirm("确认提交上架该商品?").then(() => {
- return submitSellerGoods(this.goodsId)
- }).then(response => {
- const data = response.data || {}
- const label = data.goodsStatusLabel || "操作成功"
- this.$modal.msgSuccess("提交成功,当前状态:" + label)
- this.localVisible = false
- this.$emit("success")
- }).catch(() => {})
- },
- /** 下架 */
- handleOffShelf() {
- this.$modal.confirm("下架后 C 端不可购买,是否继续?").then(() => {
- return offShelfSellerGoods(this.goodsId)
- }).then(() => {
- this.$modal.msgSuccess("下架成功")
- this.localVisible = false
- this.$emit("success")
- }).catch(() => {})
- },
- /** 删除 */
- handleDelete() {
- this.$modal.confirm("确认删除该商品?删除后不可恢复。").then(() => {
- return delSellerGoods(this.goodsId)
- }).then(() => {
- this.$modal.msgSuccess("删除成功")
- this.localVisible = false
- this.$emit("success")
- }).catch(() => {})
- }
- }
- }
- </script>
- <style scoped>
- .drawer-content {
- padding: 0 20px 20px;
- }
- .section-header {
- margin: 16px 0 10px;
- font-size: 15px;
- color: #303133;
- border-left: 3px solid #409EFF;
- padding-left: 8px;
- }
- .mb16 {
- margin-bottom: 16px;
- }
- .reject-reason {
- color: #F56C6C;
- }
- .empty-tip {
- color: #909399;
- font-size: 13px;
- }
- .detail-content {
- padding: 12px;
- background: #fafafa;
- border-radius: 4px;
- line-height: 1.6;
- }
- .action-bar {
- margin-top: 24px;
- padding-top: 16px;
- border-top: 1px solid #EBEEF5;
- }
- .sub-pics-row {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- }
- .sub-pic-item {
- flex-shrink: 0;
- }
- </style>
|