<template>
|
<div class="app-container">
|
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="80px">
|
<el-form-item label="商品名称" prop="goodsName">
|
<el-input v-model="queryParams.goodsName" placeholder="请输入商品名称" style="width: 200px" />
|
</el-form-item>
|
<el-form-item label="商品分类" prop="goodsClass">
|
<el-cascader :props="goodsClassify.props" v-model="goodsClassify.classifysAdd" clearable @change="onClassifyChange()" style="width: 200px" />
|
</el-form-item>
|
<el-form-item label="状态" prop="shopState">
|
<el-select v-model="queryParams.shopState" placeholder="状态" clearable style="width: 200px">
|
<el-option :key="0" label="全部" value="" />
|
<el-option :key="1" label="上架" value="1" />
|
<el-option :key="2" label="下架" value="2" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="出售状态" prop="saleState">
|
<el-select v-model="queryParams.saleState" placeholder="出售状态" clearable style="width: 200px">
|
<el-option :key="0" label="全部" value="" />
|
<el-option :key="1" label="在售" value="1" />
|
<el-option :key="2" label="已售" value="2" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" icon="Search" @click="getDataList">搜索</el-button>
|
<el-button icon="Refresh" @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="Plus" :disabled="power.add" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
|
</el-col>
|
<el-col :span="1.5">
|
<el-button type="danger" plain icon="Delete" :disabled="power.multiple" @click="handleDelete()" v-hasPermi="['system:role:remove']">删除</el-button>
|
</el-col>
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getDataList"></right-toolbar>
|
</el-row>
|
<el-table v-loading="tableOption.loading" :data="dataTable" @selection-change="handleSelectionChange" @cell-dblclick="handleInfo">
|
<el-table-column type="selection" width="50" align="center" />
|
<el-table-column label="缩略图" align="center">
|
<template #default="scope">
|
<div class="custom-img">
|
<el-image :src="baseUrl + scope.row.goodsImg" fit="contain"> </el-image>
|
</div>
|
</template>
|
</el-table-column>
|
<el-table-column label="商品名称" align="center" key="goodsName" prop="goodsName" />
|
<el-table-column label="商品分类" align="center" key="goodsClass" prop="goodsClass" />
|
<el-table-column label="编码" align="center" key="goodsCode" prop="goodsCode" />
|
<!-- <el-table-column label="产地" align="center" key="goodsPlace" prop="goodsPlace" /> -->
|
<el-table-column label="售价" align="center" key="goodsPrice" prop="goodsPrice" />
|
<el-table-column label="出售状态" align="center">
|
<template #default="scope">
|
<span>{{ scope.row.saleState == 1 ? "在售" : "已售" }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="状态" align="center">
|
<template #default="scope">
|
<span>{{ scope.row.shopState == 1 ? "上架" : "下架" }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="排序" align="center" key="sortNum" prop="sortNum" />
|
<!-- <el-table-column label="创建人" align="center" key="createName" prop="createName" width="120" />
|
<el-table-column label="创建时间" align="center" key="createTime" prop="createTime" width="170" /> -->
|
<el-table-column label="操作" align="center" width="120">
|
<template #default="scope">
|
<el-tooltip content="修改" placement="top">
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
</el-tooltip>
|
<el-tooltip content="删除" placement="top">
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button>
|
</el-tooltip>
|
</template>
|
</el-table-column>
|
</el-table>
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getDataList" />
|
|
<el-dialog title="商品详情" v-model="isOpenInfo" width="1200px" draggable :close-on-click-modal="false">
|
<el-descriptions :column="3">
|
<el-descriptions-item label="商品名称">{{ dataInfo.goodsName }}</el-descriptions-item>
|
<el-descriptions-item label="商品分类">{{ dataInfo.goodsClass }}</el-descriptions-item>
|
<el-descriptions-item label="商品编码">{{ dataInfo.goodsCode }}</el-descriptions-item>
|
|
<el-descriptions-item label="指圈圈口" v-if="dataInfo.classCode1 == '104'">{{ dataInfo.fingerSize }}</el-descriptions-item>
|
<el-descriptions-item label="手镯圈口" v-if="dataInfo.classCode1 == '101'">{{ dataInfo.handSize }}</el-descriptions-item>
|
|
<el-descriptions-item label="颜色类型"> {{ dispDictLabel(color_code, dataInfo.colorCode) }}</el-descriptions-item>
|
<el-descriptions-item label="瑕疵类型"> {{ dispDictLabel(flaw_code, dataInfo.flawCode) }} </el-descriptions-item>
|
<el-descriptions-item label="镶嵌类型"> {{ dispDictLabel(inset_code, dataInfo.insetCode) }} </el-descriptions-item>
|
<el-descriptions-item label="种"> {{ dispDictLabel(var_code, dataInfo.varCode) }} </el-descriptions-item>
|
<el-descriptions-item label="水"> {{ dispDictLabel(lucency_code, dataInfo.lucencyCode) }}</el-descriptions-item>
|
|
<el-descriptions-item label="商品原价">{{ dataInfo.marketPrice }}</el-descriptions-item>
|
<el-descriptions-item label="商品售价">{{ dataInfo.goodsPrice }}</el-descriptions-item>
|
<el-descriptions-item label="商品plus价">{{ dataInfo.plusPrice }}</el-descriptions-item>
|
<el-descriptions-item label="商品会员价">{{ dataInfo.vipPrice }}</el-descriptions-item>
|
|
<el-descriptions-item label="重量">{{ dataInfo.goodsWeight }}</el-descriptions-item>
|
<el-descriptions-item label="产地">{{ dataInfo.goodsPlace }}</el-descriptions-item>
|
<el-descriptions-item label="出售状态">{{ dataInfo.saleState == 1 ? "在售" : "已售" }}</el-descriptions-item>
|
<el-descriptions-item label="官网显示">{{ dataInfo.webState == 1 ? "是" : "否" }}</el-descriptions-item>
|
<el-descriptions-item label="状态">{{ dataInfo.shopState == 1 ? "上架" : "下架" }}</el-descriptions-item>
|
<el-descriptions-item label="排序">{{ dataInfo.sortNum }}</el-descriptions-item>
|
<el-descriptions-item label="备注">{{ dataInfo.remark }}</el-descriptions-item>
|
</el-descriptions>
|
|
<el-descriptions :column="1">
|
<el-descriptions-item label="商品主图">
|
<div style="width: 120px; height: 120px"><el-image :src="baseUrl + dataInfo.goodsImg" fit="contain"> </el-image></div>
|
</el-descriptions-item>
|
<el-descriptions-item label="商品轮播图">
|
<div>
|
<div
|
style="width: 120px; height: 120px; display: inline-block; margin-left: 5px"
|
v-for="item in inImageUrlToList(dataInfo.goodsBanner)"
|
:key="item.url"
|
>
|
<el-image :src="baseUrl + item.url" fit="contain" v-if="checkFileType(item.type) == 1"> </el-image>
|
<video :src="baseUrl + item.url" v-else></video>
|
</div>
|
</div>
|
</el-descriptions-item>
|
<el-descriptions-item label="商品详情图">
|
<div>
|
<div
|
style="width: 120px; height: 120px; display: inline-block; margin-left: 5px"
|
v-for="item in inImageUrlToList(dataInfo.goodsDetail)"
|
:key="item.url"
|
>
|
<el-image :src="baseUrl + item.url" fit="contain"> </el-image>
|
</div>
|
</div>
|
</el-descriptions-item>
|
</el-descriptions>
|
</el-dialog>
|
</div>
|
</template>
|
<script setup lang="ts">
|
import { reactive, onMounted, toRefs, getCurrentInstance, ref } from "vue";
|
import { getGoodsInfo, getGoodsList, updateGoods, deleteGoods } from "@/api/goods/goods";
|
import { getClassThreeList } from "@/api/goods/classify";
|
import { goodsDTO, TypeGoodsDTO, TypeGoodsInfoDTO } from "@/types/DTO/goodsDTO";
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
import type { CascaderProps } from "element-plus";
|
import { useRouter } from "vue-router";
|
const router = useRouter();
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
const { flaw_code, inset_code, color_code, var_code, lucency_code } = proxy.useDict("flaw_code", "inset_code", "color_code", "var_code", "lucency_code");
|
|
const ids = ref<number[]>([]);
|
const state = reactive({
|
dataTable: [] as TypeGoodsInfoDTO[], //数据列表
|
dataInfo: {} as TypeGoodsInfoDTO, //数据详情
|
total: 0, //总条数
|
tableOption: {
|
//表格配置
|
loading: false,
|
},
|
power: {
|
//操作权限
|
add: false,
|
single: false, //
|
multiple: true, //
|
},
|
showSearch: true, //是否显示搜索
|
showAddGoods: false, //是否显示新增
|
isOpenSeletGoods: false, //是否显示选择商品
|
isOpenInfo: false, //是否显示商品详情
|
});
|
const { dataTable, total, tableOption, power, showSearch, dataInfo, isOpenInfo } = toRefs(state);
|
|
onMounted(() => {
|
getDataList();
|
});
|
|
//#region 查询
|
|
const queryRef = ref<Omit<Common.formDataType, "formRef">>();
|
const queryParams = reactive({
|
//查询配置参数
|
pageNum: 1,
|
pageSize: 10,
|
goodsName: "",
|
classCode1: "",
|
classCode2: "",
|
shopState: "",
|
saleState: "",
|
});
|
|
/**
|
* 获取数据列表
|
*/
|
const getDataList = async () => {
|
await getGoodsList(queryParams).then((res) => {
|
if (res.code == 200) {
|
state.dataTable = res.rows;
|
state.total = res.total;
|
state.tableOption.loading = false;
|
}
|
});
|
};
|
|
/**
|
* 重置
|
*/
|
const resetQuery = () => {
|
queryRef.value!.resetFields();
|
};
|
//#endregion
|
|
//#region common
|
|
/**
|
* 商品分类加载配置
|
*/
|
const classifyAddRef = ref();
|
const goodsClassify = reactive({
|
props: {
|
// label: "title",
|
// value: "value",
|
// leaf: "hasChildren",
|
checkStrictly: false,
|
lazy: true,
|
async lazyLoad(node, resolve) {
|
const { level, value } = node;
|
// setTimeout( () => {
|
let list = await getGoodsClassify(value as string, level);
|
// ++level;
|
resolve(list);
|
// }, 500);
|
},
|
} as CascaderProps,
|
classifysAdd: [],
|
});
|
const getGoodsClassify = async (val: string, level: number) => {
|
let list: any[] = [];
|
await getClassThreeList({ parentId: val }).then((res) => {
|
if (res.code == 200) {
|
list = res.data.map((item: any) => ({
|
value: item.value,
|
label: item.title,
|
leaf: level >= 1,
|
}));
|
// list = res.data;
|
}
|
});
|
return list;
|
};
|
|
/**
|
* 商品分类选择完成
|
*/
|
const onClassifyChange = () => {
|
if (goodsClassify.classifysAdd.length == 2) {
|
queryParams.classCode1 = goodsClassify.classifysAdd[0];
|
queryParams.classCode2 = goodsClassify.classifysAdd[1];
|
} else {
|
queryParams.classCode1 = "";
|
queryParams.classCode2 = "";
|
}
|
};
|
|
/**
|
* 显示字典值
|
* @param list
|
* @param val
|
*/
|
const dispDictLabel = (list: Dict.dictType[], val: string) => {
|
return list.find((f) => f.value == val)?.label || "";
|
};
|
|
//#endregion
|
|
//#region 新增
|
|
/**
|
* 新增
|
*/
|
const handleAdd = () => {
|
router.push({
|
path: "/goods/run/add",
|
query: {
|
type: 1,
|
},
|
});
|
};
|
|
//#endregion
|
|
//#region 删除
|
/**
|
* 选择时
|
* @param {} row
|
*/
|
const handleSelectionChange = (row: TypeGoodsInfoDTO[]) => {
|
ids.value = row.map((item: TypeGoodsInfoDTO) => item.goodsId);
|
state.power.multiple = !ids.value.length;
|
};
|
|
/**
|
* 删除
|
*/
|
const handleDelete = (row?: TypeGoodsInfoDTO) => {
|
const roleIds = (row && row.goodsId) || ids.value;
|
proxy.$modal
|
.confirm("是否确认删除选中的商品?")
|
.then(function () {
|
return deleteGoods(roleIds);
|
})
|
.then(() => {
|
getDataList();
|
// let ss = new Set(row_keys.value);
|
proxy.$modal.msgSuccess("删除成功");
|
})
|
.catch(() => {});
|
};
|
|
//#endregion
|
|
//#region 修改
|
|
/**
|
* 修改
|
*/
|
const handleUpdate = (e: TypeGoodsDTO) => {
|
router.push({
|
path: "/goods/run/add",
|
query: {
|
type: 2,
|
id: e.goodsId,
|
},
|
});
|
};
|
|
//#endregion
|
|
//#region 详情
|
|
/**
|
* 序列化图片地址
|
* @param val
|
*/
|
const inImageUrlToList = (val: string) => {
|
let list: any[] = [];
|
if (val) {
|
let ss = val.split(",");
|
for (const el of ss) {
|
list.push({
|
url: el,
|
type: el.substring(el.lastIndexOf(".") + 1),
|
});
|
}
|
}
|
return list;
|
};
|
|
/**
|
*
|
* @param val
|
*/
|
const checkFileType = (val: string) => {
|
if (val == "png" || val == "jpg" || val == "jpeg" || val == "gif") {
|
return 1;
|
}
|
return 2;
|
};
|
|
/**
|
* 展开详情
|
*/
|
const handleInfo = (e: TypeGoodsInfoDTO) => {
|
getDataInfo(e.goodsId, () => {
|
state.isOpenInfo = true;
|
});
|
};
|
|
/**
|
* 获取详情
|
* @param {} e
|
*/
|
const getDataInfo = async (e: number, fnc: () => void) => {
|
await getGoodsInfo(e).then((res) => {
|
if (res.code == 200) {
|
let data = res.data;
|
state.dataInfo = { ...data };
|
if (fnc != null) {
|
fnc();
|
}
|
}
|
});
|
};
|
|
//#endregion
|
|
/**
|
* 导出
|
*/
|
const handleExport = () => {};
|
</script>
|
|
<style scoped lang="scss">
|
.custom-img {
|
width: 50px;
|
height: 50px;
|
}
|
|
.video {
|
width: 120px;
|
height: 120px;
|
}
|
</style>
|