newadmin
This commit is contained in:
parent
263a27c6a4
commit
188dbedbe6
86
src/api/modules/audit.js
Normal file
86
src/api/modules/audit.js
Normal file
@ -0,0 +1,86 @@
|
||||
import request from '@/utils/axios'
|
||||
|
||||
// 查询审核列表
|
||||
export const getAuditList = (params) => {
|
||||
return request({
|
||||
url: '/zhishu/audit/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 导出审核列表
|
||||
export const exportAudit = (data) => {
|
||||
return request({
|
||||
url: '/zhishu/audit/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取审核详细信息
|
||||
export const getAuditById = (id) => {
|
||||
return request({
|
||||
url: `/zhishu/audit/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增审核
|
||||
export const addAudit = (data) => {
|
||||
return request({
|
||||
url: '/zhishu/audit',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改审核
|
||||
export const updateAudit = (data) => {
|
||||
return request({
|
||||
url: '/zhishu/audit',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除审核
|
||||
export const deleteAudit = (ids) => {
|
||||
return request({
|
||||
url: `/zhishu/audit/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改审核通过状态
|
||||
export const updateAuditStatus = (data) => {
|
||||
return request({
|
||||
url: '/zhishu/audit/updateStatus',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改审核未通过状态
|
||||
export const failSendAudit = (data) => {
|
||||
return request({
|
||||
url: '/zhishu/audit/failSend',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 审核API对象
|
||||
export const auditApi = {
|
||||
getAuditList,
|
||||
exportAudit,
|
||||
getAuditById,
|
||||
addAudit,
|
||||
updateAudit,
|
||||
deleteAudit,
|
||||
updateAuditStatus,
|
||||
failSendAudit
|
||||
}
|
||||
|
||||
export default auditApi
|
||||
36
src/api/modules/bookAudit.js
Normal file
36
src/api/modules/bookAudit.js
Normal file
@ -0,0 +1,36 @@
|
||||
import instance from '../../utils/axios.js'
|
||||
|
||||
// 图书审核相关API
|
||||
const bookAuditApi = {
|
||||
// 获取图书审核列表
|
||||
getBookAuditList: (params) => instance.get('/zhishu/bookAudit/list', { params }),
|
||||
|
||||
// 获取图书审核详细信息
|
||||
getBookAuditById: (id) => instance.get(`/zhishu/bookAudit/${id}`),
|
||||
|
||||
// 新增图书审核
|
||||
addBookAudit: (data) => instance.post('/zhishu/bookAudit', data),
|
||||
|
||||
// 修改图书审核
|
||||
updateBookAudit: (data) => instance.put('/zhishu/bookAudit', data),
|
||||
|
||||
// 删除图书审核(支持批量删除)
|
||||
deleteBookAudit: (ids) => {
|
||||
const idStr = Array.isArray(ids) ? ids.join(',') : ids;
|
||||
return instance.delete(`/zhishu/bookAudit/${idStr}`);
|
||||
},
|
||||
|
||||
// 导出图书审核列表
|
||||
exportBookAudit: (data) => instance.post('/zhishu/bookAudit/export', data, {
|
||||
responseType: 'blob'
|
||||
}),
|
||||
|
||||
// 修改审核状态(通过/未通过)
|
||||
updateBookAuditStatus: (data) => instance.put('/zhishu/bookAudit/updateStatus', data),
|
||||
|
||||
// 审核未通过并记录日志
|
||||
failSendBookAudit: (data) => instance.post('/zhishu/bookAudit/failSend', data)
|
||||
};
|
||||
|
||||
// 导出模块
|
||||
export { bookAuditApi };
|
||||
107
src/api/modules/excelTask.js
Normal file
107
src/api/modules/excelTask.js
Normal file
@ -0,0 +1,107 @@
|
||||
import instance from '../../utils/axios.js'
|
||||
|
||||
// 查询任务列表
|
||||
export const getExcelTaskList = (params = {}) => {
|
||||
return instance.get('/zhishu/excelTask/list', { params })
|
||||
}
|
||||
|
||||
// 获取任务详细信息
|
||||
export const getExcelTaskDetail = (id) => {
|
||||
return instance.get(`/zhishu/excelTask/${id}`)
|
||||
}
|
||||
|
||||
// 新增任务
|
||||
export const addExcelTask = (data) => {
|
||||
return instance.post('/zhishu/excelTask', data)
|
||||
}
|
||||
|
||||
// 修改任务
|
||||
export const updateExcelTask = (data) => {
|
||||
return instance.put('/zhishu/excelTask', data)
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
export const deleteExcelTask = (ids) => {
|
||||
return instance.delete(`/zhishu/excelTask/${ids}`)
|
||||
}
|
||||
|
||||
// 导出任务列表
|
||||
export const exportExcelTask = (params) => {
|
||||
return instance.post('/zhishu/excelTask/export', params, {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取导入模板
|
||||
export const getImportTemplate = () => {
|
||||
return instance.post('/zhishu/excelTask/importTemplate', {}, {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 文件上传
|
||||
export const uploadExcelFile = (file) => {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return instance.post('/zhishu/excelTask/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取日志列表
|
||||
export const getLogsList = (id) => {
|
||||
return instance.get('/zhishu/excelTask/logsList', {
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取日志消息
|
||||
export const getLogsMsg = (id) => {
|
||||
return instance.get('/zhishu/excelTask/logsMsg', {
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取详细日志列表
|
||||
export const getLogsDetailList = (taskId, shopId) => {
|
||||
return instance.get(`/zhishu/excelTask/logsDetailList/${taskId}/${shopId}`)
|
||||
}
|
||||
|
||||
// 下载日志
|
||||
export const downloadLogs = (fileName) => {
|
||||
return instance.get(`/zhishu/excelTask/downloadLogs/${fileName}`, {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 暂停线程
|
||||
export const pauseThread = (threadId, taskId) => {
|
||||
return instance.get(`/zhishu/excelTask/pauseThread/${threadId}/${taskId}`)
|
||||
}
|
||||
|
||||
// 继续执行线程
|
||||
export const continueThread = (threadId, taskId) => {
|
||||
return instance.get(`/zhishu/excelTask/continueThread/${threadId}/${taskId}`)
|
||||
}
|
||||
|
||||
// 为了向后兼容,也导出整个对象
|
||||
export const excelTaskApi = {
|
||||
getExcelTaskList,
|
||||
getExcelTaskDetail,
|
||||
addExcelTask,
|
||||
updateExcelTask,
|
||||
deleteExcelTask,
|
||||
exportExcelTask,
|
||||
getImportTemplate,
|
||||
uploadExcelFile,
|
||||
getLogsList,
|
||||
getLogsMsg,
|
||||
getLogsDetailList,
|
||||
downloadLogs,
|
||||
pauseThread,
|
||||
continueThread
|
||||
}
|
||||
|
||||
export default excelTaskApi
|
||||
58
src/api/modules/pddGoods.js
Normal file
58
src/api/modules/pddGoods.js
Normal file
@ -0,0 +1,58 @@
|
||||
import instance from '../../utils/axios.js'
|
||||
|
||||
// 拼多多商品相关API
|
||||
const pddGoodsApi = {
|
||||
// 获取授权回调代码
|
||||
getCode: (params) => instance.get('/pddGoods', { params }),
|
||||
|
||||
// 获取店铺商品总数
|
||||
getShopGoodsTotalNum: (shopId) => instance.get(`/pddGoods/getShopGoodsTotalNum?shopId=${shopId}`),
|
||||
|
||||
// 创建店铺商品列表同步任务
|
||||
createShopGoodsList: (shopId, sycFlag) => instance.get(`/pddGoods/createShopGoodsList?shopId=${shopId}&sycFlag=${sycFlag}`),
|
||||
|
||||
// 创建店铺商品详细信息同步任务
|
||||
createShopGoodsDetailList: (shopId) => instance.get(`/pddGoods/createShopGoodsDetailList?shopId=${shopId}`),
|
||||
|
||||
// 获取店铺商品列表
|
||||
getShopGoodsList: (shopId, isOnsale, pageNum, pageSize) => instance.get(`/pddGoods/getShopGoodsList?shopId=${shopId}&isOnsale=${isOnsale}&pageNum=${pageNum}&pageSize=${pageSize}`),
|
||||
|
||||
// 导出店铺商品数据
|
||||
emportShopGoods: (data) => instance.post('/pddGoods/emportShopGoods', data, { responseType: 'blob' }),
|
||||
|
||||
// 检查CSV文件是否存在
|
||||
checkFile: (shopId) => instance.get(`/pddGoods/checkFile?shopId=${shopId}`),
|
||||
|
||||
// 批量修改所有商品上架状态
|
||||
editShopGoodsAllByIsOnSale: (shopId, isOnSale) => instance.post('/pddGoods/editShopGoodsAllByIsOnSale', `shopId=${shopId}&isOnSale=${isOnSale}`, {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
}),
|
||||
|
||||
// 获取商品价格验证文件下载链接
|
||||
getVerifyPriceUrl: (shopId) => instance.get(`/pddGoods/getVerifyPriceUrl?shopId=${shopId}`),
|
||||
|
||||
// 通过CSV修改商品价格数据
|
||||
updateShopGoodsDataPriceCSV: (data) => instance.post('/pddGoods/updateShopGoodsDataPriceCSV', data),
|
||||
|
||||
// 批量设置商品为售罄状态
|
||||
batchSetSoldOut: (shopId) => instance.post('/pddGoods/batchSetSoldOut', `shopId=${shopId}`, {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
}),
|
||||
|
||||
// 通过CSV批量翻新上架商品
|
||||
batchRenovateOnSaleByCsv: (file, shopId) => {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('shopId', shopId)
|
||||
return instance.post('/pddGoods/batchRenovateOnSaleByCsv', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
},
|
||||
|
||||
// 翻新单个商品上架状态
|
||||
renovateOnSale: (data) => instance.post('/pddGoods/renovateOnSale', data)
|
||||
|
||||
};
|
||||
|
||||
// 导出模块
|
||||
export { pddGoodsApi };
|
||||
166
src/api/modules/shopOrder.js
Normal file
166
src/api/modules/shopOrder.js
Normal file
@ -0,0 +1,166 @@
|
||||
import request from '@/utils/axios'
|
||||
|
||||
/**
|
||||
* 店铺订单相关接口
|
||||
*/
|
||||
|
||||
// 查询订单列表
|
||||
export function getShopOrderList(params) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询订单列表(分页)
|
||||
export function getShopOrderPage(params) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/page',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 导出订单列表
|
||||
export function exportShopOrder(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/export',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取订单详细信息
|
||||
export function getShopOrderInfo(id) {
|
||||
return request({
|
||||
url: `/zhishu/shopOrder/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增订单
|
||||
export function addShopOrder(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改订单
|
||||
export function updateShopOrder(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
export function deleteShopOrder(ids) {
|
||||
return request({
|
||||
url: `/zhishu/shopOrder/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 订单列表查询接口(根据成交时间)
|
||||
export function getInterShopOrder(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/getInterShopOrder',
|
||||
method: 'get',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 根据订单编码查询订单信息
|
||||
export function getOrderByOrderSn(orderSn) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/listByOrderSn',
|
||||
method: 'get',
|
||||
params: { orderSn }
|
||||
})
|
||||
}
|
||||
|
||||
// 根据店铺id查询订单信息
|
||||
export function getOrderByShopId(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/listByShopId',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量插入/更新订单信息
|
||||
export function insertOrUpdateOrderBatch(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/insertOrUpdateOrderBatch',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 定时同步孔网订单
|
||||
export function syncKfzOrderTask() {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/syncKfzOrderTask',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取配送方式列表
|
||||
export function getDeliveryMethodList(params) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/delivery/methodList',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 订单发货
|
||||
export function orderDelivery(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/delivery',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 检查订单信息
|
||||
export function checkOrderInfo(orderId) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/checkInfo',
|
||||
method: 'post',
|
||||
params: { orderId }
|
||||
})
|
||||
}
|
||||
|
||||
// 重新同步订单(已扣减库存订单不会再次扣减)
|
||||
export function syncKfzHistoryOrder(params, data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/syncKfzHistoryOrder',
|
||||
method: 'post',
|
||||
params,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 重新同步订单完成回调
|
||||
export function syncKfzHistoryOrderCallBack(params) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/syncKfzHistoryOrderCallBack',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改订单同步状态
|
||||
export function updateIsSynOrder(data) {
|
||||
return request({
|
||||
url: '/zhishu/shopOrder/updateIsSynOrder',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
66
src/components/Pagination.vue
Normal file
66
src/components/Pagination.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'Pagination'
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 10
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
|
||||
|
||||
const currentPage = computed({
|
||||
get: () => props.page,
|
||||
set: (val) => emit('update:page', val)
|
||||
})
|
||||
|
||||
const pageSize = computed({
|
||||
get: () => props.limit,
|
||||
set: (val) => emit('update:limit', val)
|
||||
})
|
||||
|
||||
const handleSizeChange = (size) => {
|
||||
emit('update:limit', size)
|
||||
emit('pagination', { page: currentPage.value, limit: size })
|
||||
}
|
||||
|
||||
const handleCurrentChange = (page) => {
|
||||
emit('update:page', page)
|
||||
emit('pagination', { page, limit: pageSize.value })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
54
src/components/RightToolbar.vue
Normal file
54
src/components/RightToolbar.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="right-toolbar">
|
||||
<div class="toolbar-actions">
|
||||
<el-button @click="toggleSearch" circle>
|
||||
<el-icon>
|
||||
<Search />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button @click="handleRefresh" circle>
|
||||
<el-icon>
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Search, Refresh } from '@element-plus/icons-vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'RightToolbar'
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
showSearch: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:showSearch', 'queryTable'])
|
||||
|
||||
const toggleSearch = () => {
|
||||
emit('update:showSearch', !props.showSearch)
|
||||
}
|
||||
|
||||
const handleRefresh = () => {
|
||||
emit('queryTable')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.right-toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -2,7 +2,7 @@
|
||||
<el-menu router :default-active="$route.path" :collapse="false" unique-opened background-color="#304156"
|
||||
text-color="#bfcbd9" active-text-color="#409EFF">
|
||||
<template v-for="item in filteredMenuTree" :key="item.id">
|
||||
<!-- 有子菜单的情况 -->
|
||||
<!-- 有子菜单的情况 -->
|
||||
<el-sub-menu v-if="item.children && item.children.length > 0" :index="item.path || item.id.toString()">
|
||||
<template #title>
|
||||
<el-icon v-if="item.icon">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<!-- 顶部导航 -->
|
||||
<el-header height="60px"><navbar /></el-header>
|
||||
<el-container>
|
||||
<!-- 侧边栏 -->
|
||||
<!-- 侧边栏 -->
|
||||
<el-aside width="220px"><Sidebar /></el-aside>
|
||||
<!-- 标签页 -->
|
||||
<el-main style="padding: 5px;">
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
const admin = JSON.parse(localStorage.getItem('userInfo'))
|
||||
// 获取 用户名
|
||||
const userName = admin?.username || 'admin'
|
||||
// 路由
|
||||
// 路由
|
||||
const router = useRouter()
|
||||
// 跳转
|
||||
const goTo = (path:string) => {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<span>{{ item.title }}</span>
|
||||
</template>
|
||||
|
||||
<!-- 二级菜单 -->
|
||||
<!-- 二级菜单 -->
|
||||
<el-menu-item v-for="child in item.children" :key="child.path" :index="child.path">
|
||||
{{ child.title }}
|
||||
</el-menu-item>
|
||||
|
||||
635
src/views/Audit/index.vue
Normal file
635
src/views/Audit/index.vue
Normal file
@ -0,0 +1,635 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition enter-active-class="animate__animated animate__fadeInDown"
|
||||
leave-active-class="animate__animated animate__fadeOutUp">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="search-form">
|
||||
<div class="search-left">
|
||||
<el-form-item label="企业名称" prop="companyName" label-width="100px">
|
||||
<el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系方式" prop="contactPhone">
|
||||
<el-input v-model="queryParams.contactPhone" placeholder="请输入联系方式" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="search-right">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="auditList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="ID" align="center" prop="id" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="truncate-cell">
|
||||
{{ row.id }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="用户昵称" align="center" prop="userName" width="140" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<div class="truncate-cell">
|
||||
<el-button link @click="handleQueryInfo(scope.row)" class="apply-btn" title="点击显示用户详细信息">{{
|
||||
scope.row.userName }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="企业名称" align="center" prop="companyName" />
|
||||
<el-table-column label="企业类型" align="center" prop="companyType">
|
||||
<template #default="{ row }">
|
||||
{{ row.companyType === '1' ? '有限责任公司' :
|
||||
row.companyType === '2' ? '股份有限公司' :
|
||||
row.companyType === '3' ? '个人独资企业' :
|
||||
'合伙企业' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="联系人名" align="center" prop="contactPerson" />
|
||||
<el-table-column label="联系方式" align="center" prop="contactPhone" />
|
||||
<el-table-column label="邮箱" align="center" prop="email" />
|
||||
<el-table-column label="备注" align="center" prop="remark" width="120" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="truncate-cell">
|
||||
{{ row.remark }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核状态" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '0' ? 'success' : row.status === '1' ? 'danger' : 'info'"
|
||||
:effect="row.status === '0' ? 'dark' : 'light'" size="large">
|
||||
{{ row.status === '0' ? '通过' : row.status === '1' ? '未通过' : '待审核' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="通过" placement="top">
|
||||
<el-button link type="success" @click="handleUpdateStatus(scope.row.id, '0')">
|
||||
<el-icon><Check /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="未通过" placement="top">
|
||||
<el-button link type="danger" circle @click="handleOpenDialog(scope.row.id)">X</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="getList" />
|
||||
</el-card>
|
||||
|
||||
<!-- 添加或修改审核对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="auditFormRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="管理员ID" prop="adminId">
|
||||
<el-input v-model="form.adminId" placeholder="请输入管理员ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="企业名称" prop="companyName">
|
||||
<el-input v-model="form.companyName" placeholder="请输入企业名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="企业类型" prop="companyType">
|
||||
<el-input v-model="form.companyType" placeholder="请输入企业类型" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系人名" prop="contactPerson">
|
||||
<el-input v-model="form.contactPerson" placeholder="请输入联系人名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系方式" prop="contactPhone">
|
||||
<el-input v-model="form.contactPhone" placeholder="请输入联系方式" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="营业执照" prop="license">
|
||||
<el-input v-model="form.license" placeholder="请输入营业执照" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审核状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :label="0" border size="large" value="0">通过</el-radio>
|
||||
<el-radio :label="1" border size="large" value="1">未通过</el-radio>
|
||||
<el-radio :label="2" border size="large" value="2">待审核</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 未通过信息对话框 -->
|
||||
<el-dialog title="填写未通过信息" center v-model="dialog1.visible" width="50%" :close-on-click-modal="false">
|
||||
<el-form ref="formRef" :model="form" label-width="120px" :rules="rules">
|
||||
<el-form-item label="驳回理由" prop="remark" :rules="[
|
||||
{ required: true, message: '必须填写驳回理由', trigger: 'blur' },
|
||||
{ min: 10, message: '至少输入10个字符', trigger: 'blur' }
|
||||
]">
|
||||
<el-input type="textarea" :rows="3" v-model="form.remark" placeholder="请输入具体驳回原因,例如:1.材料不完整;2.信息有误..."
|
||||
show-word-limit :maxlength="500" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialog1.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="hitbackButton(form.remark)">
|
||||
确认打回
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 申请入驻对话框 -->
|
||||
<el-dialog title="申请入驻" v-model="dialogVisible" width="50%" :before-close="handleClose">
|
||||
<el-form ref="settleFormRef" :model="form" :rules="rules" label-width="120px" disabled>
|
||||
<el-form-item label="身份证正反面" prop="cardIdentity">
|
||||
<el-image v-if="cardFronUrl" :src="cardFronUrl" class="avatar" :preview-src-list="[cardFronUrl]"
|
||||
style="width: 200px;height: 200px;margin-right: 30px">
|
||||
</el-image>
|
||||
<el-image v-if="cartSideUrl" :src="cartSideUrl" class="avatar" :preview-src-list="[cartSideUrl]"
|
||||
style="width: 200px;height: 200px">
|
||||
</el-image>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="联系人" prop="contactPerson">
|
||||
<el-input v-model="form.contactPerson" disabled="true" placeholder="联系人姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="contactPhone">
|
||||
<el-input v-model="form.contactPhone" placeholder="请输入联系电话"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电子邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入电子邮箱"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="营业执照" prop="license">
|
||||
<el-image v-if="imageUrl" :src="imageUrl" class="avatar" :preview-src-list="[imageUrl]"
|
||||
style="width: 200px;height: 200px">
|
||||
<template #tip>
|
||||
<div class="upload-tip">请上传经营许可证</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item style="display: none" label="营业执照名称:" prop="licenseName">
|
||||
<el-input v-model="form.licenseName" placeholder="请输入营业执照名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="注册号:" prop="licenseNumber">
|
||||
<el-input v-model="form.licenseNumber" disabled="true" placeholder="营业执照注册号"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="企业名称" prop="companyName">
|
||||
<el-input v-model="form.companyName" disabled="true" placeholder="企业全称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="店铺地址" prop="adress">
|
||||
<el-input v-model="form.adress" disabled="true" placeholder="店铺地址"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="企业类型" prop="companyType">
|
||||
<el-select v-model="form.companyType" placeholder="请选择企业类型">
|
||||
<el-option label="有限责任公司" value="1"></el-option>
|
||||
<el-option label="股份有限公司" value="2"></el-option>
|
||||
<el-option label="个人独资企业" value="3"></el-option>
|
||||
<el-option label="合伙企业" value="4"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="营业执照过期时间" prop="licenseTime">
|
||||
<el-date-picker v-model="form.licenseTime" date-format="YYYY/MM/DD" value-format="YYYY/MM/DD" type="date"
|
||||
placeholder="date" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="经营许可证" prop="businessLicense">
|
||||
<el-image v-if="Imagelicense" :src="Imagelicense" class="avatar" :preview-src-list="[Imagelicense]"
|
||||
style="width: 200px;height: 200px">
|
||||
<template #tip>
|
||||
<div class="upload-tip">请上传经营许可证</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="经营许可证过期时间" prop="businessLicenseTime">
|
||||
<el-date-picker v-model="form.businessLicenseTime" date-format="YYYY/MM/DD" value-format="YYYY/MM/DD"
|
||||
type="date" placeholder="date" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出版物许可证证照核实方式" prop="remark">
|
||||
<el-input type="textarea" :rows="3" v-model="form.remark" placeholder="请输入其他需要说明的信息"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineOptions({
|
||||
name: 'Audit'
|
||||
})
|
||||
import { ref, reactive, toRefs, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Check } from '@element-plus/icons-vue'
|
||||
import { getAuditList, getAuditById, addAudit, updateAudit, deleteAudit, updateAuditStatus, failSendAudit, exportAudit } from '@/api/modules/audit'
|
||||
import { ImageApi } from '@/api/modules/Image'
|
||||
|
||||
const auditList = ref([])
|
||||
const buttonLoading = ref(false)
|
||||
const loading = ref(true)
|
||||
const showSearch = ref(true)
|
||||
const ids = ref([])
|
||||
const single = ref(true)
|
||||
const multiple = ref(true)
|
||||
const total = ref(0)
|
||||
|
||||
const queryFormRef = ref()
|
||||
const auditFormRef = ref()
|
||||
const formRef = ref()
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: ''
|
||||
})
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
const dialog1 = reactive({
|
||||
visible: false,
|
||||
title: ''
|
||||
})
|
||||
|
||||
// 身份证正面
|
||||
const cardFronUrl = ref('')
|
||||
// 身份证反面
|
||||
const cartSideUrl = ref('')
|
||||
// 营业执照图片
|
||||
const imageUrl = ref('')
|
||||
const Imagelicense = ref('')
|
||||
|
||||
const initFormData = {
|
||||
userId: undefined,
|
||||
userName: undefined,
|
||||
adminId: undefined,
|
||||
status: undefined,
|
||||
companyName: undefined,
|
||||
companyType: undefined,
|
||||
contactPerson: undefined,
|
||||
contactPhone: undefined,
|
||||
email: undefined,
|
||||
license: undefined,
|
||||
remark: undefined
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userId: undefined,
|
||||
userName: undefined,
|
||||
adminId: undefined,
|
||||
companyName: undefined,
|
||||
companyType: undefined,
|
||||
contactPerson: undefined,
|
||||
contactPhone: undefined,
|
||||
email: undefined,
|
||||
license: undefined,
|
||||
remark: undefined,
|
||||
status: undefined
|
||||
},
|
||||
rules: {}
|
||||
})
|
||||
|
||||
// 组合式API存储当前操作上下文
|
||||
const operationContext = reactive({
|
||||
currentId: '',
|
||||
currentData: {}
|
||||
})
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data)
|
||||
|
||||
// 打开弹窗方法
|
||||
const handleOpenDialog = (id) => {
|
||||
operationContext.currentId = id
|
||||
console.log(operationContext.currentId)
|
||||
dialog1.visible = true
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
/** 查询审核列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getAuditList(queryParams.value)
|
||||
auditList.value = res.data?.list || res.data || []
|
||||
total.value = res.data?.total || res.total || 0
|
||||
} catch (error) {
|
||||
console.error('获取审核列表失败:', error)
|
||||
ElMessage.error('获取审核列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset()
|
||||
dialog.visible = false
|
||||
}
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData }
|
||||
auditFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map(item => item.id)
|
||||
single.value = selection.length !== 1
|
||||
multiple.value = !selection.length
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset()
|
||||
dialog.visible = true
|
||||
dialog.title = '添加审核'
|
||||
}
|
||||
|
||||
const handleQueryInfo = async (row) => {
|
||||
reset()
|
||||
const _id = row?.id || ids.value[0]
|
||||
try {
|
||||
const res = await getAuditById(_id)
|
||||
console.log(res)
|
||||
|
||||
console.log("res.data.license", res.data.license)
|
||||
|
||||
// 处理营业执照图片
|
||||
try {
|
||||
const imageResponse = await ImageApi.getImage({ fileName: res.data.license })
|
||||
imageUrl.value = imageResponse // 现在直接返回字符串
|
||||
console.log("imageUrl.value", imageUrl.value)
|
||||
} catch (imageError) {
|
||||
console.error('获取营业执照图片失败:', imageError)
|
||||
imageUrl.value = null
|
||||
}
|
||||
|
||||
Imagelicense.value = res.data.businessLicense
|
||||
console.log("Imagelicense.value", Imagelicense.value)
|
||||
|
||||
// 处理身份证图片
|
||||
try {
|
||||
const urlArray = JSON.parse(res.data.cardIdentity)
|
||||
|
||||
try {
|
||||
const cardFrontResponse = await ImageApi.getImage({ fileName: urlArray[0] })
|
||||
cardFronUrl.value = cardFrontResponse // 现在直接返回字符串
|
||||
console.log("cardFronUrl.value", cardFronUrl.value)
|
||||
} catch (imageError) {
|
||||
console.error('获取身份证正面图片失败:', imageError)
|
||||
cardFronUrl.value = null
|
||||
}
|
||||
|
||||
try {
|
||||
const cartSideResponse = await ImageApi.getImage({ fileName: urlArray[1] })
|
||||
cartSideUrl.value = cartSideResponse // 现在直接返回字符串
|
||||
console.log("cartSideUrl.value", cartSideUrl.value)
|
||||
} catch (imageError) {
|
||||
console.error('获取身份证反面图片失败:', imageError)
|
||||
cartSideUrl.value = null
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('解析身份证图片失败:', error)
|
||||
}
|
||||
|
||||
Object.assign(form.value, res.data)
|
||||
dialogVisible.value = true
|
||||
} catch (error) {
|
||||
console.error('获取审核详情失败:', error)
|
||||
ElMessage.error('获取审核详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row) => {
|
||||
reset()
|
||||
const _id = row?.id || ids.value[0]
|
||||
try {
|
||||
const res = await getAuditById(_id)
|
||||
Object.assign(form.value, res.data)
|
||||
dialog.visible = true
|
||||
dialog.title = '修改审核'
|
||||
} catch (error) {
|
||||
console.error('获取审核详情失败:', error)
|
||||
ElMessage.error('获取审核详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 审核通过按钮操作 */
|
||||
const handleUpdateStatus = async (id, status) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`是否审核编号为"${id}"的数据项?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
const params = {
|
||||
id: id,
|
||||
status: status
|
||||
}
|
||||
|
||||
await updateAuditStatus(params)
|
||||
ElMessage.success('审核通过')
|
||||
await getList()
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('审核状态更新失败:', error)
|
||||
ElMessage.error('审核状态更新失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打回按钮
|
||||
*/
|
||||
const hitbackButton = async (remark) => {
|
||||
const payload = {
|
||||
id: operationContext.currentId,
|
||||
status: '1',
|
||||
remark
|
||||
}
|
||||
|
||||
try {
|
||||
await failSendAudit(payload)
|
||||
ElMessage.success('审核未通过操作成功')
|
||||
dialog1.visible = false
|
||||
await getList()
|
||||
} catch (error) {
|
||||
console.error('审核未通过操作失败:', error)
|
||||
ElMessage.error('审核未通过操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
auditFormRef.value?.validate(async (valid) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true
|
||||
try {
|
||||
if (form.value.id) {
|
||||
await updateAudit(form.value)
|
||||
} else {
|
||||
await addAudit(form.value)
|
||||
}
|
||||
ElMessage.success('操作成功')
|
||||
dialog.visible = false
|
||||
await getList()
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error)
|
||||
ElMessage.error('操作失败')
|
||||
} finally {
|
||||
buttonLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row) => {
|
||||
const _ids = row?.id || ids.value
|
||||
try {
|
||||
await ElMessageBox.confirm(`是否确认删除审核编号为"${_ids}"的数据项?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
await deleteAudit(_ids)
|
||||
ElMessage.success('删除成功')
|
||||
await getList()
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error)
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
const res = await exportAudit(queryParams.value)
|
||||
// 处理文件下载
|
||||
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `audit_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
ElMessage.success('导出成功')
|
||||
} catch (error) {
|
||||
console.error('导出失败:', error)
|
||||
ElMessage.error('导出失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 文本溢出处理 */
|
||||
.truncate-cell {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.avatar-uploader:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 140px;
|
||||
height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
margin-top: 8px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.search-left {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.avatar-uploader .avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
408
src/views/bookAudit/index.vue
Normal file
408
src/views/bookAudit/index.vue
Normal file
@ -0,0 +1,408 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div v-if="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="商品编号" prop="itemNumber">
|
||||
<el-input v-model="queryParams.itemNumber" placeholder="请输入商品编号" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="品相" prop="conditionCode">
|
||||
<el-input v-model="queryParams.conditionCode" placeholder="请输入品相" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="isbn" prop="isbn">
|
||||
<el-input v-model="queryParams.isbn" placeholder="请输入isbn" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain :disabled="single" @click="handleUpdate()">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain :disabled="multiple" @click="handleDelete()">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain @click="handleExport">导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button @click="showSearch = !showSearch">{{ showSearch ? '隐藏搜索' : '显示搜索' }}</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="bookAuditList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<el-form label-position="left" inline class="demo-table-expand">
|
||||
<el-form-item>
|
||||
<el-image style="width: 100px; height: 120px" :src="row.bookPic" fit="cover"
|
||||
:preview-src-list="[row.bookPic]" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="审核图书id" align="center" prop="id" />
|
||||
<el-table-column label="产品编码" align="center" prop="productId" />
|
||||
<el-table-column label="商品名称" align="center" prop="goodsName" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="truncate-cell">
|
||||
{{ row.goodsName }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="isbn" align="center" prop="isbn" />
|
||||
<el-table-column label="标准售价" align="center" prop="price">
|
||||
<template #default="{ row }">
|
||||
{{ (row.price / 100).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核状态" align="center" prop="status">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '0' ? 'success' : row.status === '1' ? 'danger' : 'info'"
|
||||
:effect="row.status === '0' ? 'dark' : 'light'" size="large">
|
||||
{{ row.status === '0' ? '通过' : row.status === '1' ? '未通过' : '待审核' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="通过" placement="top">
|
||||
<el-button link type="success" icon="Check" @click="handleUpdateStatus(scope.row.id, '0')">
|
||||
<el-icon>
|
||||
<Check />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="未通过" placement="top">
|
||||
<el-button link type="danger" circle @click="handleUpdateStatus(scope.row.id, '1')">X</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination v-if="total > 0" :total="total" v-model:current-page="queryParams.pageNum"
|
||||
v-model:page-size="queryParams.pageSize" @current-change="getList" @size-change="getList"
|
||||
:page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" />
|
||||
</el-card>
|
||||
|
||||
<!-- 添加或修改图书审核管理对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="bookAuditFormRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="用户id" prop="userId">
|
||||
<el-input v-model="form.userId" placeholder="请输入用户id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品编码" prop="productId">
|
||||
<el-input v-model="form.productId" placeholder="请输入产品编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品名称" prop="goodsName">
|
||||
<el-input v-model="form.goodsName" placeholder="请输入商品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="isbn" prop="isbn">
|
||||
<el-input v-model="form.isbn" placeholder="请输入isbn" />
|
||||
</el-form-item>
|
||||
<el-form-item label="货号" prop="artNo">
|
||||
<el-input v-model="form.artNo" placeholder="请输入货号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="品相" prop="conditionCode">
|
||||
<el-input v-model="form.conditionCode" placeholder="请输入品相" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品编号" prop="itemNumber">
|
||||
<el-input v-model="form.itemNumber" placeholder="请输入商品编号" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { bookAuditApi } from '@/api/modules/bookAudit'
|
||||
import { Check } from '@element-plus/icons-vue'
|
||||
|
||||
// 响应式数据
|
||||
const bookAuditList = ref([])
|
||||
const buttonLoading = ref(false)
|
||||
const loading = ref(true)
|
||||
const showSearch = ref(true)
|
||||
const ids = ref([])
|
||||
const single = ref(true)
|
||||
const multiple = ref(true)
|
||||
const total = ref(0)
|
||||
|
||||
// 表单引用
|
||||
const queryFormRef = ref()
|
||||
const bookAuditFormRef = ref()
|
||||
|
||||
// 对话框状态
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: ''
|
||||
})
|
||||
|
||||
// 初始表单数据
|
||||
const initFormData = {
|
||||
userId: '',
|
||||
productId: '',
|
||||
goodsName: '',
|
||||
isbn: '',
|
||||
artNo: '',
|
||||
conditionCode: '',
|
||||
itemNumber: '',
|
||||
status: '',
|
||||
inventory: '',
|
||||
bookPic: ''
|
||||
}
|
||||
|
||||
// 查询参数
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userId: '',
|
||||
productId: '',
|
||||
goodsName: '',
|
||||
isbn: '',
|
||||
artNo: '',
|
||||
conditionCode: '',
|
||||
itemNumber: '',
|
||||
status: '',
|
||||
inventory: '',
|
||||
bookPic: ''
|
||||
})
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({ ...initFormData })
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
conditionCode: [
|
||||
{ required: true, message: "品相不能为空", trigger: "blur" }
|
||||
]
|
||||
})
|
||||
|
||||
// 审核状态更新
|
||||
const handleUpdateStatus = async (id, status) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`是否审核编号为"${id}"的数据项?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
const params = {
|
||||
id: id,
|
||||
status: status
|
||||
}
|
||||
|
||||
await bookAuditApi.updateBookAuditStatus(params)
|
||||
ElMessage.success(status === '0' ? '审核通过' : '审核未通过')
|
||||
await getList()
|
||||
} catch (error) {
|
||||
console.error('审核状态更新失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 查询图书审核管理列表
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const filteredParams = Object.entries(queryParams)
|
||||
.filter(([_, v]) => v !== '' && v !== null && v !== undefined)
|
||||
.reduce((acc, [k, v]) => {
|
||||
acc[k] = v
|
||||
return acc
|
||||
}, {})
|
||||
const res = await bookAuditApi.getBookAuditList(filteredParams)
|
||||
bookAuditList.value = res.data.list || res.data.rows || []
|
||||
total.value = res.data.total || 0
|
||||
} catch (error) {
|
||||
console.error('获取列表失败:', error)
|
||||
ElMessage.error('获取列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 取消按钮
|
||||
const cancel = () => {
|
||||
reset()
|
||||
dialog.visible = false
|
||||
}
|
||||
|
||||
// 表单重置
|
||||
const reset = () => {
|
||||
Object.assign(form, initFormData)
|
||||
bookAuditFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 搜索按钮操作
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNum = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
// 重置按钮操作
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields()
|
||||
Object.assign(queryParams, {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userId: '',
|
||||
productId: '',
|
||||
goodsName: '',
|
||||
isbn: '',
|
||||
artNo: '',
|
||||
conditionCode: '',
|
||||
itemNumber: '',
|
||||
status: '',
|
||||
inventory: '',
|
||||
bookPic: ''
|
||||
})
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map(item => item.id)
|
||||
single.value = selection.length !== 1
|
||||
multiple.value = !selection.length
|
||||
}
|
||||
|
||||
// 新增按钮操作
|
||||
const handleAdd = () => {
|
||||
reset()
|
||||
dialog.visible = true
|
||||
dialog.title = "添加图书审核管理"
|
||||
}
|
||||
|
||||
// 修改按钮操作
|
||||
const handleUpdate = async (row) => {
|
||||
reset()
|
||||
const _id = row?.id || ids.value[0]
|
||||
try {
|
||||
const res = await bookAuditApi.getBookAuditById(_id)
|
||||
Object.assign(form, res.data)
|
||||
dialog.visible = true
|
||||
dialog.title = "修改图书审核管理"
|
||||
} catch (error) {
|
||||
console.error('获取详情失败:', error)
|
||||
ElMessage.error('获取详情失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 提交按钮
|
||||
const submitForm = () => {
|
||||
bookAuditFormRef.value?.validate(async (valid) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await bookAuditApi.updateBookAudit(form)
|
||||
} else {
|
||||
await bookAuditApi.addBookAudit(form)
|
||||
}
|
||||
ElMessage.success("操作成功")
|
||||
dialog.visible = false
|
||||
await getList()
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error)
|
||||
ElMessage.error('操作失败')
|
||||
} finally {
|
||||
buttonLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除按钮操作
|
||||
const handleDelete = async (row) => {
|
||||
const _ids = row?.id || ids.value
|
||||
try {
|
||||
await ElMessageBox.confirm(`是否确认删除图书审核管理编号为"${_ids}"的数据项?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
await bookAuditApi.deleteBookAudit(_ids)
|
||||
ElMessage.success("删除成功")
|
||||
await getList()
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 导出按钮操作
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
const res = await bookAuditApi.exportBookAudit(queryParams)
|
||||
// 创建下载链接
|
||||
const url = window.URL.createObjectURL(new Blob([res.data]))
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.setAttribute('download', `bookAudit_${new Date().getTime()}.xlsx`)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error('导出失败:', error)
|
||||
ElMessage.error('导出失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时获取列表
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 文本溢出处理 */
|
||||
.truncate-cell {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 增强悬浮提示样式 */
|
||||
.el-tooltip__popper {
|
||||
max-width: 400px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.demo-table-expand {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.demo-table-expand label {
|
||||
width: 90px;
|
||||
color: #99a9bf;
|
||||
}
|
||||
|
||||
.demo-table-expand .el-form-item {
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
||||
601
src/views/excelTask/index.vue
Normal file
601
src/views/excelTask/index.vue
Normal file
@ -0,0 +1,601 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="任务类型" prop="taskType">
|
||||
<el-select v-model="queryParams.taskType" placeholder="请选择任务类型" clearable>
|
||||
<el-option label="发布任务" value="1" />
|
||||
<el-option label="更新任务" value="2" />
|
||||
<el-option label="下架任务" value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件名称" prop="fileName">
|
||||
<el-input v-model="queryParams.fileName" placeholder="请输入文件名称" clearable
|
||||
@keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="任务状态" prop="taskStatus">
|
||||
<el-select v-model="queryParams.taskStatus" placeholder="请选择任务状态" clearable>
|
||||
<el-option label="执行中" value="1" />
|
||||
<el-option label="已暂停" value="2" />
|
||||
<el-option label="已完成" value="3" />
|
||||
<el-option label="已失败" value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>书品导入任务列表</span>
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新增任务</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="任务编码" align="center" prop="id" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="truncate-cell">
|
||||
{{ row.id }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务类型" align="center" prop="taskType">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.taskType === '1'" type="success">发布任务</el-tag>
|
||||
<el-tag v-else-if="scope.row.taskType === '2'" type="warning">更新任务</el-tag>
|
||||
<el-tag v-else-if="scope.row.taskType === '3'" type="danger">下架任务</el-tag>
|
||||
<el-tag v-else>未知</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="货区名称" align="center" prop="depotIds" />
|
||||
<el-table-column label="文件名称" align="center" prop="fileName" width="250" />
|
||||
<el-table-column label="执行数据条数" align="center" prop="dataNum" />
|
||||
<el-table-column label="任务状态" align="center" prop="taskStatus">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.taskStatus === '1'" type="success">执行中</el-tag>
|
||||
<el-tag v-else-if="scope.row.taskStatus === '2'" type="warning">已暂停</el-tag>
|
||||
<el-tag v-else-if="scope.row.taskStatus === '3'" type="info">已完成</el-tag>
|
||||
<el-tag v-else-if="scope.row.taskStatus === '4'" type="danger">已失败</el-tag>
|
||||
<el-tag v-else>未知</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
|
||||
<template #default="scope">
|
||||
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="查看日志" placement="top">
|
||||
<el-button link type="primary" @click="showLogs(scope.row)">
|
||||
日志
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="暂停任务" placement="top">
|
||||
<el-button v-if="scope.row.taskStatus === '1'" link type="warning"
|
||||
@click="pauseTask(scope.row)">
|
||||
暂停
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="恢复任务" placement="top">
|
||||
<el-button v-if="scope.row.taskStatus === '2'" link type="success"
|
||||
@click="resumeTask(scope.row)">
|
||||
恢复
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="删除任务" placement="top">
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<el-pagination v-show="total > 0" :total="total" v-model:current-page="queryParams.pageNum"
|
||||
v-model:page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper" @size-change="getList" @current-change="getList" />
|
||||
</el-card>
|
||||
|
||||
<!-- 添加任务对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="900px" append-to-body>
|
||||
<el-form ref="taskFormRef" :model="form" :rules="rules" label-width="100px" style="height:600px">
|
||||
<el-form-item label="任务类型" prop="taskType">
|
||||
<el-select v-model="form.taskType" placeholder="请选择任务类型">
|
||||
<el-option label="发布任务" value="1"></el-option>
|
||||
<el-option label="更新任务" value="2"></el-option>
|
||||
<el-option label="下架任务" value="3"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库选择" prop="depotIds" style="width: 100%">
|
||||
<el-checkbox-group v-model="form.depotIds">
|
||||
<el-checkbox v-for="item in depotList" :key="item.value" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文件选择" prop="fileUrl" style="width: 100%">
|
||||
<el-row>
|
||||
<el-col :span="14">
|
||||
<el-upload ref="uploadRef" class="upload-demo" :action="uploadUrl" :limit="1"
|
||||
:headers="uploadHeaders" :on-success="handleUploadSuccess" :on-exceed="handleExceed"
|
||||
:before-upload="beforeUpload">
|
||||
<template #trigger>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-button @click="downloadTemplate">下载模板</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 日志对话框 -->
|
||||
<el-dialog :title="dialog.logsTitle" v-model="dialog.logsVisible" width="800px" append-to-body>
|
||||
<div class="logs-message">
|
||||
{{ logsMessage }}
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="taskLogsList" height="400px">
|
||||
<el-table-column label="仓库名称" align="center" prop="depotName" />
|
||||
<el-table-column label="进度" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.progress }}%
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间/修改时间" align="center" prop="createTime" width="300">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.createTime }} / {{ scope.row.updateTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="查看" placement="top">
|
||||
<el-button link type="primary" icon="Memo" @click="showLogsDetail(scope.row)">查看</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="下载" placement="top">
|
||||
<el-button link type="primary" icon="Download"
|
||||
@click="downloadTaskLogs(scope.row.taskId + scope.row.shopId)">下载</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeLogsDialog">关 闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 详细日志对话框 -->
|
||||
<el-dialog :title="dialog.detailTitle" v-model="dialog.detailVisible" width="700px" append-to-body>
|
||||
<el-table v-loading="loading" :data="taskLogsDetailList" height="700px">
|
||||
<el-table-column label="日志名称" align="center" prop="logName" />
|
||||
<el-table-column label="数量" align="center" prop="num" width="100px" />
|
||||
<el-table-column label="占比" align="center" width="100px">
|
||||
<template #default="scope">
|
||||
{{ scope.row.progress }}%
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100px">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="下载日志" placement="top">
|
||||
<el-button link type="primary" icon="Download"
|
||||
@click="downloadTaskLogs(scope.row.mark)">下载日志</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeDetailDialog">关 闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
getExcelTaskList,
|
||||
addExcelTask,
|
||||
deleteExcelTask,
|
||||
getLogsList,
|
||||
getLogsMsg,
|
||||
getLogsDetailList,
|
||||
downloadLogs,
|
||||
pauseThread,
|
||||
continueThread,
|
||||
getImportTemplate,
|
||||
uploadExcelFile
|
||||
} from '@/api/modules/excelTask'
|
||||
import { depotApi } from '@/api/modules/depot'
|
||||
|
||||
const { appContext } = getCurrentInstance()
|
||||
const animate = appContext.config.globalProperties.$animate || {
|
||||
searchAnimate: {
|
||||
enter: 'animate__animated animate__fadeInDown',
|
||||
leave: 'animate__animated animate__fadeOutUp'
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const taskList = ref([])
|
||||
const taskLogsList = ref([])
|
||||
const taskLogsDetailList = ref([])
|
||||
const depotList = ref([])
|
||||
const buttonLoading = ref(false)
|
||||
const loading = ref(true)
|
||||
const showSearch = ref(true)
|
||||
const ids = ref([])
|
||||
const total = ref(0)
|
||||
const logsMessage = ref('')
|
||||
|
||||
// 表单引用
|
||||
const queryFormRef = ref()
|
||||
const taskFormRef = ref()
|
||||
const uploadRef = ref()
|
||||
|
||||
// 查询参数
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
taskType: undefined,
|
||||
fileName: undefined,
|
||||
taskStatus: undefined
|
||||
})
|
||||
|
||||
// 表单数据
|
||||
const form = ref({
|
||||
taskType: undefined,
|
||||
depotIds: [],
|
||||
fileUrl: undefined
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
taskType: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
|
||||
depotIds: [{ required: true, message: '仓库不能为空', trigger: 'blur' }],
|
||||
fileUrl: [{ required: true, message: '文件不能为空', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
// 对话框状态
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
logsVisible: false,
|
||||
logsTitle: '',
|
||||
detailVisible: false,
|
||||
detailTitle: ''
|
||||
})
|
||||
|
||||
// 上传配置
|
||||
const baseUrl = import.meta.env.VITE_APP_BASE_API
|
||||
const uploadUrl = ref(baseUrl + '/zhishu/excelTask/upload')
|
||||
const uploadHeaders = ref({
|
||||
'Authorization': `Bearer ${localStorage.getItem('accessToken') || ''}`
|
||||
})
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (time) => {
|
||||
if (!time) return ''
|
||||
const date = new Date(time)
|
||||
return date.toLocaleString('zh-CN')
|
||||
}
|
||||
|
||||
// 获取任务列表
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getExcelTaskList(queryParams.value)
|
||||
taskList.value = res.data?.list || []
|
||||
total.value = res.data?.total || 0
|
||||
} catch (error) {
|
||||
console.error('获取任务列表失败:', error)
|
||||
ElMessage.error('获取任务列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取仓库列表
|
||||
const getDepotList = async () => {
|
||||
try {
|
||||
const res = await depotApi.getDepotNameList()
|
||||
const resList = res.data?.rows || []
|
||||
depotList.value = resList.map(item => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('获取仓库列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
// 多选
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map(item => item.id)
|
||||
}
|
||||
|
||||
// 新增任务
|
||||
const handleAdd = () => {
|
||||
resetForm()
|
||||
dialog.visible = true
|
||||
dialog.title = '添加任务'
|
||||
}
|
||||
|
||||
// 暂停任务
|
||||
const pauseTask = async (row) => {
|
||||
try {
|
||||
await pauseThread(row.threadId, row.id)
|
||||
ElMessage.success('任务已暂停')
|
||||
getList()
|
||||
} catch (error) {
|
||||
console.error('暂停任务失败:', error)
|
||||
ElMessage.error('暂停任务失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复任务
|
||||
const resumeTask = async (row) => {
|
||||
try {
|
||||
await continueThread(row.threadId, row.id)
|
||||
ElMessage.success('任务已恢复')
|
||||
getList()
|
||||
} catch (error) {
|
||||
console.error('恢复任务失败:', error)
|
||||
ElMessage.error('恢复任务失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`是否确认删除任务编号为"${row.id}"的数据项?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
await deleteExcelTask(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
getList()
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除任务失败:', error)
|
||||
ElMessage.error('删除任务失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 显示日志
|
||||
const showLogs = async (row) => {
|
||||
try {
|
||||
const [logsRes, msgRes] = await Promise.all([
|
||||
getLogsList(row.id),
|
||||
getLogsMsg(row.id)
|
||||
])
|
||||
taskLogsList.value = logsRes.data || []
|
||||
logsMessage.value = msgRes.data || ''
|
||||
dialog.logsVisible = true
|
||||
dialog.logsTitle = '任务日志'
|
||||
} catch (error) {
|
||||
console.error('获取日志失败:', error)
|
||||
ElMessage.error('获取日志失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 显示详细日志
|
||||
const showLogsDetail = async (row) => {
|
||||
try {
|
||||
const res = await getLogsDetailList(row.taskId, row.shopId)
|
||||
taskLogsDetailList.value = res.data || []
|
||||
dialog.detailVisible = true
|
||||
dialog.detailTitle = `详细日志信息:${taskLogsDetailList.value[0]?.depotName || ''}`
|
||||
} catch (error) {
|
||||
console.error('获取详细日志失败:', error)
|
||||
ElMessage.error('获取详细日志失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 下载日志
|
||||
const downloadTaskLogs = async (fileName) => {
|
||||
try {
|
||||
const fullFileName = fileName + '.xlsx'
|
||||
const url = `${baseUrl}/zhishu/excelTask/downloadLogs/${fullFileName}`
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = fullFileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
} catch (error) {
|
||||
console.error('下载日志失败:', error)
|
||||
ElMessage.error('下载日志失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 下载模板
|
||||
const downloadTemplate = async () => {
|
||||
try {
|
||||
const res = await getImportTemplate()
|
||||
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `task_template_${new Date().getTime()}.xlsx`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error('下载模板失败:', error)
|
||||
ElMessage.error('下载模板失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 文件上传前检查
|
||||
const beforeUpload = (file) => {
|
||||
const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
|
||||
file.type === 'application/vnd.ms-excel'
|
||||
if (!isExcel) {
|
||||
ElMessage.error('只能上传Excel文件!')
|
||||
return false
|
||||
}
|
||||
const isLt10M = file.size / 1024 / 1024 < 10
|
||||
if (!isLt10M) {
|
||||
ElMessage.error('上传文件大小不能超过 10MB!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 文件上传成功
|
||||
const handleUploadSuccess = (response) => {
|
||||
if (response.code === 200) {
|
||||
form.value.fileUrl = response.data?.url || ''
|
||||
ElMessage.success('文件上传成功')
|
||||
} else {
|
||||
ElMessage.error(response.message || '文件上传失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 文件超出限制
|
||||
const handleExceed = () => {
|
||||
ElMessage.warning('只能上传一个文件')
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitForm = async () => {
|
||||
if (!taskFormRef.value) return
|
||||
|
||||
try {
|
||||
await taskFormRef.value.validate()
|
||||
buttonLoading.value = true
|
||||
|
||||
const submitData = {
|
||||
...form.value,
|
||||
depotIds: form.value.depotIds.join(',')
|
||||
}
|
||||
|
||||
await addExcelTask(submitData)
|
||||
ElMessage.success('操作成功')
|
||||
dialog.visible = false
|
||||
getList()
|
||||
} catch (error) {
|
||||
if (error !== false) { // 表单验证失败时error为false
|
||||
console.error('提交失败:', error)
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
} finally {
|
||||
buttonLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
form.value = {
|
||||
taskType: undefined,
|
||||
depotIds: [],
|
||||
fileUrl: undefined
|
||||
}
|
||||
taskFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 取消
|
||||
const cancel = () => {
|
||||
resetForm()
|
||||
dialog.visible = false
|
||||
}
|
||||
|
||||
// 关闭日志对话框
|
||||
const closeLogsDialog = () => {
|
||||
dialog.logsVisible = false
|
||||
taskLogsList.value = []
|
||||
logsMessage.value = ''
|
||||
}
|
||||
|
||||
// 关闭详细日志对话框
|
||||
const closeDetailDialog = () => {
|
||||
dialog.detailVisible = false
|
||||
taskLogsDetailList.value = []
|
||||
}
|
||||
|
||||
// 组件挂载时执行
|
||||
onMounted(() => {
|
||||
getList()
|
||||
getDepotList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.truncate-cell {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.logs-message {
|
||||
width: 100%;
|
||||
height: 162px;
|
||||
background: #f2f2f2;
|
||||
white-space: pre-wrap;
|
||||
padding: 13px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 4px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.el-tooltip__popper {
|
||||
max-width: 400px;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
879
src/views/pddGoods/index.vue
Normal file
879
src/views/pddGoods/index.vue
Normal file
@ -0,0 +1,879 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition enter-active-class="animate__animated animate__fadeInDown"
|
||||
leave-active-class="animate__animated animate__fadeOutUp">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-position="left" label-width="80px">
|
||||
<el-form-item label="店铺名称" prop="shopId">
|
||||
<el-select v-model="shopId" placeholder="请选择店铺" clearable @change="handleQuery">
|
||||
<el-option v-for="dict in shopList" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="is_onsale">
|
||||
<el-select v-model="queryParams.is_onsale" placeholder="请选择状态" clearable @change="handleQuery">
|
||||
<el-option key="0" label="下架" value="0" />
|
||||
<el-option key="1" label="上架" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button type="primary" @click="exportData">导出</el-button>
|
||||
<el-button type="primary" @click="confirmTongBu">删除后拉取</el-button>
|
||||
<el-button type="primary" @click="tongBu1">拉取</el-button>
|
||||
<el-button type="danger" @click="handleAdd" v-hasPermi="['zhishu:pddGoods:tongbu']">
|
||||
拼多多专属详情同步 </el-button>
|
||||
<el-button type="primary" @click="editIsOnSale('1')">整店上架</el-button>
|
||||
<el-button type="primary" @click="editIsOnSale('0')">整店下架</el-button>
|
||||
<el-button type="danger" @click="repeatData">下架重复</el-button>
|
||||
<el-button type="success" @click="showRenovateDialog">翻新上架</el-button>
|
||||
<el-button type="primary" @click="createVerifyPriceUrl">生成核价链接</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-dialog v-model="verifyPriceDialog" title="核价链接" width="700px" @close="closeData">
|
||||
<div class="verify-price-dialog">
|
||||
<el-form :model="encrypForm" :rules="encrypRules" ref="encrypFormRef">
|
||||
<el-form-item label="店铺优惠" prop="shopPrice" v-if="!pricingLink">
|
||||
<el-input v-model="encrypForm.shopPrice" placeholder="请输入店铺优惠、在0-20之间整数" />
|
||||
</el-form-item>
|
||||
<el-form-item label="利润区间" prop="profitRange" v-if="!pricingLink">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="minPrice">
|
||||
<el-input v-model="encrypForm.minPrice" type="number" placeholder="利润最小值(整数)">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4" style="text-align: center; line-height: 32px"> 至</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="maxPrice">
|
||||
<el-input v-model="encrypForm.maxPrice" type="number" placeholder="利润最大值(整数)">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="价格模版名称" prop="shopPrice" v-if="pricingLink">
|
||||
<el-input v-model="priceName" disabled />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="height: 110px; padding: 10px">
|
||||
<span>{{ pricingLink }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button v-if="pricingLink" @click="copyLink" type="primary" style="margin-left: 10px"> 一键复制 </el-button>
|
||||
<el-button type="primary" @click="encrypMethod" v-if="!pricingLink">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- 翻新上架弹窗 -->
|
||||
<el-dialog v-model="renovateDialogVisible" title="批量翻新上架" width="500px">
|
||||
<el-upload ref="upload" class="upload-demo" :auto-upload="false" :on-change="handleFileChange"
|
||||
:before-upload="beforeUpload" :limit="1" :file-list="fileList" accept=".csv">
|
||||
<template #trigger>
|
||||
<el-button type="primary">选择CSV文件</el-button>
|
||||
</template>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">请上传包含商品信息的CSV文件</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button @click="renovateDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="uploading" @click="handleUpload">开始上传</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="pddGoodsList" :element-loading-text="loadingText"
|
||||
element-loading-svg-view-box="-10, -10, 50, 50" element-loading-background="rgba(122, 122, 122, 0.8)"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="缩略图" align="left" prop="thumb_url" width="70" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<el-image style="width: 30px; height: 30px" :src="row.Img" fit="scale-down"
|
||||
:preview-src-list="[currentPreviewImg]" preview-teleported @click="handlePreview(row.Img)">
|
||||
<template #error>
|
||||
<div class="image-slot">暂无</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品id" align="center" prop="TrilateralId" width="150" />
|
||||
<el-table-column label="商品编码" align="center" prop="ISBN" width="150" />
|
||||
<el-table-column label="商品名称" align="center" prop="Title" />
|
||||
<el-table-column label="库存数量" align="center" prop="Stock" width="100" />
|
||||
<el-table-column label="是否在架上" align="center" prop="IsOnSale" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.IsOnSale == '1' ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="TotalPrice" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.TotalPrice ? row.TotalPrice / 100 : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格编码/货号(孔网)" align="center" prop="SkuCode" />
|
||||
<el-table-column label="创建时间" align="center" prop="FinishTime" width="200" />
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 添加这个新的弹窗用于展示重复商品数据 -->
|
||||
<el-dialog v-model="repeatDataDialog" title="重复商品列表" width="80%">
|
||||
<el-table :data="repeatDataList" v-loading="repeatLoading" border style="width: 100%">
|
||||
<el-table-column prop="trilateralId" label="商品ID" width="180" />
|
||||
<el-table-column label="商品图片" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-image style="width: 50px; height: 50px" :src="row.img" fit="cover" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="商品名称" show-overflow-tooltip />
|
||||
<el-table-column prop="isbn" label="商品编码" width="150" />
|
||||
<el-table-column prop="stock" label="库存" width="80" />
|
||||
<el-table-column prop="isOnSale" label="是否在售" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.isOnSale === '1' ? '是' : '否' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="finishTime" label="创建时间" width="180" />
|
||||
</el-table>
|
||||
|
||||
<template #footer>
|
||||
<el-pagination v-model:current-page="repeatQuery.pageNum" v-model:page-size="repeatQuery.pageSize"
|
||||
:total="repeatTotal" layout="total, sizes, prev, pager, next, jumper" @size-change="handleRepeatSizeChange"
|
||||
@current-change="handleRepeatCurrentChange" />
|
||||
<el-button type="danger" :loading="buttonLoading" @click="batchOffShelf">批量下架</el-button>
|
||||
<el-button @click="repeatDataDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加或修改充值对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="userRechargeFormRef" :rules="rules" label-width="80px">
|
||||
<el-form-item label="支付方式" prop="rechargType">
|
||||
<el-select v-model="rechargType" placeholder="请选择支付方式">
|
||||
<el-option v-for="dict in t_recharge_way" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<span style="color: red; font-size: 14px; margin-left: 12px">{{ rechargText }}</span>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="tongBuDetail">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="dialog.titlePrcode" v-model="dialog.visiblePrcode" width="360px" append-to-body>
|
||||
<div>
|
||||
<img :src="qrCodeText" alt="Base64 图片" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup name="Notice">
|
||||
import { ref, reactive, onMounted, toRefs } from 'vue';
|
||||
import { pddGoodsApi } from '@/api/modules/pddGoods';
|
||||
import { taskApi } from '@/api/modules/task';
|
||||
const { getShopGoodsTask, getRepeatData, selectTaskStatusByTaskType, getShopTaskAllNum } = taskApi;
|
||||
import { userRechargeApi } from '@/api/modules/userRecharge';
|
||||
const {
|
||||
listUserRecharge,
|
||||
getUserRecharge,
|
||||
delUserRecharge,
|
||||
addUserRecharge,
|
||||
updateUserRecharge,
|
||||
userRecharge,
|
||||
checkTask,
|
||||
editRechargeToError,
|
||||
getConfigKey
|
||||
} = userRechargeApi;
|
||||
import { shopApi } from '@/api/modules/shop';
|
||||
const { encrypUrlMenthod, getListShop, getVerifyPriceUrl } = shopApi;
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
|
||||
// 添加响应式数据
|
||||
const verifyPriceDialog = ref(false);
|
||||
const verifyPriceUrl = ref('');
|
||||
const shopTotalCount = ref('');
|
||||
const loadingVerifyUrl = ref(false);
|
||||
const rechargType = ref('');
|
||||
const qrCodeText = ref('');
|
||||
const rechargText = ref('');
|
||||
|
||||
// 移除proxy相关代码,直接使用响应式数据
|
||||
const t_notice_status = ref([]);
|
||||
const t_recharge_way = ref([]);
|
||||
|
||||
const pddGoodsList = ref([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(false);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const shopId = ref('');
|
||||
const loadingText = ref('正在加载数据');
|
||||
|
||||
const queryFormRef = ref();
|
||||
const noticeFormRef = ref();
|
||||
const userRechargeFormRef = ref();
|
||||
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const repeatDataDialog = ref(false);
|
||||
const repeatLoading = ref(false);
|
||||
const repeatDataList = ref([]);
|
||||
const repeatTotal = ref(0);
|
||||
const repeatQuery = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
const selectedRepeatItems = ref([]);
|
||||
|
||||
const initFormData = {
|
||||
created_at: undefined,
|
||||
goods_id: undefined,
|
||||
goods_name: undefined,
|
||||
goods_quantity: undefined,
|
||||
goods_reserve_quantity: undefined,
|
||||
image_url: undefined,
|
||||
is_more_sku: undefined,
|
||||
is_onsale: undefined,
|
||||
sku_list: undefined,
|
||||
thumb_url: undefined,
|
||||
price: undefined,
|
||||
skuCode: undefined
|
||||
};
|
||||
const data = reactive({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
created_at: undefined,
|
||||
goods_id: undefined,
|
||||
goods_name: undefined,
|
||||
goods_quantity: undefined,
|
||||
goods_reserve_quantity: undefined,
|
||||
image_url: undefined,
|
||||
is_more_sku: undefined,
|
||||
is_onsale: undefined,
|
||||
sku_list: undefined,
|
||||
thumb_url: undefined,
|
||||
price: undefined,
|
||||
skuCode: undefined,
|
||||
params: {}
|
||||
}
|
||||
});
|
||||
|
||||
//加密需要的数据
|
||||
const encrypForm = reactive({
|
||||
dataUrl: undefined,
|
||||
shopPrice: undefined,
|
||||
maxPrice: undefined,
|
||||
minPrice: undefined,
|
||||
shopId: undefined,
|
||||
shopType: undefined,
|
||||
totalCount: undefined
|
||||
});
|
||||
|
||||
const pricingLink = ref('');
|
||||
|
||||
const priceName = ref('');
|
||||
|
||||
const { queryParams, form } = toRefs(data);
|
||||
|
||||
//表单校验
|
||||
const encrypFormRef = ref(); // 表单引用
|
||||
const encrypRules = {
|
||||
shopPrice: [
|
||||
{ required: true, message: '请输入店铺优惠', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
const num = Number(value);
|
||||
if (!Number.isInteger(num)) {
|
||||
callback(new Error('必须输入整数'));
|
||||
} else if (num < 0 || num > 20) {
|
||||
callback(new Error('请输入0-20之间的整数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
minPrice: [
|
||||
{ required: true, message: '请输入利润最小值', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (!Number.isInteger(Number(value))) {
|
||||
callback(new Error('必须输入整数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
maxPrice: [
|
||||
{ required: true, message: '请输入利润最大值', trigger: 'blur' },
|
||||
{
|
||||
validator: function (rule, value, callback) {
|
||||
const min = Number(encrypForm.minPrice);
|
||||
const max = Number(value);
|
||||
if (!Number.isInteger(max)) {
|
||||
callback(new Error('必须输入整数'));
|
||||
} else if (max <= min) {
|
||||
callback(new Error('最大值必须大于最小值'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}.bind(this),
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/** 查询消息通知列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const isOnsale = queryParams.value.is_onsale ? queryParams.value.is_onsale : '';
|
||||
const res = await pddGoodsApi.getShopGoodsList(shopId.value, isOnsale, queryParams.value.pageNum, queryParams.value.pageSize);
|
||||
|
||||
// 调试信息:打印API返回的原始数据
|
||||
console.log('API返回的原始数据:', res);
|
||||
|
||||
// 处理后端返回的数据结构
|
||||
if (res.data) {
|
||||
pddGoodsList.value = res.data.records || [];
|
||||
total.value = res.data.total || 0;
|
||||
console.log('使用res.data结构,records数量:', pddGoodsList.value.length, '总数:', total.value);
|
||||
} else {
|
||||
// 如果直接返回分页数据结构
|
||||
pddGoodsList.value = res.records || [];
|
||||
total.value = res.total || 0;
|
||||
console.log('使用直接结构,records数量:', pddGoodsList.value.length, '总数:', total.value);
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
dialog.visible = false;
|
||||
};
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData };
|
||||
noticeFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = async () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*/
|
||||
const exportData = async () => {
|
||||
const isOnsale = queryParams.value.is_onsale ? queryParams.value.is_onsale : '';
|
||||
|
||||
proxy?.download(
|
||||
'huidiao/pdd/emportShopGoods',
|
||||
{
|
||||
'shopId': shopId.value,
|
||||
'isOnsale': isOnsale
|
||||
},
|
||||
`baseInfo_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
};
|
||||
|
||||
const createVerifyPriceUrl = async () => {
|
||||
if (!shopId.value) {
|
||||
ElMessage.error('请先选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pddGoodsList.value.length === 0) {
|
||||
proxy?.$modal.msgError('当前店铺没有商品数据');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loadingVerifyUrl.value = true;
|
||||
const allNum = await getShopTaskAllNum(shopId.value, '1');
|
||||
console.log("res1",allNum)
|
||||
if (allNum.data > 0) {
|
||||
verifyPriceUrl.value = shopId.value;
|
||||
shopTotalCount.value = allNum.data;
|
||||
verifyPriceDialog.value = true;
|
||||
} else {
|
||||
ElMessage.error('请先同步店铺数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('生成核价链接出错:', error);
|
||||
ElMessage.error('生成核价链接出错');
|
||||
} finally {
|
||||
loadingVerifyUrl.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 模拟API调用,替换成你实际的API
|
||||
const createVerifyPriceUrlApi = async (shopId) => {
|
||||
// 这里应该是你的实际API调用,例如:
|
||||
return await getVerifyPriceUrl(shopId);
|
||||
};
|
||||
|
||||
const copyVerifyUrl = () => {
|
||||
if (!verifyPriceUrl.value) return;
|
||||
|
||||
navigator.clipboard
|
||||
.writeText(verifyPriceUrl.value)
|
||||
.then(() => {
|
||||
ElMessage.success('链接已复制到剪贴板');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('复制失败:', err);
|
||||
ElMessage.error('复制链接失败');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 详细商品支付选择
|
||||
*/
|
||||
const handleAdd = async () => {
|
||||
const checkRes = await getShopGoodsTask(shopId.value);
|
||||
if (checkRes.code == 200) {
|
||||
//获取总数
|
||||
const totalData = await pddGoodsApi.getShopGoodsTotalNum(shopId.value);
|
||||
|
||||
reset();
|
||||
dialog.visible = true;
|
||||
dialog.title = '充值';
|
||||
rechargText.value = '查询店铺总数据条数:' + totalData.data + '; 充值金额为:' + (Math.ceil((totalData.data / 10000) * 100) / 100).toFixed(2);
|
||||
buttonLoading.value = false;
|
||||
} else {
|
||||
ElMessage.error(checkRes.msg);
|
||||
}
|
||||
};
|
||||
|
||||
const confirmTongBu = () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm('本操作将删除选择店铺的所有商品再从孔网拉取,请谨慎操作,点击确定将执行该操作。', '提示', { type: 'warning' }).then(() => {
|
||||
tongBu();
|
||||
}).catch(() => { });
|
||||
};
|
||||
|
||||
const tongBu = async () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
let sycFlag = 1;
|
||||
const checkRes = await getShopGoodsTask(shopId.value);
|
||||
|
||||
if (checkRes.code == 200) {
|
||||
const res = await pddGoodsApi.createShopGoodsList(shopId.value, sycFlag);
|
||||
ElMessage.success(res.msg);
|
||||
} else {
|
||||
ElMessage.error(checkRes.msg);
|
||||
}
|
||||
};
|
||||
const tongBu1 = async () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
let sycFlag = 2;
|
||||
const checkRes = await getShopGoodsTask(shopId.value);
|
||||
|
||||
if (checkRes.code == 200) {
|
||||
const res = await pddGoodsApi.createShopGoodsList(shopId.value, sycFlag);
|
||||
ElMessage.success(res.msg);
|
||||
} else {
|
||||
ElMessage.error(checkRes.msg);
|
||||
}
|
||||
};
|
||||
|
||||
const tongBuDetail = async () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
if (rechargType.value == null || rechargType.value == undefined || rechargType.value == '') {
|
||||
ElMessage.error('请选择支付方式');
|
||||
return;
|
||||
}
|
||||
|
||||
buttonLoading.value = true;
|
||||
//获取总数,生成二维码
|
||||
const totalData = await pddGoodsApi.getShopGoodsTotalNum(shopId.value);
|
||||
|
||||
if (totalData.code == 200 && totalData.data > 0) {
|
||||
//数量除以10000向上取
|
||||
const price = (Math.ceil((totalData.data / 10000) * 100) / 100).toFixed(2);
|
||||
const data = {
|
||||
'rechargType': '1',
|
||||
'rechargPrice': price
|
||||
};
|
||||
const res = await userRecharge(data);
|
||||
|
||||
if (res.code == 200) {
|
||||
qrCodeText.value = 'data:image/png;base64,' + res.data.img;
|
||||
dialog.visiblePrcode = true;
|
||||
dialog.titlePrcode = '支付';
|
||||
//定时器 2分钟持续获取 支付单据状态
|
||||
let count = 0;
|
||||
const maxCount = 40; // 两分钟内,每隔三秒打印一次,总共打印40次
|
||||
let intervalId = setInterval(async () => {
|
||||
if (count < maxCount) {
|
||||
const status = await checkTask(res.data.id);
|
||||
if (status == '1') {
|
||||
count = 80;
|
||||
const res = await pddGoodsApi.createShopGoodsDetailList(shopId.value);
|
||||
ElMessage.success(res.msg);
|
||||
}
|
||||
count++;
|
||||
} else {
|
||||
if (count == 40) {
|
||||
editRechargeToError(res.data.id);
|
||||
}
|
||||
dialog.visible = false;
|
||||
dialog.visiblePrcode = false;
|
||||
qrCodeText.value = undefined;
|
||||
buttonLoading.value = false;
|
||||
getList();
|
||||
clearInterval(intervalId); // 停止定时器
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('未获取到店铺商品数量信息');
|
||||
}
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
const currentPreviewImg = ref(''); // 仅存储当前点击的图片
|
||||
// 点击事件处理
|
||||
const handlePreview = (imgUrl) => {
|
||||
currentPreviewImg.value = imgUrl;
|
||||
};
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const shopList = ref([]);
|
||||
const getShopList = async () => {
|
||||
const res = await getListShop();
|
||||
console.log("res",res)
|
||||
if (res.code === 200 && Array.isArray(res.data)) {
|
||||
shopList.value = res.data.map(item => ({
|
||||
value: item.id,
|
||||
label: item.shopName
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const formatTimestamp = (row, column, timestamp) => {
|
||||
if (!timestamp) return '';
|
||||
|
||||
// 将10位时间戳转为毫秒(JS的Date需要毫秒)
|
||||
const date = new Date(timestamp * 1000);
|
||||
|
||||
// 格式化为 YYYY-MM-DD hh:mm:ss
|
||||
const padZero = (num) => num.toString().padStart(2, '0');
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = padZero(date.getMonth() + 1);
|
||||
const day = padZero(date.getDate());
|
||||
const hours = padZero(date.getHours());
|
||||
const minutes = padZero(date.getMinutes());
|
||||
const seconds = padZero(date.getSeconds());
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
//加密链接生成
|
||||
const encrypMethod = async () => {
|
||||
try {
|
||||
// 1. 执行表单验证
|
||||
await encrypFormRef.value?.validate();
|
||||
|
||||
// 2. 验证通过后,设置加载状态
|
||||
loadingVerifyUrl.value = true;
|
||||
|
||||
// 3. 准备请求数据 - 将元转换为分
|
||||
const requestData = {
|
||||
...encrypForm,
|
||||
shopPrice: Math.round(Number(encrypForm.shopPrice) * 100), // 元转分
|
||||
minPrice: Math.round(Number(encrypForm.minPrice) * 100), // 元转分
|
||||
maxPrice: Math.round(Number(encrypForm.maxPrice) * 100), // 元转分
|
||||
dataUrl: verifyPriceUrl.value,
|
||||
shopId: shopId.value,
|
||||
totalCount: shopTotalCount.value,
|
||||
shopType: '1' // 假设这是拼多多店铺类型
|
||||
};
|
||||
|
||||
// 4. 调用加密接口
|
||||
const res = await encrypUrlMenthod(requestData);
|
||||
|
||||
// 5. 处理结果
|
||||
if (res) {
|
||||
pricingLink.value = res.url;
|
||||
if (res.url != null) {
|
||||
priceName.value = res.name;
|
||||
}
|
||||
ElMessage.success('核价链接生成成功');
|
||||
} else {
|
||||
ElMessage.warning('拼多多以外店铺正在开发中,请重新选择');
|
||||
}
|
||||
} catch (error) {
|
||||
// 验证失败会直接进入catch,不需要额外处理
|
||||
console.error('表单验证失败:', error);
|
||||
} finally {
|
||||
loadingVerifyUrl.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
//一键复制核价链接
|
||||
const copyLink = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(pricingLink.value);
|
||||
ElMessage.success('复制成功');
|
||||
} catch (err) {
|
||||
ElMessage.error('复制失败,请手动复制');
|
||||
}
|
||||
};
|
||||
const closeData = async () => {
|
||||
pricingLink.value = null;
|
||||
encrypForm.dataUrl = null;
|
||||
encrypForm.shopId = null;
|
||||
encrypForm.shopPrice = null;
|
||||
encrypForm.maxPrice = null;
|
||||
encrypForm.minPrice = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* 去重
|
||||
*/
|
||||
|
||||
const repeatData = async () => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
repeatQuery.pageNum = 1;
|
||||
repeatQuery.pageSize = 10;
|
||||
repeatTotal.value = 0;
|
||||
repeatDataList.value = [];
|
||||
buttonLoading.value = false;
|
||||
|
||||
repeatDataDialog.value = true;
|
||||
try {
|
||||
getRepeatDataList();
|
||||
} catch (error) {
|
||||
console.error('获取重复数据失败:', error);
|
||||
ElMessage.error('获取重复数据失败');
|
||||
repeatLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const getRepeatDataList = async () => {
|
||||
repeatLoading.value = true;
|
||||
const res = await getRepeatData(shopId.value, repeatQuery.pageNum, repeatQuery.pageSize);
|
||||
// 处理后端返回的数据结构
|
||||
if (res.data) {
|
||||
repeatDataList.value = res.data.records || [];
|
||||
repeatTotal.value = res.data.total || 0;
|
||||
} else {
|
||||
// 如果直接返回分页数据结构
|
||||
repeatDataList.value = res.records || [];
|
||||
repeatTotal.value = res.total || 0;
|
||||
}
|
||||
repeatLoading.value = false;
|
||||
};
|
||||
|
||||
// 添加分页相关方法
|
||||
const handleRepeatSizeChange = (val) => {
|
||||
repeatQuery.pageSize = val;
|
||||
getRepeatDataList();
|
||||
};
|
||||
|
||||
const handleRepeatCurrentChange = (val) => {
|
||||
repeatQuery.pageNum = val;
|
||||
getRepeatDataList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 整店上/下架
|
||||
*/
|
||||
const editIsOnSale = async (isOnSale) => {
|
||||
if (shopId.value == null || shopId.value == undefined || shopId.value == '') {
|
||||
ElMessage.error('请选择店铺');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await pddGoodsApi.editShopGoodsAllByIsOnSale(shopId.value, isOnSale);
|
||||
|
||||
if (res.code == 200) {
|
||||
ElMessage.success(res.msg);
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量下架任务
|
||||
*/
|
||||
const batchOffShelf = async () => {
|
||||
buttonLoading.value = true;
|
||||
const check = await selectTaskStatusByTaskType(shopId.value, 'BATCH_SET_SOLD_OUT');
|
||||
if (check.code == 200) {
|
||||
const res = await pddGoodsApi.batchSetSoldOut(shopId.value);
|
||||
repeatDataDialog.value = false;
|
||||
buttonLoading.value = false;
|
||||
ElMessage.success(res.msg);
|
||||
} else {
|
||||
ElMessage.error(check.msg);
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getShopList();
|
||||
});
|
||||
|
||||
// 翻新上架相关变量
|
||||
const renovateDialogVisible = ref(false); // 弹窗显示控制
|
||||
const uploadFile = ref(); // 上传文件引用
|
||||
const fileList = ref([]); // 文件列表
|
||||
const uploading = ref(false); // 上传状态
|
||||
|
||||
// 显示翻新上架弹窗
|
||||
const showRenovateDialog = () => {
|
||||
if (!shopId.value) {
|
||||
proxy?.$modal.msgError('请先选择店铺');
|
||||
return;
|
||||
}
|
||||
renovateDialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 处理文件上传
|
||||
const handleUpload = async () => {
|
||||
if (fileList.value.length === 0) {
|
||||
ElMessage.error('请先选择CSV文件');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
uploading.value = true;
|
||||
const file = fileList.value[0].raw;
|
||||
const res = await batchRenovateOnSaleByCsv(file, shopId.value);
|
||||
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.msg || '已受理翻新上架请求');
|
||||
renovateDialogVisible.value = false;
|
||||
fileList.value = []; // 清空文件列表
|
||||
} else {
|
||||
ElMessage.error(res.msg || '翻新上架失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('翻新上架出错:', error);
|
||||
ElMessage.error('翻新上架出错');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 文件上传前校验
|
||||
const beforeUpload = (file) => {
|
||||
const isCSV = file.type === 'text/csv' || file.name.endsWith('.csv');
|
||||
if (!isCSV) {
|
||||
ElMessage.error('只能上传CSV格式文件');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 文件变化处理
|
||||
const handleFileChange = (file, fileList) => {
|
||||
uploadFile.value = file;
|
||||
fileList.value = fileList.slice(-1); // 只保留最新上传的文件
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 文本溢出处理 */
|
||||
.truncate-cell {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.verify-price-dialog {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.url-display {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tips p {
|
||||
margin: 5px 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.upload-demo {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
1442
src/views/shopOrder/index.vue
Normal file
1442
src/views/shopOrder/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user