From 07d034e2477a96736f62112c3845799bb74884d5 Mon Sep 17 00:00:00 2001 From: Ximu-Luya <794876939@qq.com> Date: Sun, 17 Mar 2024 02:16:50 +0800 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=B0=86?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=80=89=E9=A1=B9=E4=BF=9D=E5=AD=98=E5=88=B0?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E6=9C=AC=E5=9C=B0=E5=B9=B6=E8=AF=BB?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stores/settings.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stores/settings.ts b/stores/settings.ts index c11569c..4cf7fac 100644 --- a/stores/settings.ts +++ b/stores/settings.ts @@ -1,7 +1,10 @@ +import { skipHydrate } from 'pinia' +import { useStorage } from '@vueuse/core' + export type ListSortMode = 'byCity' | 'byProfit' export const useSettingStore = defineStore('setting', () => { - const listSortMode = ref('byCity') + const listSortMode = useStorage('listSortMode', 'byCity') // 切换列表排序模式 const switchListSortModeTo = (targetMode: ListSortMode) => { @@ -9,7 +12,7 @@ export const useSettingStore = defineStore('setting', () => { } return { - listSortMode, + listSortMode: skipHydrate(listSortMode), switchListSortModeTo } }) From 8aeba488f70b2fc7b7ac999ae7b8237df2e62136 Mon Sep 17 00:00:00 2001 From: Ximu-Luya <794876939@qq.com> Date: Sun, 17 Mar 2024 22:32:18 +0800 Subject: [PATCH 02/10] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=A9?= =?UTF-8?q?=E6=B6=A6=E8=AE=A1=E7=AE=97=E8=A7=84=E5=88=99=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=94=AE=E5=87=BA=E4=BB=B7=E7=9B=B4=E6=8E=A5=E5=87=8F?= =?UTF-8?q?=E4=B9=B0=E5=85=A5=E5=9F=8E=E5=B8=82=E4=B9=B0=E5=85=A5=E4=BB=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Price.vue | 10 +++------- stores/latest.ts | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/components/Price.vue b/components/Price.vue index 3814de7..bbc764b 100644 --- a/components/Price.vue +++ b/components/Price.vue @@ -28,13 +28,9 @@ const store = useLatestLogs(); const profit = computed(() => { if (!props.log || props.log?.type === 'buy') return undefined; - const productLog = store.getLatestLog(props.log.sourceCity, props.log.name, props.log.sourceCity); - if (productLog) { - return Math.round( - 1.06 * props.log.price - - 0.85 * productLog.price - - (1.06 * props.log.price - 0.85 * productLog.price) * 0.06 - ); + const sourceCityLatestLog = store.getLatestLog(props.log.sourceCity, props.log.name, props.log.sourceCity); + if (sourceCityLatestLog) { + return Math.round(props.log.price - sourceCityLatestLog.price) } else { return undefined; } diff --git a/stores/latest.ts b/stores/latest.ts index 2167025..7be9131 100644 --- a/stores/latest.ts +++ b/stores/latest.ts @@ -6,7 +6,7 @@ export const useLatestLogs = defineStore('latest_logs', () => { const fetch = async () => { const resp = await $fetch(`/api/product`, { retry: 3 }); - logs.value = resp.latest.map((l) => ({ ...l, uploadedAt: new Date(l.uploadedAt) })); + logs.value = resp.latest.map(log => ({ ...log, uploadedAt: new Date(log.uploadedAt) })); maps.clear(); for (const log of logs.value) { const key = `${log.sourceCity} - ${log.name}`; From 997a76d1e2a45e75f10e628646b0ab955aa2d9df Mon Sep 17 00:00:00 2001 From: Ximu-Luya <794876939@qq.com> Date: Sun, 17 Mar 2024 22:43:51 +0800 Subject: [PATCH 03/10] =?UTF-8?q?chore:=20=E4=BB=A3=E7=A0=81=E9=A3=8E?= =?UTF-8?q?=E6=A0=BC=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- layouts/default.vue | 90 ++++++++------------------------------------- 1 file changed, 15 insertions(+), 75 deletions(-) diff --git a/layouts/default.vue b/layouts/default.vue index d907d9c..0bdf8d3 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -26,9 +26,7 @@ const settingStore = useSettingStore() From be8f584a271846323c13b020a4e842dd465010bb Mon Sep 17 00:00:00 2001 From: Ximu-Luya <794876939@qq.com> Date: Mon, 18 Mar 2024 00:18:29 +0800 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E6=8C=89?= =?UTF-8?q?=E5=8D=95=E7=A5=A8=E5=88=A9=E6=B6=A6=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/City.vue | 89 ++++++++++++++++++++++++++------------------ components/Price.vue | 35 +++++++++++++---- layouts/default.vue | 65 ++++++++++++++++++++------------ stores/settings.ts | 2 +- 4 files changed, 123 insertions(+), 68 deletions(-) diff --git a/components/City.vue b/components/City.vue index 3e0eb57..0ea240b 100644 --- a/components/City.vue +++ b/components/City.vue @@ -30,14 +30,27 @@ const mode = ref<'simple' | 'full' | 'edit'>('simple'); const store = useLatestLogs(); +const settingStore = useSettingStore() + // 售出城市列表 const sellCities = computed(() => { return cities.filter((c) => c.name !== currentCity.name) }) -const settingStore = useSettingStore() +// 按设置排序后的城市列表 +const sortCitesWithSetting = (filteredCities: CityInfo[], sourceCityName: string, productName: string) => { + if (settingStore.listSortMode === 'byCity') { + return filteredCities + } else if (settingStore.listSortMode === 'byProfit') { + return sortCitesByPercent(filteredCities, sourceCityName, productName) + } else if (settingStore.listSortMode === 'byPerTicketProfit') { + return sortCitesByPerTicketProfit(filteredCities, sourceCityName, productName) + } else { + return filteredCities + } +} -// 返回对各城市利润排序后的城市列表 +// 按单位利润排序城市 const sortCitesByPercent = (filteredCities: CityInfo[], sourceCityName: string, productName: string) => { const sourceCityPrice = store.getLatestLog(sourceCityName, productName, sourceCityName)?.price || 0 @@ -53,6 +66,28 @@ const sortCitesByPercent = (filteredCities: CityInfo[], sourceCityName: string, const sortedCities = filteredCities.sort((a, b) => citiesProfitMap[b.name] - citiesProfitMap[a.name]) return sortedCities } + +// 按单票利润排序城市 +const sortCitesByPerTicketProfit = (filteredCities: CityInfo[], sourceCityName: string, productName: string) => { + const sourceCityPrice = store.getLatestLog(sourceCityName, productName, sourceCityName)?.price || 0 + const baseVolume = getProductInfo(sourceCityName, productName)?.baseVolume || 0 + + // 计算各城市货物利润 + let citiesProfitMap: {[key: string]: number} = {} + filteredCities.map(city => { + const latestLog = store.getLatestLog(sourceCityName, productName, city.name) + // 如果最新交易记录无效,且有最新交易记录和原产地价格,则计算利润 + const profit = !Boolean(isLogValid(latestLog)) && latestLog && sourceCityPrice ? latestLog.price - sourceCityPrice : -9999 + return { cityName: city.name, profit } + }).forEach(cityProfit => citiesProfitMap[cityProfit.cityName] = cityProfit.profit) + + const sortedCities = filteredCities.sort((a, b) => { + const aProfit = citiesProfitMap[a.name] * (baseVolume ?? 0) + const bProfit = citiesProfitMap[b.name] * (baseVolume ?? 0) + return bProfit - aProfit + }) + return sortedCities +} -