feat 支持自定义优惠

This commit is contained in:
timerzz 2024-06-16 09:41:36 +08:00
parent fd02219251
commit 1bf55e3308
6 changed files with 191 additions and 33 deletions

View File

@ -0,0 +1,12 @@
import {mande} from "mande";
const usCoachOutletSpider = mande('/api/v1/spider/us/coach-outlet')
export const GetUSCoachOutletSpiderCfg = ()=> usCoachOutletSpider.get("cfg")
export const SetUSCoachOutletSpiderCfg = (cfg)=> usCoachOutletSpider.post("cfg",cfg)
export const GetUSCoachOutletSpiderGlobalCalculate = ()=> usCoachOutletSpider.get("global/calculate")
export const DeleteCnCoachOutletSpiderGlobalCalculate = (id)=> usCoachOutletSpider.delete(`global/calculate/u/${id}`)
export const SaveUSCoachOutletSpiderGlobalCalculate = (data)=> usCoachOutletSpider.post("global/calculate",data)
export const DeleteCnCoachOutletSpiderCalculate = (id)=> usCoachOutletSpider.delete(`calculate/u/${id}`)
export const SaveUSCoachOutletSpiderCalculate = (data)=> usCoachOutletSpider.post("calculate",data)

View File

@ -1,7 +0,0 @@
import {mande} from "mande";
const spider = mande('/api/v1/spider')
export const GetSpiderCfg = ()=> spider.get("cfg")
export const SetSpiderCfg = (cfg)=> spider.post("cfg",cfg)

View File

@ -13,12 +13,12 @@ const routes = [
{
path: '/us-coach',
name: 'us-coach',
component: ()=>import('@/views/Product/US.vue')
component: ()=>import('@/views/Product/USCoachOutlet.vue')
},
{
path: '/cn-coach',
name: 'cn-coach',
component: ()=>import('@/views/Product/CN.vue')
component: ()=>import('@/views/Product/CNCoachOutlet.vue')
},
{
path: '/pusher',

View File

@ -21,7 +21,7 @@
</template>
<template v-else-if="column.key === 'cnyPrice'">
<div class="flex space items-center">
<span>{{record.cnyPrice}}</span>
<span >{{record.cnyPrice}}</span>
<CaretUpOutlined class="text-red" v-if="record.priceStatus === PRICE_STATUS.UP"/>
<CaretDownOutlined class="text-green" v-if="record.priceStatus === PRICE_STATUS.DOWN"/>
</div>
@ -43,14 +43,6 @@
:src="record.image"
/>
</template>
<template v-else-if="column.key === 'cnyPrice'">
<a-popover >
<template #content>
<div class="whitespace-pre">{{record.calMark}}</div>
</template>
<span class="cursor-pointer">{{parseFloat(record.cnyPrice).toFixed(2)}}</span>
</a-popover>
</template>
<template v-else-if="column.key === 'orderable'">
<span :class="[record.orderable ? '':'text-red']">{{record.orderable?'是':'否'}}</span>
</template>
@ -230,6 +222,7 @@ const editData = reactive({
})
const onEdit=(record, param) => {
console.log('click')
editData.data = clone(record)
editData.param = param
editData.edit = true

View File

@ -0,0 +1,118 @@
<template>
<a-modal v-model:open="open" centered :width="1300" @ok="save">
<template #title>
编辑
</template>
<div class="w-full flex flex-col space-y-4">
<div class="flex items-center space-x-4">
<a-button type="primary" @click="add">+</a-button>
<div class="text-lg">原价originalPrice 汇率exchangeRate 运费freight</div>
</div>
<a-form :model="modal.data" class="w-full">
<div v-for="(item,index) in modal.data.calculate" class="flex space-x-4 justify-between w-full ">
<a-form-item label="名称" required :name="['calculate',index,'Name']" >
<a-input v-model:value="item.Name"></a-input>
</a-form-item>
<a-form-item label="条件">
<a-input class="w-[300px]" v-model:value="item.Condition"></a-input>
</a-form-item>
<a-form-item label="计算" required :name="['calculate',index,'Process']">
<a-input class="w-[500px]" v-model:value="item.Process"></a-input>
</a-form-item>
<a-button danger type="primary" @click="del(item.id, index,item.Name)">-</a-button>
</div>
</a-form>
</div>
</a-modal>
</template>
<script setup>
import {computed, reactive} from "vue";
import {message, Modal} from "ant-design-vue";
const props = defineProps({
visible: {
type: Boolean,
default: false
},
getter: {
type: Function,
default: ()=>{}
},
add: {
type: Function,
default: ()=>{}
},
del: {
type: Function,
default: ()=>{}
},
save: {
type: Function,
default: ()=>{}
}
})
const emit = defineEmits(['update:visible'])
const open = computed({
get() {
if(props.visible){
load()
}
return props.visible
},
set(value) {
emit('update:visible', value)
}
})
const load = ()=>{
props.getter().then(res=>{
modal.data.calculate = res
})
}
const modal = reactive({
data: {
calculate: []
}
})
const add = ()=>{
const cs = props.add()
if(cs){
modal.data.calculate.push(cs)
}
}
const del = (id, idx, name)=>{
if(!id) {
modal.data.calculate.splice(idx, 1)
}else{
Modal.confirm({
title: '确定',
content: `确定删除【${name}】?`,
centered:true,
onOk() {
props.del(id).then(res=>{
modal.data.calculate.splice(idx, 1)
}).catch(err=>{
console.log(err)
message.error('删除失败')
})
},
});
}
}
const save = ()=>{
props.save(modal.data.calculate).then(res=>{
open.value = false
message.success('保存成功')
}).catch(err=>{
console.log(err)
message.error('保存失败')
})
}
</script>
<style scoped>
</style>

View File

@ -4,8 +4,8 @@
<div class="flex items-center space-x-16">
<div>当前汇率<span class="text-xl">{{spiderCfg.exchangeRate}}</span></div>
<div>当前默认运费<span class="text-xl">{{spiderCfg.freight}}</span></div>
<div>当前折扣<span class="text-xl">{{spiderCfg.discount}}% </span></div>
<FormOutlined class="cursor-pointer" @click="editSpiderCfg"/>
<a-button type="primary" @click="globalCalculateVisible=true">查看优惠设置</a-button>
</div>
<div class="flex space-x-4">
<a-input placeholder="请输入关键词" v-model:value="query.keyword" @pressEnter="search"></a-input>
@ -23,9 +23,9 @@
<template v-else-if="column.key === 'updatedAt'">
<span>{{moment(record.updatedAt).format('YYYY-MM-DD HH:mm:ss')}}</span>
</template>
<template v-else-if="column.key === 'usPrice'">
<template v-else-if="column.key === 'originalPrice'">
<div class="flex space items-center">
<span>{{record.usPrice}}</span>
<span>{{record.originalPrice}}</span>
<CaretUpOutlined class="text-red" v-if="record.priceStatus === PRICE_STATUS.UP"/>
<CaretDownOutlined class="text-green" v-if="record.priceStatus === PRICE_STATUS.DOWN"/>
</div>
@ -70,6 +70,7 @@
<a-popover title="" placement="bottom">
<template #content>
<a-button type="text" block @click="onEdit(record, 'modal')">编辑</a-button>
<a-button type="text" block @click="showCalculateModal(record)">查看优惠</a-button>
<a-button type="text" block @click="onWatch(record.pid, record.name)">一键蹲货</a-button>
</template>
<SettingOutlined class="cursor-pointer" />
@ -83,7 +84,7 @@
<div class="text-xl">历史价格</div>
<div class="flex space-x-16 my-2 text-lg" v-for="h in record.historyPrices">
<div>{{moment(h.createdAt).format('YYYY-MM-DD HH:mm:ss')}}</div>
<div>${{h.usPrice}}</div>
<div>${{h.originalPrice}}</div>
</div>
<div class="text-xl mt-4">得物价格CNY</div>
<div v-if="record.dwHistoryPrices?.length>0" class="flex space-x-16 my-2 text-lg" v-for="h in record.dwHistoryPrices">
@ -106,7 +107,7 @@
</template>
<a-form :model="editData.data" :labelCol="{span: 6}">
<a-form-item label="价格(美元)">
<a-input-number disabled v-model:value="editData.data.usPrice"/>
<a-input-number disabled v-model:value="editData.data.originalPrice"/>
</a-form-item>
<a-form-item label="成本">
<a-input-number disabled v-model:value="editData.data.cnyPrice"/>
@ -133,11 +134,20 @@
<a-form-item label="运费">
<a-input-number v-model:value="spiderCfgModal.data.freight" :min="1"/>
</a-form-item>
<a-form-item label="折扣">
<a-input-number addon-after="%" v-model:value="spiderCfgModal.data.discount" :min="1" :max="100"/>
</a-form-item>
</a-form>
</a-modal>
<Calculate v-model:visible="globalCalculateVisible"
:getter="GetUSCoachOutletSpiderGlobalCalculate"
:add="()=>{return {Condition:'', Name:'',Pid:'us-coach-outlet',Process:'' }}"
:del="DeleteCnCoachOutletSpiderGlobalCalculate"
:save="SaveUSCoachOutletSpiderGlobalCalculate"
></Calculate>
<Calculate v-model:visible="calculateModal.visible"
:getter="calculateModal.getter"
:add="calculateModal.add"
:del="calculateModal.del"
:save="calculateModal.save"
></Calculate>
</template>
<script setup>
@ -148,8 +158,15 @@ import { clone } from 'radash'
import {LoadingOutlined, SaveOutlined,SettingOutlined,CaretUpOutlined,CaretDownOutlined, FormOutlined} from "@ant-design/icons-vue";
import {message, Modal} from "ant-design-vue";
import {CreateWatcher} from "@/api/watcher.js";
import {GetSpiderCfg, SetSpiderCfg} from "@/api/spider.js";
import {
DeleteCnCoachOutletSpiderCalculate,
DeleteCnCoachOutletSpiderGlobalCalculate,
GetUSCoachOutletSpiderCfg,
GetUSCoachOutletSpiderGlobalCalculate, SaveUSCoachOutletSpiderCalculate, SaveUSCoachOutletSpiderGlobalCalculate,
SetUSCoachOutletSpiderCfg
} from "@/api/cn-coach-outlet-spider.js";
import {WEBSITES} from "@/constants/website.js";
import Calculate from "@/views/Product/Calculate.vue";
onMounted(()=>{
list()
@ -209,8 +226,8 @@ const columns = computed(()=>[
},
{
title: '价格(美元)',
dataIndex: 'usPrice',
key: 'usPrice',
dataIndex: 'originalPrice',
key: 'originalPrice',
},
{
title: '折扣力度',
@ -361,11 +378,10 @@ const PRICE_STATUS = {
const spiderCfg = ref({
exchangeRate: 0,
freight: 0,
discount: 100
})
const loadSpiderCfg = ()=>{
GetSpiderCfg().then(res=>{
GetUSCoachOutletSpiderCfg().then(res=>{
spiderCfg.value = res
}).catch(err=>{
message.error("获取spider配置失败")
@ -396,7 +412,6 @@ const spiderCfgModal = reactive({
data: {
exchangeRate: 0,
freight: 0,
discount: 100
},
visible: false,
})
@ -407,7 +422,7 @@ const editSpiderCfg = ()=>{
}
const updateSpiderCfg = ()=>{
SetSpiderCfg(spiderCfgModal.data).then(res=>{
SetUSCoachOutletSpiderCfg(spiderCfgModal.data).then(res=>{
message.success('修改成功')
}).catch(err=>{
message.error('修改失败')
@ -417,6 +432,33 @@ const updateSpiderCfg = ()=>{
loadSpiderCfg()
})
}
const globalCalculateVisible = ref(false)
const calculateModal = reactive({
visible : false,
getter: ()=>{},
add: ()=>{},
del: ()=>{},
save: ()=>{}
})
const showCalculateModal = (record)=>{
calculateModal.getter = ()=>{
return GetProduct(record.pid).then(res=>res.calculateProcess)
}
calculateModal.add = ()=>{
return {
Pid: record.pid,
website: WEBSITES.US_COACH_OUTLET,
Condition:'',
Name:'',
Process:''
}
}
calculateModal.del = DeleteCnCoachOutletSpiderCalculate
calculateModal.save = SaveUSCoachOutletSpiderCalculate
calculateModal.visible = true
}
</script>