Merge branch 'dev2' of https://git.gpxscs.cn/front/java-mall-admin into dev2
This commit is contained in:
commit
68cbfe3bc1
@ -5,5 +5,5 @@
|
||||
window.ver = "2.0.278";
|
||||
window.SYS = {CONFIG:{}, URL:{}};</script><script>window._AMapSecurityConfig = {
|
||||
securityJsCode:"07788e7ebd7e913985722bfc5986999f"
|
||||
}</script><script src="https://mall.gpxscs.cn/admin/config.js?v=2.0.278"></script><script src="https://mall.gpxscs.cn/admin/im/libs3.6.0.min.js?v=2.0.278"></script><script src="https://mall.gpxscs.cn/admin/im/im.js?v=2.0.278"></script><link href="static/css/chunk-19648027.83a11e8c.css" rel="prefetch"><link href="static/css/chunk-3b9411e6.b0d59fca.css" rel="prefetch"><link href="static/css/vab-extra.9da8d2d7.css" rel="prefetch"><link href="static/js/chunk-19648027.6233a553.js" rel="prefetch"><link href="static/js/chunk-3b9411e6.008e954c.js" rel="prefetch"><link href="static/js/vab-extra.29abc81b.js" rel="prefetch"><link href="static/css/app.d3766ec2.css" rel="preload" as="style"><link href="static/css/element-ui.0e3a750b.css" rel="preload" as="style"><link href="static/js/app.7aab1e38.js" rel="preload" as="script"><link href="static/js/element-ui.4e8e0db4.js" rel="preload" as="script"><link href="static/js/vue.11eaebc3.js" rel="preload" as="script"><link href="static/css/element-ui.0e3a750b.css" rel="stylesheet"><link href="static/css/app.d3766ec2.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="img/icons/favicon-16x16.png"><link rel="manifest" href="manifest.json"><meta name="theme-color" content="#ffffff"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="xiaofa-admin"><link rel="apple-touch-icon" href="img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="img/icons/safari-pinned-tab.svg" color="#ffffff"><meta name="msapplication-TileImage" content="img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#ffffff"></head><body><noscript></noscript><div id="app"><div class="first-loading-wrp"><div class="loading-wrp"><span class="dot dot-spin"><i></i> <i></i> <i></i> <i></i></span></div><h1>小发同城</h1></div></div><script>if (window.location.hostname !== 'localhost') {
|
||||
}</script><script src="static/js/element-ui.4e8e0db4.js"></script><script src="static/js/vue.11eaebc3.js"></script><script src="static/js/app.7aab1e38.js"></script></body></html>
|
||||
}</script><script src="https://mall.gpxscs.cn/admin/config.js?v=2.0.278"></script><script src="https://mall.gpxscs.cn/admin/im/libs3.6.0.min.js?v=2.0.278"></script><script src="https://mall.gpxscs.cn/admin/im/im.js?v=2.0.278"></script><link href="static/css/chunk-19648027.83a11e8c.css" rel="prefetch"><link href="static/css/chunk-801acd4c.afe24c41.css" rel="prefetch"><link href="static/css/vab-extra.9da8d2d7.css" rel="prefetch"><link href="static/js/chunk-19648027.6233a553.js" rel="prefetch"><link href="static/js/chunk-801acd4c.760f3270.js" rel="prefetch"><link href="static/js/vab-extra.29abc81b.js" rel="prefetch"><link href="static/css/app.d3766ec2.css" rel="preload" as="style"><link href="static/css/element-ui.0e3a750b.css" rel="preload" as="style"><link href="static/js/app.df3b691f.js" rel="preload" as="script"><link href="static/js/element-ui.4e8e0db4.js" rel="preload" as="script"><link href="static/js/vue.11eaebc3.js" rel="preload" as="script"><link href="static/css/element-ui.0e3a750b.css" rel="stylesheet"><link href="static/css/app.d3766ec2.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="img/icons/favicon-16x16.png"><link rel="manifest" href="manifest.json"><meta name="theme-color" content="#ffffff"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="xiaofa-admin"><link rel="apple-touch-icon" href="img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="img/icons/safari-pinned-tab.svg" color="#ffffff"><meta name="msapplication-TileImage" content="img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#ffffff"></head><body><noscript></noscript><div id="app"><div class="first-loading-wrp"><div class="loading-wrp"><span class="dot dot-spin"><i></i> <i></i> <i></i> <i></i></span></div><h1>小发同城</h1></div></div><script>if (window.location.hostname !== 'localhost') {
|
||||
}</script><script src="static/js/element-ui.4e8e0db4.js"></script><script src="static/js/vue.11eaebc3.js"></script><script src="static/js/app.df3b691f.js"></script></body></html>
|
||||
@ -2376,7 +2376,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "im/libs3.6.0.min.js"
|
||||
},
|
||||
{
|
||||
"revision": "42aa58b41d3e5a7ee51d3813266b1755",
|
||||
"revision": "352e407a09c074af51ec5ea2b89edb64",
|
||||
"url": "index.html"
|
||||
},
|
||||
{
|
||||
@ -2392,7 +2392,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "robots.txt"
|
||||
},
|
||||
{
|
||||
"revision": "319d08d5594ace9aaf2d",
|
||||
"revision": "7b4e1047aabe7f32a5f9",
|
||||
"url": "static/css/app.d3766ec2.css"
|
||||
},
|
||||
{
|
||||
@ -2400,8 +2400,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "static/css/chunk-19648027.83a11e8c.css"
|
||||
},
|
||||
{
|
||||
"revision": "205d59c37c9ea360b608",
|
||||
"url": "static/css/chunk-3b9411e6.b0d59fca.css"
|
||||
"revision": "054187581134215965fa",
|
||||
"url": "static/css/chunk-801acd4c.afe24c41.css"
|
||||
},
|
||||
{
|
||||
"revision": "7b9212a0410ce12f6058",
|
||||
@ -2636,16 +2636,16 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
"url": "static/img/xiaofa-logo.20439423.png"
|
||||
},
|
||||
{
|
||||
"revision": "319d08d5594ace9aaf2d",
|
||||
"url": "static/js/app.7aab1e38.js"
|
||||
"revision": "7b4e1047aabe7f32a5f9",
|
||||
"url": "static/js/app.df3b691f.js"
|
||||
},
|
||||
{
|
||||
"revision": "f5dd29b853f67685e75d",
|
||||
"url": "static/js/chunk-19648027.6233a553.js"
|
||||
},
|
||||
{
|
||||
"revision": "205d59c37c9ea360b608",
|
||||
"url": "static/js/chunk-3b9411e6.008e954c.js"
|
||||
"revision": "054187581134215965fa",
|
||||
"url": "static/js/chunk-801acd4c.760f3270.js"
|
||||
},
|
||||
{
|
||||
"revision": "7b9212a0410ce12f6058",
|
||||
@ -14,7 +14,7 @@
|
||||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||
|
||||
importScripts(
|
||||
"precache-manifest.073b518e041ab2c5f645b4dac923d8c8.js"
|
||||
"precache-manifest.025fd2536572cf5272c5c580bcfc1a00.js"
|
||||
);
|
||||
|
||||
workbox.core.setCacheNameDetails({prefix: "xiaofa-admin"});
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* build: xiaofa-admin
|
||||
* copyright: https://www.lancerdt.com
|
||||
* time: 2025-12-24 11:47:55
|
||||
* time: 2025-12-30 11:59:51
|
||||
*/
|
||||
/*!
|
||||
* Quill Editor v1.3.7
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* build: xiaofa-admin
|
||||
* copyright: https://www.lancerdt.com
|
||||
* time: 2025-12-24 11:47:55
|
||||
* time: 2025-12-30 11:59:51
|
||||
*/@media only screen and (max-width:767px){.hidden-xs-only{display:none!important}}@media only screen and (min-width:768px){.hidden-sm-and-up{display:none!important}}@media only screen and (min-width:768px) and (max-width:991px){.hidden-sm-only{display:none!important}}@media only screen and (max-width:991px){.hidden-sm-and-down{display:none!important}}@media only screen and (min-width:992px){.hidden-md-and-up{display:none!important}}@media only screen and (min-width:992px) and (max-width:1199px){.hidden-md-only{display:none!important}}@media only screen and (max-width:1199px){.hidden-md-and-down{display:none!important}}@media only screen and (min-width:1200px){.hidden-lg-and-up{display:none!important}}@media only screen and (min-width:1200px) and (max-width:1919px){.hidden-lg-only{display:none!important}}@media only screen and (max-width:1919px){.hidden-lg-and-down{display:none!important}}@media only screen and (min-width:1920px){.hidden-xl-only{display:none!important}}
|
||||
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* build: xiaofa-admin
|
||||
* copyright: https://www.lancerdt.com
|
||||
* time: 2025-12-24 11:47:55
|
||||
* time: 2025-12-30 11:59:51
|
||||
*/[data-v-28093814]:export{menu-color:#fff;menu-color-active:#fff;menu-background:#282c34;column-second-menu-background:#fff}.vab-avatar-list[data-v-28093814] .el-avatar{display:inline-block;margin-left:-15px;cursor:pointer;border:3px solid #fff}.echarts{width:600px;height:400px}[data-v-7f7baab5]:export{menu-color:#fff;menu-color-active:#fff;menu-background:#282c34;column-second-menu-background:#fff}@media only screen and (max-width:767px){[data-v-7f7baab5] .vab-cropper-canvas{display:block;float:none;margin:0 auto}[data-v-7f7baab5] .vab-cropper-preview{display:none}}[data-v-7f7baab5] .el-textarea{margin-top:20px}[data-v-7f7baab5] .el-dialog__footer{height:72px}[data-v-7f7baab5] .el-dialog__footer:before{display:block;clear:both;content:""}[data-v-7f7baab5] .el-dialog__footer>div>div{display:inline}[data-v-7f7baab5] .el-dialog__footer>div>div .el-upload-list{display:none}[data-v-7f7baab5] .el-dialog__footer>div>div .el-upload--picture-card{float:right;width:auto;height:32px;line-height:32px;vertical-align:middle;background-color:transparent;border:0;border-radius:0}[data-v-7f7baab5] .el-dialog__footer>div .el-button{float:right;margin-left:10px}.icon-selector-popper .el-card__body{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;height:20px;cursor:pointer}.icon-selector-popper .el-card__body i{font-size:28px;color:rgba(0,0,0,.65);text-align:center;vertical-align:middle;pointer-events:none;cursor:pointer}.icon-selector-popper .el-pagination{margin:0}[data-v-3aef4cea]:export{menu-color:#fff;menu-color-active:#fff;menu-background:#282c34;column-second-menu-background:#fff}.upload[data-v-3aef4cea]{height:500px}.upload .upload-content .el-upload__tip[data-v-3aef4cea]{display:block;height:30px;line-height:30px}.upload .upload-content[data-v-3aef4cea] .el-upload--picture-card{width:128px;height:128px;margin:3px 8px 8px 8px;border:2px dashed #c0ccda}.upload .upload-content[data-v-3aef4cea] .el-upload-list--picture{margin-bottom:20px}.upload .upload-content[data-v-3aef4cea] .el-upload-list--picture-card .el-upload-list__item{width:128px;height:128px;margin:3px 8px 8px 8px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
admin/static/js/chunk-801acd4c.760f3270.js
Normal file
6
admin/static/js/chunk-801acd4c.760f3270.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -45,6 +45,28 @@ export async function downloadTempGoods() {
|
||||
responseType: 'blob',
|
||||
})
|
||||
}
|
||||
//商品导入 下载三个模板
|
||||
export async function downloadBrandTemplate() {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/brandTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
})
|
||||
}
|
||||
export async function downloadCategoryTemplate() {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/categoryTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
})
|
||||
}
|
||||
export async function downloadGoodsTemplate() {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/shopTemplate',
|
||||
method: 'get',
|
||||
responseType: 'blob',
|
||||
})
|
||||
}
|
||||
export async function exportUncheckShopData(storeId) {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-productMapper/exportUncheckShopData',
|
||||
@ -128,6 +150,37 @@ export async function importGoodsData(data) {
|
||||
data,
|
||||
})
|
||||
}
|
||||
//商品导入的三个导入
|
||||
export async function categoryImportData(data) {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/categoryImportData',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
data,
|
||||
})
|
||||
}
|
||||
export async function brandImportData(data) {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/brandImportData',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
data,
|
||||
})
|
||||
}
|
||||
export async function shopImportData(data) {
|
||||
return request({
|
||||
url: '/admin/shop/shop-sync-import/shopImportData',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export async function syncShopImages(data) {
|
||||
data = stringify(data)
|
||||
@ -169,5 +222,11 @@ export default {
|
||||
importGoodsData,
|
||||
syncShopImages,
|
||||
getImgList,
|
||||
saveBatchBarcode
|
||||
saveBatchBarcode,
|
||||
downloadBrandTemplate,
|
||||
downloadCategoryTemplate,
|
||||
downloadGoodsTemplate,
|
||||
categoryImportData,
|
||||
brandImportData,
|
||||
shopImportData
|
||||
}
|
||||
|
||||
36
src/api/syncApp.js
Normal file
36
src/api/syncApp.js
Normal file
@ -0,0 +1,36 @@
|
||||
import request from '@/utils/request'
|
||||
import { stringify } from 'qs'
|
||||
|
||||
export async function getSyncAppList() {
|
||||
return request({
|
||||
url: '/admin/shop/sync-app/list',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
export async function saveSyncApp(data) {
|
||||
return request({
|
||||
url: '/admin/shop/sync-app/saveSyncApp',
|
||||
method: 'post',
|
||||
data:data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
export async function editSyncApp(data) {
|
||||
return request({
|
||||
url: '/admin/shop/sync-app/editSyncApp',
|
||||
method: 'put',
|
||||
data:data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
export async function deleteSyncApp(syncId) {
|
||||
return request({
|
||||
url: '/admin/shop/sync-app/delSyncApp',
|
||||
method: 'delete',
|
||||
params: { syncAppId: syncId },
|
||||
})
|
||||
}
|
||||
@ -34,7 +34,7 @@ export function convertRouter(asyncRoutes) {
|
||||
const obj = {
|
||||
path: '/goodsImgs',
|
||||
component: '@/views/product/goodsImg/goodsImgs',
|
||||
name: 'Vab88000',
|
||||
name: 'Vab88003',
|
||||
redirect: null,
|
||||
meta: {
|
||||
title: '商品图库管理',
|
||||
@ -46,6 +46,23 @@ export function convertRouter(asyncRoutes) {
|
||||
}
|
||||
route.children.push(obj)
|
||||
}
|
||||
if (route.meta.title == '商品' && route.name == 'Vab320') {
|
||||
const obj = {
|
||||
path: '/goodsImport',
|
||||
component: '@/views/product/goodsImport/index',
|
||||
name: 'Vab88004',
|
||||
redirect: null,
|
||||
meta: {
|
||||
title: '商品导入管理',
|
||||
icon: '',
|
||||
noClosable: 0,
|
||||
hidden: null,
|
||||
},
|
||||
menuHidden: false,
|
||||
}
|
||||
|
||||
route.children.push(obj)
|
||||
}
|
||||
if (route.meta.title == '店铺' && route.name == 'Vab330') {
|
||||
const obj = {
|
||||
path: '/storeConf',
|
||||
@ -63,6 +80,23 @@ export function convertRouter(asyncRoutes) {
|
||||
|
||||
route.children.push(obj)
|
||||
}
|
||||
if (route.meta.title == '店铺' && route.name == 'Vab330') {
|
||||
const obj = {
|
||||
path: '/SyncApp',
|
||||
component: '@/views/store/storeSyncApp/index',
|
||||
name: 'Vab88001',
|
||||
redirect: null,
|
||||
meta: {
|
||||
title: '店铺密钥配置',
|
||||
icon: '',
|
||||
noClosable: 0,
|
||||
hidden: null,
|
||||
},
|
||||
menuHidden: false,
|
||||
}
|
||||
|
||||
route.children.push(obj)
|
||||
}
|
||||
|
||||
if (route.meta.title == '店铺' && route.name == 'Vab330') {
|
||||
const obj = {
|
||||
|
||||
199
src/views/product/goodsImport/importBrand.vue
Normal file
199
src/views/product/goodsImport/importBrand.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="品牌数据导入"
|
||||
width="50%"
|
||||
:visible.sync="visible"
|
||||
height="300px"
|
||||
>
|
||||
<div style="display: flex; align-items: center; margin-bottom: 20px;">
|
||||
<el-select
|
||||
v-model="filter.storeId"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="选择店铺"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in shopList"
|
||||
:key="item.store_id"
|
||||
:label="item.store_name"
|
||||
:value="item.store_id"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<div style="margin-left: 10px; position: relative;">
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
accept=".xlsx,.xls"
|
||||
style="display: none;"
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
<el-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click="openFileSelector"
|
||||
>
|
||||
选择文件
|
||||
</el-button>
|
||||
<span v-if="fileName" style="margin-left: 10px; font-size: 12px;">
|
||||
{{ fileName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="uploadMessage" :style="{ color: uploadMessageType === 'success' ? 'green' : 'red', fontSize: '12px', marginTop: '10px' }">
|
||||
{{ uploadMessage }}
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handlerImportCategory"
|
||||
:disabled="!filter.storeId || !selectedFile"
|
||||
>
|
||||
导入
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
|
||||
export default {
|
||||
name: 'importCategory',
|
||||
data() {
|
||||
return {
|
||||
filter: {
|
||||
productName: '',
|
||||
storeId: '',
|
||||
},
|
||||
visible: false,
|
||||
shopList: [],
|
||||
selectedFile: null,
|
||||
fileName: '',
|
||||
uploadMessage: '',
|
||||
uploadMessageType: '' // 提示类型 success/error
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.visible = true
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.uploadMessageType = ''
|
||||
},
|
||||
async getShopList() {
|
||||
try {
|
||||
let res = await GoodsToolApi.getShopList()
|
||||
this.shopList = res.data.items || []
|
||||
} catch (error) {
|
||||
console.error('获取店铺列表失败:', error)
|
||||
}
|
||||
},
|
||||
// 打开文件选择器
|
||||
openFileSelector() {
|
||||
this.$refs.fileInput.click()
|
||||
},
|
||||
// 处理文件选择
|
||||
handleFileChange(e) {
|
||||
const file = e.target.files[0]
|
||||
if (file) {
|
||||
// 校验文件类型
|
||||
const fileExt = file.name.split('.').pop().toLowerCase()
|
||||
if (fileExt !== 'xlsx' && fileExt !== 'xls') {
|
||||
this.uploadMessage = '请选择Excel文件(.xlsx/.xls)'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
// 清空input值,以便可以重新选择同一个文件
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
// 校验文件大小
|
||||
const maxSize = 5 * 1024 * 1024 // 5MB
|
||||
if (file.size > maxSize) {
|
||||
this.uploadMessage = '文件大小不能超过5MB'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
this.selectedFile = file
|
||||
this.fileName = file.name
|
||||
this.uploadMessage = '' // 清空错误提示
|
||||
}
|
||||
},
|
||||
|
||||
async handlerImportCategory() {
|
||||
if (!this.filter.storeId) {
|
||||
this.uploadMessage = '请先选择店铺'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.selectedFile) {
|
||||
this.uploadMessage = '请先选择要上传的Excel文件'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', this.selectedFile)
|
||||
formData.append('storeId', this.filter.storeId)
|
||||
|
||||
this.uploadMessage = '正在上传文件,请稍候...'
|
||||
this.uploadMessageType = 'success'
|
||||
|
||||
const res = await GoodsToolApi.brandImportData(formData)
|
||||
|
||||
if (res.status == 200 || res.success) {
|
||||
this.uploadMessage = '文件上传成功!'
|
||||
this.uploadMessageType = 'success'
|
||||
// 清空文件选择
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
this.$message.success('导入品牌成功!')
|
||||
this.visible=false
|
||||
} else {
|
||||
this.uploadMessage = res.msg || '文件上传失败,请重试'
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
} catch (error) {
|
||||
this.uploadMessage = '文件上传失败:' + (error.message || '网络错误')
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.visible = false
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.filter.storeId = ''
|
||||
if (this.$refs.fileInput) {
|
||||
this.$refs.fileInput.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-dialog {
|
||||
height: 300px !important;
|
||||
}
|
||||
</style>
|
||||
201
src/views/product/goodsImport/importCategory.vue
Normal file
201
src/views/product/goodsImport/importCategory.vue
Normal file
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="商品分类数据导入"
|
||||
width="50%"
|
||||
:visible.sync="visible"
|
||||
height="300px"
|
||||
>
|
||||
<div style="display: flex; align-items: center; margin-bottom: 20px;">
|
||||
<el-select
|
||||
v-model="filter.storeId"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="选择店铺"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in shopList"
|
||||
:key="item.store_id"
|
||||
:label="item.store_name"
|
||||
:value="item.store_id"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<div style="margin-left: 10px; position: relative;">
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
accept=".xlsx,.xls"
|
||||
style="display: none;"
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
<el-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click="openFileSelector"
|
||||
>
|
||||
选择文件
|
||||
</el-button>
|
||||
<span v-if="fileName" style="margin-left: 10px; font-size: 12px;">
|
||||
{{ fileName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="uploadMessage" :style="{ color: uploadMessageType === 'success' ? 'green' : 'red', fontSize: '12px', marginTop: '10px' }">
|
||||
{{ uploadMessage }}
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handlerImportCategory"
|
||||
:disabled="!filter.storeId || !selectedFile"
|
||||
>
|
||||
导入
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
|
||||
export default {
|
||||
name: 'importCategory',
|
||||
data() {
|
||||
return {
|
||||
filter: {
|
||||
productName: '',
|
||||
storeId: '',
|
||||
},
|
||||
visible: false,
|
||||
shopList: [],
|
||||
selectedFile: null,
|
||||
fileName: '',
|
||||
uploadMessage: '',
|
||||
uploadMessageType: '' // 提示类型 success/error
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.visible = true
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.uploadMessageType = ''
|
||||
},
|
||||
async getShopList() {
|
||||
try {
|
||||
let res = await GoodsToolApi.getShopList()
|
||||
this.shopList = res.data.items || []
|
||||
} catch (error) {
|
||||
console.error('获取店铺列表失败:', error)
|
||||
}
|
||||
},
|
||||
// 打开文件选择器
|
||||
openFileSelector() {
|
||||
this.$refs.fileInput.click()
|
||||
},
|
||||
// 处理文件选择
|
||||
handleFileChange(e) {
|
||||
const file = e.target.files[0]
|
||||
if (file) {
|
||||
// 校验文件类型
|
||||
const fileExt = file.name.split('.').pop().toLowerCase()
|
||||
if (fileExt !== 'xlsx' && fileExt !== 'xls') {
|
||||
this.uploadMessage = '请选择Excel文件(.xlsx/.xls)'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
// 清空input值,以便可以重新选择同一个文件
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
// 校验文件大小
|
||||
const maxSize = 5 * 1024 * 1024 // 5MB
|
||||
if (file.size > maxSize) {
|
||||
this.uploadMessage = '文件大小不能超过5MB'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
this.selectedFile = file
|
||||
this.fileName = file.name
|
||||
this.uploadMessage = '' // 清空错误提示
|
||||
}
|
||||
},
|
||||
|
||||
async handlerImportCategory() {
|
||||
if (!this.filter.storeId) {
|
||||
this.uploadMessage = '请先选择店铺'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.selectedFile) {
|
||||
this.uploadMessage = '请先选择要上传的Excel文件'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', this.selectedFile)
|
||||
formData.append('storeId', this.filter.storeId)
|
||||
|
||||
this.uploadMessage = '正在上传文件,请稍候...'
|
||||
this.uploadMessageType = 'success'
|
||||
|
||||
const res = await GoodsToolApi.categoryImportData(formData)
|
||||
console.log("?????",res)
|
||||
if (res.status === 200) {
|
||||
this.uploadMessage = '文件上传成功!'
|
||||
this.uploadMessageType = 'success'
|
||||
// 清空文件选择
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
|
||||
this.$message.success('导入分类成功!')
|
||||
this.visible=false
|
||||
} else {
|
||||
this.uploadMessage = res.msg || '文件上传失败,请重试'
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('文件上传失败:', error)
|
||||
this.uploadMessage = '文件上传失败:' + (error.message || '网络错误')
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.visible = false
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.filter.storeId = ''
|
||||
if (this.$refs.fileInput) {
|
||||
this.$refs.fileInput.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-dialog {
|
||||
height: 300px !important;
|
||||
}
|
||||
</style>
|
||||
201
src/views/product/goodsImport/importGoods.vue
Normal file
201
src/views/product/goodsImport/importGoods.vue
Normal file
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="品牌数据导入"
|
||||
width="50%"
|
||||
:visible.sync="visible"
|
||||
height="300px"
|
||||
>
|
||||
<div style="display: flex; align-items: center; margin-bottom: 20px;">
|
||||
<el-select
|
||||
v-model="filter.storeId"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="选择店铺"
|
||||
style="width: 200px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in shopList"
|
||||
:key="item.store_id"
|
||||
:label="item.store_name"
|
||||
:value="item.store_id"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<div style="margin-left: 10px; position: relative;">
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
accept=".xlsx,.xls"
|
||||
style="display: none;"
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
<el-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click="openFileSelector"
|
||||
>
|
||||
选择文件
|
||||
</el-button>
|
||||
<span v-if="fileName" style="margin-left: 10px; font-size: 12px;">
|
||||
{{ fileName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="uploadMessage" :style="{ color: uploadMessageType === 'success' ? 'green' : 'red', fontSize: '12px', marginTop: '10px' }">
|
||||
{{ uploadMessage }}
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handlerImportCategory"
|
||||
:disabled="!filter.storeId || !selectedFile"
|
||||
>
|
||||
导入
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
|
||||
export default {
|
||||
name: 'importCategory',
|
||||
data() {
|
||||
return {
|
||||
filter: {
|
||||
productName: '',
|
||||
storeId: '',
|
||||
},
|
||||
visible: false,
|
||||
shopList: [],
|
||||
selectedFile: null,
|
||||
fileName: '',
|
||||
uploadMessage: '',
|
||||
uploadMessageType: '' // 提示类型 success/error
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.visible = true
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.uploadMessageType = ''
|
||||
},
|
||||
async getShopList() {
|
||||
try {
|
||||
let res = await GoodsToolApi.getShopList()
|
||||
this.shopList = res.data.items || []
|
||||
} catch (error) {
|
||||
console.error('获取店铺列表失败:', error)
|
||||
}
|
||||
},
|
||||
// 打开文件选择器
|
||||
openFileSelector() {
|
||||
this.$refs.fileInput.click()
|
||||
},
|
||||
// 处理文件选择
|
||||
handleFileChange(e) {
|
||||
const file = e.target.files[0]
|
||||
if (file) {
|
||||
// 校验文件类型
|
||||
const fileExt = file.name.split('.').pop().toLowerCase()
|
||||
if (fileExt !== 'xlsx' && fileExt !== 'xls') {
|
||||
this.uploadMessage = '请选择Excel文件(.xlsx/.xls)'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
// 清空input值,以便可以重新选择同一个文件
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
// 校验文件大小
|
||||
const maxSize = 5 * 1024 * 1024 // 5MB
|
||||
if (file.size > maxSize) {
|
||||
this.uploadMessage = '文件大小不能超过5MB'
|
||||
this.uploadMessageType = 'error'
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
this.selectedFile = file
|
||||
this.fileName = file.name
|
||||
this.uploadMessage = '' // 清空错误提示
|
||||
}
|
||||
},
|
||||
|
||||
async handlerImportCategory() {
|
||||
if (!this.filter.storeId) {
|
||||
this.uploadMessage = '请先选择店铺'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.selectedFile) {
|
||||
this.uploadMessage = '请先选择要上传的Excel文件'
|
||||
this.uploadMessageType = 'error'
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', this.selectedFile)
|
||||
formData.append('storeId', this.filter.storeId)
|
||||
|
||||
this.uploadMessage = '正在上传文件,请稍候...'
|
||||
this.uploadMessageType = 'success'
|
||||
|
||||
const res = await GoodsToolApi.shopImportData(formData)
|
||||
|
||||
if (res.status == 200) {
|
||||
this.uploadMessage = '文件上传成功!'
|
||||
this.uploadMessageType = 'success'
|
||||
// 清空文件选择
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.$refs.fileInput.value = ''
|
||||
|
||||
this.$message.success('导入商品数据成功!')
|
||||
this.visible=false
|
||||
} else {
|
||||
this.uploadMessage = res.msg || '文件上传失败,请重试'
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('文件上传失败:', error)
|
||||
this.uploadMessage = '文件上传失败:' + (error.message || '网络错误')
|
||||
this.uploadMessageType = 'error'
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.visible = false
|
||||
this.selectedFile = null
|
||||
this.fileName = ''
|
||||
this.uploadMessage = ''
|
||||
this.filter.storeId = ''
|
||||
if (this.$refs.fileInput) {
|
||||
this.$refs.fileInput.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-dialog {
|
||||
height: 300px !important;
|
||||
}
|
||||
</style>
|
||||
115
src/views/product/goodsImport/index.vue
Normal file
115
src/views/product/goodsImport/index.vue
Normal file
@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="goods_tool_container">
|
||||
<div class="list">
|
||||
<div class="tool">
|
||||
<el-button type="primary" @click="downloadBrandTemplate">品牌模板下载</el-button>
|
||||
|
||||
<el-button type="success" @click="downloadCategoryTemplate">商品分类导入模板下载</el-button>
|
||||
<el-button plain size="mini" type="info" @click="downloadGoodsTemplate">商品导入模板下载</el-button>
|
||||
|
||||
<el-button type="warning" @click="openBrandImport">品牌数据导入</el-button>
|
||||
<el-button type="danger" @click="openCategoryImport">商品分类数据导入</el-button>
|
||||
<el-button @click="openGoodsImport">商品数据导入</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<importCategory ref="importCategoryRef"></importCategory>
|
||||
<importBrand ref="importBrandRef"></importBrand>
|
||||
<importGoods ref="importGoodsRef"></importGoods>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
import importBrand from '@/views/product/goodsImport/importBrand.vue'
|
||||
import importCategory from '@/views/product/goodsImport/importCategory.vue'
|
||||
import importGoods from '@/views/product/goodsImport/importGoods.vue'
|
||||
export default {
|
||||
components: {importBrand,importCategory,importGoods},
|
||||
data() {
|
||||
return {
|
||||
importCategoryRef:null,
|
||||
importBrandRef:null,
|
||||
importGoodsRef:null,
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
async downloadBrandTemplate() {
|
||||
const res = await GoodsToolApi.downloadBrandTemplate()
|
||||
if (res) {
|
||||
this.$message.success('操作成功')
|
||||
this.downloadFile(res, '品牌模板.xlsx')
|
||||
}
|
||||
},
|
||||
async downloadCategoryTemplate() {
|
||||
const res = await GoodsToolApi.downloadCategoryTemplate()
|
||||
if (res) {
|
||||
this.$message.success('操作成功')
|
||||
this.downloadFile(res, '商品分类导入模板.xlsx')
|
||||
}
|
||||
},
|
||||
async downloadGoodsTemplate() {
|
||||
const res = await GoodsToolApi.downloadGoodsTemplate()
|
||||
if (res) {
|
||||
this.$message.success('操作成功')
|
||||
this.downloadFile(res, '商品导入模板.xlsx')
|
||||
}
|
||||
},
|
||||
downloadFile(blobData, fileName) {
|
||||
const url = window.URL.createObjectURL(new Blob([blobData]))
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.setAttribute('download', fileName)
|
||||
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
|
||||
document.body.removeChild(link)
|
||||
window.URL.revokeObjectURL(url)
|
||||
},
|
||||
openBrandImport(){
|
||||
this.$refs.importBrandRef?.open()
|
||||
},
|
||||
openCategoryImport(){
|
||||
this.$refs.importCategoryRef?.open()
|
||||
},
|
||||
openGoodsImport(){
|
||||
this.$refs.importGoodsRef?.open()
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
gap: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
|
||||
background: #fff;
|
||||
|
||||
.input_item {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
.list {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.tool {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
::v-deep .el-button {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -57,15 +57,19 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="grid-content bg-purple">
|
||||
<el-form-item :label="__('砍价有效期')" prop="cut_hour">
|
||||
<el-input v-model="form.cut_hour" placeholder="请输入有效期(小时)" clearable />
|
||||
<el-form-item :label="__('砍价有效期(小时)')" prop="cut_hour">
|
||||
<el-input v-model="form.cut_hour" type="number" placeholder="请输入有效期(小时)" clearable />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="grid-content bg-purple"></div>
|
||||
<el-form-item :label="__('活动商品总数')" prop="product_count">
|
||||
<el-input v-model="form.product_count" placeholder="请输入参与活动商品总数" clearable />
|
||||
<el-input v-model="form.product_count" type="number" placeholder="请输入参与活动商品总数" clearable
|
||||
:max="form.item_quantity || ''"
|
||||
@input="handleProductCountInput"
|
||||
:disabled="!form.item_id"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -112,7 +116,7 @@
|
||||
:min="2"
|
||||
/>
|
||||
<el-tooltip
|
||||
content="砍价成功的人数,例如设置为3人,一共要3个人砍价才能达到底价下单(默认最少为2)"
|
||||
content="砍价成功的人数,例如设置为3人,底价为0.01,3个人砍价之后才能达到底价0.01,然后下单(默认最少为2)"
|
||||
placement="top"
|
||||
effect="dark"
|
||||
style="margin-left: 8px;"
|
||||
@ -134,7 +138,7 @@
|
||||
style="width: 200px;"
|
||||
/>
|
||||
<el-tooltip
|
||||
content="在活动期间每个人一共可以助力好友的人数(默认最少为5)"
|
||||
content="在活动期间每个人一共可以助力好友的次数,即该活动你一共可以帮多少人砍价(默认最少为5)"
|
||||
placement="top"
|
||||
effect="dark"
|
||||
style="margin-left: 8px;"
|
||||
@ -145,7 +149,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="__('砍价第一刀')" prop="cut_first_type">
|
||||
<el-radio-group v-model="form.cut_first_type">
|
||||
<el-radio-group v-model="form.cut_first_type" @change="handleCutFirstTypeChange">
|
||||
<el-radio :label="1" >
|
||||
<span>{{ __('首刀比例') }}</span>
|
||||
<el-tooltip
|
||||
@ -171,19 +175,32 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="首刀比例(单位-%)" size="normal" v-if='form.cut_first_type == 1'>
|
||||
<el-input v-model="form.cut_first_percent" placeholder="请输入首刀比例" clearable />
|
||||
<el-input v-model="form.cut_first_percent" type="number" placeholder="请输入首刀比例" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="首刀金额(单位/块)" size="normal" v-if='form.cut_first_type == 2'>
|
||||
<el-input v-model="form.cut_first_price " placeholder="请输入首刀金额" clearable />
|
||||
<el-form-item label="首刀金额(单位/块)" size="normal" v-if='form.cut_first_type == 2'>
|
||||
<el-input v-model="form.cut_first_price" type="number" placeholder="请输入首刀金额" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
<el-form ref="touzi" label-width="250px" :model="touzi" :rules="touziRules">
|
||||
<el-form-item label="砍价幸运骰子个数" label-width="150px">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<el-input v-model="touzi.lottery_num" placeholder="请输入骰子的个数" clearable style="width: 200px;" type="number"/>
|
||||
<el-tooltip
|
||||
content="该活动一共可以投骰子用于翻倍砍价金额的次数"
|
||||
placement="top"
|
||||
effect="dark"
|
||||
style="margin-left: 8px;"
|
||||
>
|
||||
<i class="el-icon-question" style="cursor: pointer; color: #909399; font-size: 14px;"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- 总标签 + 问号提示 -->
|
||||
<el-form-item label="砍价后投骰子的点数(单位-%)" class="total-label-item">
|
||||
<el-tooltip
|
||||
content="设置骰子不同点数对应的中奖比例,6个点数比例总和不能超过100%"
|
||||
content="设置骰子不同点数对应的中奖比例,6个点数比例总和不能超过100%,可以使用默认预设,点数1:45%,点数2:45%,点数3:2%,点数4:3%,点数5:2%,点数6:3%"
|
||||
placement="top"
|
||||
effect="dark"
|
||||
style="margin-left: 8px;"
|
||||
@ -231,6 +248,7 @@
|
||||
form: {
|
||||
product_item_name: '',
|
||||
item_id: '',
|
||||
item_quantity:0,
|
||||
cut_down_type: 2,
|
||||
cut_down_user_num: 0,
|
||||
cut_down_fixed_price: '',
|
||||
@ -254,7 +272,7 @@
|
||||
{doubleValue:'5',probability:'2'},
|
||||
{doubleValue:"6",probability:'3'},
|
||||
],
|
||||
lottery_num:1
|
||||
lottery_num:3
|
||||
},
|
||||
touziErrorMsg: '', // 骰子比例总和错误提示
|
||||
touziRules: {
|
||||
@ -314,6 +332,32 @@
|
||||
],
|
||||
product_count: [
|
||||
{ required: true, trigger: 'blur', message: this.__('参与活动商品总数') },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
// 关键:先判断是否已选商品(item_id存在即视为已选),再判断库存
|
||||
if (!this.form.item_id) {
|
||||
callback(new Error(this.__('请先选择砍价商品')));
|
||||
return;
|
||||
}
|
||||
// 库存为0时提示“商品库存为0,无法设置活动总数”
|
||||
if (Number(this.form.item_quantity) <= 0) {
|
||||
callback(new Error(this.__('该商品库存为0,无法设置活动商品总数')));
|
||||
return;
|
||||
}
|
||||
const count = Number(value);
|
||||
const max = Number(this.form.item_quantity);
|
||||
if (isNaN(count)) {
|
||||
callback(new Error(this.__('请输入有效的数字')));
|
||||
} else if (count <= 0) {
|
||||
callback(new Error(this.__('活动商品总数不能小于等于0')));
|
||||
} else if (count > max) {
|
||||
callback(new Error(this.__(`活动商品总数不能超过商品库存${max}件`)));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: ['blur', 'change', 'submit']
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
@ -332,6 +376,12 @@
|
||||
getCheckItem(row) {
|
||||
this.form.item_id = row.item_id
|
||||
this.form.product_item_name = row.product_item_name
|
||||
this.form.item_quantity = row.item_quantity;
|
||||
// 可选:如果活动商品总数已有值,且超过库存,自动重置
|
||||
if (this.form.product_count && Number(this.form.product_count) > Number(this.form.item_quantity)) {
|
||||
this.form.product_count = this.form.item_quantity;
|
||||
this.$baseMessage(`活动商品总数不能超过商品库存${this.form.item_quantity},已自动重置`, 'warning');
|
||||
}
|
||||
this.$refs['form'].validateField(
|
||||
['product_item_name', 'item_id'],
|
||||
(errorMsg) => {
|
||||
@ -361,6 +411,7 @@
|
||||
cut_down_user_num: row.activity_rule.cut_down_user_num,
|
||||
cut_hour:row.cut_hour,
|
||||
product_count:row.product_count,
|
||||
//item_quantity: row.activity_rule.item_quantity 后端暂时没返回 用于校验商品库存数量的
|
||||
user_cutprice_num:row.activity_rule.user_cutprice_num,
|
||||
cut_first_type:row.activity_rule.cut_first_type,//空初始化
|
||||
cut_first_percent:row.activity_rule.cut_first_percent,
|
||||
@ -374,12 +425,29 @@
|
||||
},
|
||||
tranformData(lucky_turn){
|
||||
if(this.form.cut_first_percent){
|
||||
this.form.cut_first_type=1
|
||||
this.form.cut_first_type=1;
|
||||
this.form.cut_first_price = ''
|
||||
}else if(this.form.cut_first_price){
|
||||
this.form.cut_first_type=2
|
||||
this.form.cut_first_percent = ''
|
||||
}
|
||||
this.touzi=JSON.parse(lucky_turn)
|
||||
},
|
||||
// 父组件 methods
|
||||
handleProductCountInput() {
|
||||
if (!this.form.item_quantity) return;
|
||||
const count = Number(this.form.product_count);
|
||||
const max = Number(this.form.item_quantity);
|
||||
// 如果输入值超过库存,自动截断为库存值
|
||||
if (count > max) {
|
||||
this.form.product_count = max;
|
||||
this.$baseMessage(`活动商品总数最大为${max}件`, 'warning');
|
||||
}
|
||||
// 如果输入负数/非数字,清空
|
||||
if (count <= 0 || isNaN(count)) {
|
||||
this.form.product_count = '';
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.form = {
|
||||
product_item_name: '',
|
||||
@ -402,6 +470,16 @@
|
||||
showItemTable() {
|
||||
this.$refs['productItemTable'].showTable()
|
||||
},
|
||||
// 处理砍价第一刀类型切换
|
||||
handleCutFirstTypeChange(type) {
|
||||
if (type === 1) {
|
||||
// 选择首刀比例,清空首刀金额
|
||||
this.form.cut_first_price = '';
|
||||
} else if (type === 2) {
|
||||
// 选择首刀金额,清空首刀比例
|
||||
this.form.cut_first_percent = '';
|
||||
}
|
||||
},
|
||||
diceObjToStr(){
|
||||
this.form.diceObj = JSON.stringify(this.touzi);
|
||||
},
|
||||
|
||||
155
src/views/store/storeSyncApp/addSyncApp.vue
Normal file
155
src/views/store/storeSyncApp/addSyncApp.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<el-dialog title="新增密钥" width="50%" :visible.sync="visible">
|
||||
<div>
|
||||
<el-form v-model="syncAppForm" label-position="left" label-width="80px">
|
||||
<el-form-item label="app_key" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.app_key"
|
||||
placeholder="请输入app_key"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="app_secret" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.app_secret"
|
||||
placeholder="请输入app_secret"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="店铺" size="normal">
|
||||
<el-select
|
||||
v-model="syncAppForm.store_id"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="选择店铺"
|
||||
style="width: 200px"
|
||||
@change="handleStoreChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in shopList"
|
||||
:key="item.store_id"
|
||||
:label="item.store_name"
|
||||
:value="item.store_id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="介绍" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.intro"
|
||||
style="width: 300px"
|
||||
placeholder="请输入介绍"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="syncAppForm.status"
|
||||
clearable
|
||||
filterable
|
||||
@change="handleSyncAppStatus"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in statusList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submit">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
import { saveSyncApp } from '@/api/syncApp.js'
|
||||
export default {
|
||||
name: 'addSyncApp',
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
syncAppForm: {
|
||||
app_key: '',
|
||||
app_secret: '',
|
||||
store_id: '',
|
||||
name: '',
|
||||
intro: '',
|
||||
status: 0,
|
||||
},
|
||||
filter: {
|
||||
productName: '',
|
||||
storeId: '',
|
||||
},
|
||||
shopList: [],
|
||||
statusList: [
|
||||
{
|
||||
label: '可用',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '不可用',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '不校验签名',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
// 打开弹窗时重置表单,避免残留数据
|
||||
this.syncAppForm = {
|
||||
app_key: '',
|
||||
app_secret: '',
|
||||
store_id: '',
|
||||
name: '',
|
||||
intro: '',
|
||||
status: 1,
|
||||
}
|
||||
this.visible = true
|
||||
},
|
||||
async getShopList() {
|
||||
try {
|
||||
let res = await GoodsToolApi.getShopList()
|
||||
this.shopList = res.data.items || []
|
||||
} catch (error) {
|
||||
console.error('获取店铺列表失败:', error)
|
||||
}
|
||||
},
|
||||
handleStoreChange(storeId) {
|
||||
this.syncAppForm.name = ''
|
||||
const selectedShop = this.shopList.find(
|
||||
(item) => item.store_id === storeId
|
||||
)
|
||||
if (selectedShop) {
|
||||
this.syncAppForm.name = selectedShop.store_name
|
||||
}
|
||||
},
|
||||
async submit() {
|
||||
let res = await saveSyncApp(this.syncAppForm)
|
||||
console.log(res)
|
||||
if (res.status == 200) {
|
||||
this.visible = false
|
||||
this.$emit('success')
|
||||
}
|
||||
},
|
||||
handleSyncAppStatus(e) {
|
||||
this.syncAppForm.status = e
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
131
src/views/store/storeSyncApp/editSync.vue
Normal file
131
src/views/store/storeSyncApp/editSync.vue
Normal file
@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<el-dialog title="编辑密钥" width="50%" :visible.sync="visible">
|
||||
<div>
|
||||
<el-form v-model="syncAppForm" label-position="left" label-width="80px">
|
||||
<el-form-item label="app_key" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.app_key"
|
||||
placeholder="请输入app_key"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="app_secret" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.app_secret"
|
||||
placeholder="请输入app_secret"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="店铺" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.name"
|
||||
style="width: 200px;"
|
||||
disabled
|
||||
clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item label="介绍" size="normal">
|
||||
<el-input
|
||||
v-model="syncAppForm.intro"
|
||||
style="width: 200px;"
|
||||
placeholder="请输入介绍"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="syncAppForm.status"
|
||||
clearable
|
||||
filterable
|
||||
@change="handleSyncAppStatus"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in statusList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="changeSumbit">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsToolApi from '@/api/goodsTool'
|
||||
import { editSyncApp } from '@/api/syncApp';
|
||||
export default {
|
||||
name: 'editSyncApp',
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
syncAppForm: {
|
||||
app_key: '',
|
||||
app_secret: '',
|
||||
store_id: '',
|
||||
name: '',
|
||||
intro: '',
|
||||
status: 0,
|
||||
},
|
||||
filter: {
|
||||
productName: '',
|
||||
storeId: '',
|
||||
},
|
||||
shopList: [],
|
||||
statusList: [
|
||||
{
|
||||
label: '可用',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '不可用',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '不校验签名',
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
open(row) {
|
||||
this.visible = true
|
||||
this.syncAppForm = { ...row }
|
||||
},
|
||||
close(){
|
||||
this.visible=false
|
||||
},
|
||||
async getShopList() {
|
||||
try {
|
||||
let res = await GoodsToolApi.getShopList()
|
||||
this.shopList = res.data.items || []
|
||||
} catch (error) {
|
||||
console.error('获取店铺列表失败:', error)
|
||||
}
|
||||
},
|
||||
async changeSumbit(){
|
||||
let res = await editSyncApp(this.syncAppForm)
|
||||
console.log("sdfasa",res)
|
||||
if(res.status== 200){
|
||||
this.visible=false
|
||||
this.$emit('success')
|
||||
}
|
||||
},
|
||||
handleSyncAppStatus(e) {
|
||||
this.syncAppForm.status = e
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
106
src/views/store/storeSyncApp/index.vue
Normal file
106
src/views/store/storeSyncApp/index.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="db-config-management">
|
||||
<el-card class="list">
|
||||
<div slot="header" class="tool">
|
||||
<el-button type="primary" @click="openAddSyncApp">新增</el-button>
|
||||
</div>
|
||||
|
||||
<el-table border :data="SyncAppList" stripe>
|
||||
<el-table-column label="操作" width="250">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="primary" @click="openEdit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button size="mini" type="danger" @click="handlerDelete(scope.row.id)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="店铺id" prop="store_id" />
|
||||
<el-table-column label="店铺名字" prop="name" />
|
||||
<el-table-column label="app_key" prop="app_key" />
|
||||
<el-table-column label="密钥" prop="app_secret" />
|
||||
<el-table-column label="店铺介绍" prop="intro" />
|
||||
<el-table-column label="状态" prop="status">
|
||||
<template slot-scope="scope">
|
||||
{{
|
||||
scope.row.status == 1 ? '可用' :
|
||||
scope.row.status == 2 ? '不可用' :
|
||||
scope.row.status == 3 ? '不校验签名':
|
||||
'其他'
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<addSyncApp ref="addSyncAppRef" @success="refreshList"></addSyncApp>
|
||||
<editSync ref="editSyncAppRef" @success="refreshList"></editSync>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import addSyncApp from '@/views/store/storeSyncApp/addSyncApp.vue'
|
||||
import editSync from '@/views/store/storeSyncApp/editSync.vue'
|
||||
import {
|
||||
getSyncAppList,
|
||||
saveSyncApp,
|
||||
editSyncApp,
|
||||
deleteSyncApp,
|
||||
} from '@/api/syncApp.js'
|
||||
|
||||
export default {
|
||||
components: { addSyncApp, editSync },
|
||||
data() {
|
||||
return {
|
||||
addSyncAppRef: null,
|
||||
editSyncAppRef: null,
|
||||
SyncAppList: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getSyncList()
|
||||
},
|
||||
methods: {
|
||||
openAddSyncApp() {
|
||||
this.$refs.addSyncAppRef?.open()
|
||||
},
|
||||
openEdit(row) {
|
||||
this.$refs.editSyncAppRef?.open(row)
|
||||
},
|
||||
async getSyncList() {
|
||||
const res = await getSyncAppList()
|
||||
this.SyncAppList = res.records
|
||||
},
|
||||
refreshList(){
|
||||
this.getSyncList()
|
||||
},
|
||||
async handlerDelete(id) {
|
||||
try {
|
||||
await this.$confirm(
|
||||
'此操作将永久删除该条记录, 是否继续?',
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
const res = await deleteSyncApp(id)
|
||||
if(res.status==200){
|
||||
this.$message.success('删除成功!')
|
||||
this.getSyncList()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
this.$message.error('删除失败!')
|
||||
console.error('删除出错:', error)
|
||||
} else {
|
||||
this.$message.info('已取消删除')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
Loading…
Reference in New Issue
Block a user