632 lines
22 KiB
Vue
632 lines
22 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||
<el-form-item label="商品名称" prop="productName">
|
||
<el-input
|
||
v-model="queryParams.productName"
|
||
placeholder="请输入商品名称"
|
||
clearable
|
||
@keyup.enter.native="handleQuery"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="店铺名称" prop="shopName">
|
||
<el-input
|
||
v-model="queryParams.shopName"
|
||
placeholder="请输入店铺名称"
|
||
clearable
|
||
@keyup.enter.native="handleQuery"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="SKUID" prop="skuid">
|
||
<el-input
|
||
v-model="queryParams.skuid"
|
||
placeholder="请输入SKUID"
|
||
clearable
|
||
@keyup.enter.native="handleQuery"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="是否置顶" prop="isTop">
|
||
<el-select v-model="queryParams.isTop" placeholder="请选择" clearable>
|
||
<el-option label="是" :value="1" />
|
||
<el-option label="否" :value="0" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<el-row :gutter="10" class="mb8">
|
||
<el-col :span="1.5">
|
||
<el-button
|
||
type="primary"
|
||
plain
|
||
icon="el-icon-plus"
|
||
size="mini"
|
||
@click="handleAdd"
|
||
v-hasPermi="['jarvis:favoriteProduct:add']"
|
||
>新增</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button
|
||
type="success"
|
||
plain
|
||
icon="el-icon-edit"
|
||
size="mini"
|
||
:disabled="single"
|
||
@click="handleUpdate"
|
||
v-hasPermi="['jarvis:favoriteProduct:edit']"
|
||
>修改</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button
|
||
type="danger"
|
||
plain
|
||
icon="el-icon-delete"
|
||
size="mini"
|
||
:disabled="multiple"
|
||
@click="handleDelete"
|
||
v-hasPermi="['jarvis:favoriteProduct:remove']"
|
||
>删除</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button
|
||
type="warning"
|
||
plain
|
||
icon="el-icon-top"
|
||
size="mini"
|
||
:disabled="multiple"
|
||
@click="handleBatchTop"
|
||
v-hasPermi="['jarvis:favoriteProduct:edit']"
|
||
>批量置顶</el-button>
|
||
</el-col>
|
||
<el-col :span="1.5">
|
||
<el-button
|
||
type="info"
|
||
plain
|
||
icon="el-icon-download"
|
||
size="mini"
|
||
@click="handleExport"
|
||
v-hasPermi="['jarvis:favoriteProduct:export']"
|
||
>导出</el-button>
|
||
</el-col>
|
||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||
</el-row>
|
||
|
||
<el-table v-loading="loading" :data="favoriteProductList" @selection-change="handleSelectionChange">
|
||
<el-table-column type="selection" width="55" align="center" />
|
||
<el-table-column label="商品图片" align="center" prop="productImage" width="100">
|
||
<template slot-scope="scope">
|
||
<el-image
|
||
v-if="scope.row.productImage"
|
||
:src="scope.row.productImage"
|
||
:preview-src-list="[scope.row.productImage]"
|
||
style="width: 60px; height: 60px; border-radius: 4px;"
|
||
fit="cover"
|
||
/>
|
||
<span v-else>-</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="商品名称" align="left" prop="productName" min-width="200" :show-overflow-tooltip="true">
|
||
<template slot-scope="scope">
|
||
<div>
|
||
<div style="font-weight: bold; margin-bottom: 5px;">
|
||
<el-tag v-if="scope.row.isTop === 1" type="danger" size="mini">置顶</el-tag>
|
||
{{ scope.row.productName }}
|
||
</div>
|
||
<div style="color: #666; font-size: 12px;">
|
||
SKUID: {{ scope.row.skuid }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="店铺信息" align="left" prop="shopName" min-width="150">
|
||
<template slot-scope="scope">
|
||
<div>
|
||
<div>{{ scope.row.shopName }}</div>
|
||
<div style="color: #666; font-size: 12px;">ID: {{ scope.row.shopId }}</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="价格信息" align="center" prop="price" width="120">
|
||
<template slot-scope="scope">
|
||
<div>
|
||
<div style="color: #f56c6c; font-weight: bold;">¥{{ scope.row.price || '-' }}</div>
|
||
<div v-if="scope.row.commissionInfo" style="color: #67c23a; font-size: 12px;">
|
||
佣金: {{ scope.row.commissionInfo }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="ERP商品" align="center" prop="erpProductIds" width="120">
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
v-if="scope.row.erpProductIds"
|
||
type="text"
|
||
size="mini"
|
||
@click="showErpProducts(scope.row)"
|
||
>
|
||
查看({{ JSON.parse(scope.row.erpProductIds || '[]').length }})
|
||
</el-button>
|
||
<span v-else>-</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="使用统计" align="center" width="120">
|
||
<template slot-scope="scope">
|
||
<div>
|
||
<div>使用: {{ scope.row.useCount || 0 }}次</div>
|
||
<div style="color: #666; font-size: 12px;">
|
||
{{ scope.row.lastUsedTime || '未使用' }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="创建信息" align="center" width="150">
|
||
<template slot-scope="scope">
|
||
<div>
|
||
<div>{{ scope.row.createUserName }}</div>
|
||
<div style="color: #666; font-size: 12px;">
|
||
{{ parseTime(scope.row.createTime) }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
icon="el-icon-view"
|
||
@click="handleView(scope.row)"
|
||
>查看</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
icon="el-icon-edit"
|
||
@click="handleUpdate(scope.row)"
|
||
v-hasPermi="['jarvis:favoriteProduct:edit']"
|
||
>修改</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
icon="el-icon-top"
|
||
@click="handleTop(scope.row)"
|
||
v-hasPermi="['jarvis:favoriteProduct:edit']"
|
||
>
|
||
{{ scope.row.isTop === 1 ? '取消置顶' : '置顶' }}
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
icon="el-icon-shopping-cart-2"
|
||
@click="handleQuickPublish(scope.row)"
|
||
>快速发品</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="text"
|
||
icon="el-icon-delete"
|
||
@click="handleDelete(scope.row)"
|
||
v-hasPermi="['jarvis:favoriteProduct:remove']"
|
||
>删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<pagination
|
||
v-show="total>0"
|
||
:total="total"
|
||
:page.sync="queryParams.pageNum"
|
||
:limit.sync="queryParams.pageSize"
|
||
@pagination="getList"
|
||
/>
|
||
|
||
<!-- 添加或修改常用商品对话框 -->
|
||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="SKUID" prop="skuid">
|
||
<el-input v-model="form.skuid" placeholder="请输入SKUID" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品名称" prop="productName">
|
||
<el-input v-model="form.productName" placeholder="请输入商品名称" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="店铺名称" prop="shopName">
|
||
<el-input v-model="form.shopName" placeholder="请输入店铺名称" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="店铺ID" prop="shopId">
|
||
<el-input v-model="form.shopId" placeholder="请输入店铺ID" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品链接" prop="productUrl">
|
||
<el-input v-model="form.productUrl" placeholder="请输入商品链接" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品图片" prop="productImage">
|
||
<el-input v-model="form.productImage" placeholder="请输入商品图片URL" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品价格" prop="price">
|
||
<el-input v-model="form.price" placeholder="请输入商品价格" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="佣金信息" prop="commissionInfo">
|
||
<el-input v-model="form.commissionInfo" placeholder="请输入佣金信息" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品分类" prop="category">
|
||
<el-input v-model="form.category" placeholder="请输入商品分类" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="商品品牌" prop="brand">
|
||
<el-input v-model="form.brand" placeholder="请输入商品品牌" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<el-form-item label="是否置顶" prop="isTop">
|
||
<el-radio-group v-model="form.isTop">
|
||
<el-radio :label="1">是</el-radio>
|
||
<el-radio :label="0">否</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="排序权重" prop="sortWeight">
|
||
<el-input-number v-model="form.sortWeight" :min="0" :max="999" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||
<el-button @click="cancel">取 消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- ERP商品详情对话框 -->
|
||
<el-dialog title="ERP商品详情" :visible.sync="erpDialogVisible" width="800px" append-to-body>
|
||
<el-table :data="erpProducts" border style="width: 100%">
|
||
<el-table-column label="ERP应用ID" prop="appid" width="120" />
|
||
<el-table-column label="ERP商品ID" prop="erpProductId" width="120" />
|
||
<el-table-column label="商品标题" prop="erpProductTitle" min-width="200" :show-overflow-tooltip="true" />
|
||
<el-table-column label="商品状态" prop="erpProductStatus" width="100">
|
||
<template slot-scope="scope">
|
||
<el-tag :type="scope.row.erpProductStatus === 'active' ? 'success' : 'info'">
|
||
{{ scope.row.erpProductStatus === 'active' ? '正常' : '其他' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="商品链接" prop="erpProductUrl" min-width="200">
|
||
<template slot-scope="scope">
|
||
<el-link :href="scope.row.erpProductUrl" target="_blank" type="primary">
|
||
查看商品
|
||
</el-link>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="备注" prop="remark" width="120" />
|
||
</el-table>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button @click="erpDialogVisible = false">关 闭</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
|
||
|
||
<!-- 通用发品对话框:从常用商品直接进入,不显示ERP应用选择 -->
|
||
<PublishDialog :visible.sync="publishDialogVisible" :initial-data="publishInitialData" :hideAppid="true" />
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { listFavoriteProduct, getFavoriteProduct, delFavoriteProduct, addFavoriteProduct, updateFavoriteProduct, updateTopStatus } from "@/api/system/favoriteProduct";
|
||
import { generatePromotionContent } from "@/api/system/jdorder";
|
||
import { mapGetters, mapActions } from 'vuex'
|
||
import PublishDialog from '@/components/PublishDialog.vue'
|
||
// 自动加入常用逻辑由 PublishDialog 内部触发(线报、转链页面),本页主要用于打开发品弹窗
|
||
|
||
export default {
|
||
name: "FavoriteProduct",
|
||
components: { PublishDialog },
|
||
computed: {
|
||
...mapGetters(['favoriteProductRefreshKey'])
|
||
},
|
||
data() {
|
||
return {
|
||
// 遮罩层
|
||
loading: true,
|
||
// 选中数组
|
||
ids: [],
|
||
// 非单个禁用
|
||
single: true,
|
||
// 非多个禁用
|
||
multiple: true,
|
||
// 显示搜索条件
|
||
showSearch: true,
|
||
// 总条数
|
||
total: 0,
|
||
// 常用商品表格数据
|
||
favoriteProductList: [],
|
||
// 弹出层标题
|
||
title: "",
|
||
// 是否显示弹出层
|
||
open: false,
|
||
// 查询参数
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
productName: null,
|
||
shopName: null,
|
||
skuid: null,
|
||
isTop: null
|
||
},
|
||
// 表单参数
|
||
form: {},
|
||
// 表单校验
|
||
rules: {
|
||
skuid: [
|
||
{ required: true, message: "SKUID不能为空", trigger: "blur" }
|
||
],
|
||
productName: [
|
||
{ required: true, message: "商品名称不能为空", trigger: "blur" }
|
||
],
|
||
shopName: [
|
||
{ required: true, message: "店铺名称不能为空", trigger: "blur" }
|
||
]
|
||
},
|
||
// ERP商品对话框
|
||
erpDialogVisible: false,
|
||
erpProducts: [],
|
||
|
||
// 通用发品弹窗
|
||
publishDialogVisible: false,
|
||
publishInitialData: {}
|
||
};
|
||
},
|
||
created() {
|
||
this.getList();
|
||
},
|
||
watch: {
|
||
favoriteProductRefreshKey() {
|
||
// 全局刷新标记变更时,自动刷新列表
|
||
this.getList();
|
||
}
|
||
},
|
||
methods: {
|
||
/** 查询常用商品列表 */
|
||
getList() {
|
||
this.loading = true;
|
||
listFavoriteProduct(this.queryParams).then(response => {
|
||
this.favoriteProductList = response.rows;
|
||
this.total = response.total;
|
||
this.loading = false;
|
||
});
|
||
},
|
||
// 取消按钮
|
||
cancel() {
|
||
this.open = false;
|
||
this.reset();
|
||
},
|
||
// 表单重置
|
||
reset() {
|
||
this.form = {
|
||
id: null,
|
||
skuid: null,
|
||
productName: null,
|
||
shopName: null,
|
||
shopId: null,
|
||
productUrl: null,
|
||
productImage: null,
|
||
price: null,
|
||
commissionInfo: null,
|
||
isTop: 0,
|
||
sortWeight: 0,
|
||
remark: null,
|
||
category: null,
|
||
brand: null
|
||
};
|
||
this.resetForm("form");
|
||
},
|
||
/** 搜索按钮操作 */
|
||
handleQuery() {
|
||
this.queryParams.pageNum = 1;
|
||
this.getList();
|
||
},
|
||
/** 重置按钮操作 */
|
||
resetQuery() {
|
||
this.resetForm("queryForm");
|
||
this.handleQuery();
|
||
},
|
||
// 多选框选中数据
|
||
handleSelectionChange(selection) {
|
||
this.ids = selection.map(item => item.id)
|
||
this.single = selection.length!==1
|
||
this.multiple = !selection.length
|
||
},
|
||
/** 新增按钮操作 */
|
||
handleAdd() {
|
||
this.reset();
|
||
this.open = true;
|
||
this.title = "添加常用商品";
|
||
},
|
||
/** 修改按钮操作 */
|
||
handleUpdate(row) {
|
||
this.reset();
|
||
const id = row.id || this.ids
|
||
getFavoriteProduct(id).then(response => {
|
||
this.form = response.data;
|
||
this.open = true;
|
||
this.title = "修改常用商品";
|
||
});
|
||
},
|
||
/** 查看按钮操作 */
|
||
handleView(row) {
|
||
this.reset();
|
||
const id = row.id || this.ids
|
||
getFavoriteProduct(id).then(response => {
|
||
this.form = response.data;
|
||
this.open = true;
|
||
this.title = "查看常用商品";
|
||
// 设置为只读
|
||
this.$nextTick(() => {
|
||
Object.keys(this.form).forEach(key => {
|
||
const input = this.$refs.form.$el.querySelector(`[name="${key}"]`);
|
||
if (input) {
|
||
input.disabled = true;
|
||
}
|
||
});
|
||
});
|
||
});
|
||
},
|
||
/** 提交按钮 */
|
||
submitForm() {
|
||
this.$refs["form"].validate(valid => {
|
||
if (valid) {
|
||
if (this.form.id != null) {
|
||
updateFavoriteProduct(this.form).then(response => {
|
||
this.$modal.msgSuccess("修改成功");
|
||
this.open = false;
|
||
this.getList();
|
||
});
|
||
} else {
|
||
addFavoriteProduct(this.form).then(response => {
|
||
this.$modal.msgSuccess("新增成功");
|
||
this.open = false;
|
||
this.getList();
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
/** 删除按钮操作 */
|
||
handleDelete(row) {
|
||
const ids = row.id || this.ids;
|
||
this.$modal.confirm('是否确认删除常用商品编号为"' + ids + '"的数据项?').then(function() {
|
||
return delFavoriteProduct(ids);
|
||
}).then(() => {
|
||
this.getList();
|
||
this.$modal.msgSuccess("删除成功");
|
||
}).catch(() => {});
|
||
},
|
||
/** 置顶按钮操作 */
|
||
handleTop(row) {
|
||
const isTop = row.isTop === 1 ? 0 : 1;
|
||
const action = isTop === 1 ? '置顶' : '取消置顶';
|
||
this.$modal.confirm('是否确认' + action + '商品"' + row.productName + '"?').then(function() {
|
||
return updateTopStatus(row.id, isTop);
|
||
}).then(() => {
|
||
this.getList();
|
||
this.$modal.msgSuccess(action + "成功");
|
||
}).catch(() => {});
|
||
},
|
||
/** 批量置顶操作 */
|
||
handleBatchTop() {
|
||
this.$modal.confirm('是否确认批量置顶选中的商品?').then(function() {
|
||
// 这里需要调用批量置顶接口
|
||
return Promise.resolve();
|
||
}).then(() => {
|
||
this.getList();
|
||
this.$modal.msgSuccess("批量置顶成功");
|
||
}).catch(() => {});
|
||
},
|
||
/** 导出按钮操作 */
|
||
handleExport() {
|
||
this.download('jarvis/favoriteProduct/export', {
|
||
...this.queryParams
|
||
}, `favoriteProduct_${new Date().getTime()}.xlsx`)
|
||
},
|
||
/** 显示ERP商品详情 */
|
||
showErpProducts(row) {
|
||
try {
|
||
this.erpProducts = JSON.parse(row.erpProductIds || '[]');
|
||
this.erpDialogVisible = true;
|
||
} catch (e) {
|
||
this.$modal.msgError("ERP商品数据格式错误");
|
||
}
|
||
},
|
||
/** 快速发品 */
|
||
handleQuickPublish(row) {
|
||
const id = row.id || this.ids;
|
||
getFavoriteProduct(id).then(async res => {
|
||
const p = res && res.data ? res.data : (row || {});
|
||
try {
|
||
// 与转链保持一致:优先使用保存的商品链接,避免用名称/ID 产生歧义
|
||
if (!p.productUrl) {
|
||
this.$modal.msgWarning('该常用商品缺少商品链接,无法生成完整发品信息');
|
||
}
|
||
let detail = null;
|
||
if (p.productUrl) {
|
||
const r = await generatePromotionContent({ promotionContent: p.productUrl });
|
||
const resultStr = (r && (r.msg || r.data)) || '';
|
||
try { const arr = typeof resultStr === 'string' ? JSON.parse(resultStr) : resultStr; if (Array.isArray(arr) && arr.length) detail = arr[0]; } catch(e) {}
|
||
}
|
||
const images = Array.isArray(detail && detail.images) && detail.images.length ? detail.images : (p.productImage ? [p.productImage] : []);
|
||
const wenanArr = Array.isArray(detail && detail.wenan) ? detail.wenan : [];
|
||
const wenanOptions = wenanArr.map((w, i) => ({ label: w.type || `版本${i+1}` , content: w.content || '' }));
|
||
this.publishInitialData = {
|
||
title: (detail && (detail.skuName || detail.title)) || p.productName || '',
|
||
content: (wenanOptions[0] && wenanOptions[0].content) || '',
|
||
images: images,
|
||
originalPrice: detail && detail.price ? Number(detail.price) : (p.price ? Number(p.price) : undefined),
|
||
wenanOptions: wenanOptions,
|
||
userName: p.userName || '',
|
||
province: p.province || null,
|
||
city: p.city || null,
|
||
district: p.district || null
|
||
};
|
||
this.publishDialogVisible = true;
|
||
} catch (e) {
|
||
const imagesFallback = p.productImage ? [p.productImage] : [];
|
||
this.publishInitialData = { title: p.productName || '', images: imagesFallback, content: '' };
|
||
this.publishDialogVisible = true;
|
||
}
|
||
}).catch(() => {
|
||
const images = row && row.productImage ? [row.productImage] : [];
|
||
this.publishInitialData = { title: row.productName || '', images, content: '' };
|
||
this.publishDialogVisible = true;
|
||
});
|
||
},
|
||
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.mb8 {
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.el-table .el-table__row:hover {
|
||
background-color: #f5f7fa;
|
||
}
|
||
|
||
.el-tag {
|
||
margin-right: 5px;
|
||
}
|
||
</style>
|