This commit is contained in:
weipengfei 2023-12-05 18:39:17 +08:00
parent 3c361aef23
commit 2885e6faea
27 changed files with 788 additions and 257 deletions

View File

@ -1,16 +1,8 @@
<script setup> <script setup>
import headView from "@/components/headView.vue";
import Businesses from "@/components/Businesses.vue";
</script> </script>
<template> <template>
<dv-full-screen-container class="body"> <router-view></router-view>
<headView></headView>
<div style="height: calc(100% - 60px)">
<router-view></router-view>
</div>
<Businesses class="businesses"></Businesses>
</dv-full-screen-container>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@ -18,20 +10,4 @@ import Businesses from "@/components/Businesses.vue";
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.body {
background-image: url("/src/assets/img/bg.png");
background-size: 100% 100%;
color: #fff;
background-color: rgba($color: #000000, $alpha: 0.8);
}
.businesses {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
}
</style> </style>

35
src/api/api.js Normal file
View File

@ -0,0 +1,35 @@
import axios from "axios";
const instacne = axios.create({
baseURL: "http://192.168.1.15:9527/",
timeout: 30000,
});
instacne.interceptors.request.use(
(config) => {
return config;
},
(err) => {
return Promise.reject(err);
}
);
instacne.interceptors.response.use(
(res) => {
return res.data;
},
(err) => {
return Promise.reject(err);
}
);
export function loginAPI (parms) {
return instacne.post('/login', parms)
}

View File

@ -1,26 +1,46 @@
import axios from "@/utils/axios.js"; import axios from "@/utils/axios.js";
// 获取街道
export const getStreet = (data) => { export const getStreet = (data) => {
return axios.get('city/get_street', { params: data }); return axios.get('city/get_street', { params: data });
} }
// 订单列表
export const orderList = (data) => { export const orderList = (data) => {
return axios.get('dataview/curr_order_info', { params: data }); return axios.get('dataview/curr_order_info', { params: data });
} }
// 订单排行
export const orderRanking = (data) => { export const orderRanking = (data) => {
return axios.get('dataview/order_ranking', { params: data }); return axios.get('dataview/order_ranking', { params: data });
} }
// 配送商品排行
export const deliveredProductRanking = (data) => { export const deliveredProductRanking = (data) => {
return axios.get('dataview/delivered_product_ranking', { params: data }); return axios.get('dataview/delivered_product_ranking', { params: data });
} }
// 三轮车列表
export const vehicleList = (data) => { export const vehicleList = (data) => {
return axios.get('dataview/vehicle_list', { params: data }); return axios.get('dataview/vehicle_list', { params: data });
} }
// 配送详情
export const latestLogistics = (data) => { export const latestLogistics = (data) => {
return axios.get('dataview/latest_logistics', { params: data }); return axios.get('dataview/latest_logistics', { params: data });
} }
// 物流信息
export const logisticsCount = (data) => {
return axios.get('dataview/logistics_count', { params: data });
}
// 条状图统计信息
export const dateCangeCrderCount = (data) => {
return axios.get('dataview/date_range_order_count', { params: data });
}
// 地图配送信息
export const logisticsMapCount = (data) => {
return axios.get('dataview/logistics_map_count', { params: data });
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/login_img/DL.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

BIN
src/assets/login_img/KJ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/assets/login_img/MM.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/assets/login_img/ZH.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/assets/login_img/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -5,6 +5,10 @@ import { useRouter } from 'vue-router'
import paging from "./paging.vue" import paging from "./paging.vue"
import mitt from "@/utils/mitt" import mitt from "@/utils/mitt"
import { orderList } from "@/api/index.js" import { orderList } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const route = useRouter() const route = useRouter()
const ShwostoreType = ref(false) const ShwostoreType = ref(false)
@ -69,8 +73,8 @@ const configs = reactive({
}) })
const pages = ref({ const pages = ref({
areaCode: 510524, areaCode: appStore.address.areaCode,
streetCode: 510524100, streetCode: appStore.address.streetCode,
page: 1, page: 1,
limit: 30, limit: 30,
total: 0, total: 0,

View File

@ -49,7 +49,6 @@ const appStore = useAppStore();
// //
const choseTownFn = (item) => { const choseTownFn = (item) => {
emit('offAreaList', item);
if (item.code.length == 6) { if (item.code.length == 6) {
appStore.setMapInfo('luxian'); appStore.setMapInfo('luxian');
appStore.setAddress({ appStore.setAddress({
@ -62,6 +61,7 @@ const choseTownFn = (item) => {
streetCode: item.code streetCode: item.code
}) })
} }
emit('offAreaList', item);
} }
const open = () => { const open = () => {

View File

@ -1,11 +1,13 @@
<script setup> <script setup>
import { reactive, ref, provide, nextTick, onMounted } from "vue"; import { reactive, ref, provide, nextTick, onMounted, inject } from "vue";
import areaList from "./areaList.vue"; import areaList from "./areaList.vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import mitt from "@/utils/mitt"; import mitt from "@/utils/mitt";
import { getStreet } from "@/api/index.js" import { getStreet } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"; import { useAppStore } from "@/store/app.js";
const reload = inject('reload');
const info = reactive({ const info = reactive({
address: '泸县', address: '泸县',
pinyin: 'luxian' pinyin: 'luxian'
@ -29,6 +31,7 @@ const offAreaList = (e) => {
}) })
info.address = e.name; info.address = e.name;
mitt.emit('map_info', info); mitt.emit('map_info', info);
reload();
} }
const list = ref([]) const list = ref([])

66
src/layout/index.vue Normal file
View File

@ -0,0 +1,66 @@
<script setup>
import headView from "@/components/headView.vue";
import Businesses from "@/components/Businesses.vue";
import { ref, nextTick, provide, onMounted, onUnmounted } from "vue";
const show = ref(true);
const reload = () => {
show.value = false;
nextTick(() => {
show.value = true;
})
}
provide('reload', reload);
//
let timer = null;
const startReLoad = () => {
clearInterval(timer);
timer = setInterval(() => {
reload();
}, 3 * 60 * 1000);
}
onMounted(() => {
startReLoad();
window.addEventListener('mousemove', startReLoad);
window.addEventListener('keypress', startReLoad);
window.addEventListener('click', startReLoad);
})
onUnmounted(() => {
window.removeEventListener('mousemove', startReLoad);
window.removeEventListener('keypress', startReLoad);
window.removeEventListener('click', startReLoad);
})
</script>
<template>
<dv-full-screen-container class="body">
<headView></headView>
<div style="height: calc(100% - 60px)">
<router-view v-if="show"></router-view>
</div>
<Businesses class="businesses"></Businesses>
</dv-full-screen-container>
</template>
<style scoped lang="scss">
.body {
background-image: url("/src/assets/img/bg.png");
background-size: 100% 100%;
color: #fff;
background-color: rgba($color: #000000, $alpha: 0.8);
}
.businesses {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
}
</style>

View File

@ -4,12 +4,24 @@ const routes = [
{ {
path: '/', path: '/',
name: 'index', name: 'index',
component: () => import('../view/index/index.vue') component: () => import('../layout/index.vue'),
children: [
{
path: '/',
name: '',
component: () => import('../view/index/index.vue')
},
{
path: '/delivery',
name: 'delivery',
component: () => import('../view/delivery/index.vue')
},
]
}, },
{ {
path: '/delivery', path: '/login',
name: 'delivery', name: '/login',
component: () => import('../view/delivery/index.vue') component: () => import('../view/login/index.vue')
} }
] ]

View File

@ -4,26 +4,58 @@ import { ref } from "vue"
export const useAppStore = defineStore('app', () => { export const useAppStore = defineStore('app', () => {
const map_info = ref(localStorage.getItem('map_info') || 'luxian'); const map_info = ref(localStorage.getItem('map_info') || 'luxian');
const address = ref(JSON.parse(localStorage.getItem('address') || '{}'));
if (!address.value.areaCode) {
address.value = { areaCode: 510521, streetCode: 510521100 };
}
const setMapInfo = (e) => { const setMapInfo = (e) => {
map_info.value = e; map_info.value = e;
localStorage.setItem('map_info', e); localStorage.setItem('map_info', e);
} }
const address = ref(JSON.parse(localStorage.getItem('address') || '{}'));
if (!address.value.areaCode) {
address.value = { areaCode: 510524, streetCode: 510524100 };
}
// 测试使用的初始化配置
address.value = { areaCode: 510524, streetCode: 510524100 };
const setAddress = (e) => { const setAddress = (e) => {
address.value.areaCode = e.areaCode; e.areaCode ? address.value.areaCode = e.areaCode : null;
address.value.streetCode = e.streetCode; e.streetCode ? address.value.streetCode = e.streetCode : null;
localStorage.setItem('address', JSON.stringify(e)); localStorage.setItem('address', JSON.stringify(e));
} }
const delivery = ref({
pending_order_count: 0,
delivering_order_count: 0,
finished_order_count: 0,
order_count: 0
})
const setDelivery = (e) => {
e.pending_order_count ? delivery.value.pending_order_count = e.pending_order_count : null;
e.delivering_order_count ? delivery.value.delivering_order_count = e.delivering_order_count : null;
e.finished_order_count ? delivery.value.finished_order_count = e.finished_order_count : null;
e.order_count ? delivery.value.order_count = e.order_count : null;
}
const delivery_address = ref(JSON.parse(localStorage.getItem('delivery_address') || '{}'));
if (!delivery_address.value.areaCode) {
delivery_address.value = { areaCode: 510524, streetCode: 510524100 };
}
const setDeliveryAddress = (e) => {
delivery_address.value = e;
localStorage.setItem('delivery_address', JSON.stringify(e));
}
return { return {
map_info, map_info,
address, address,
delivery,
delivery_address,
setMapInfo, setMapInfo,
setAddress setAddress,
setDelivery,
setDeliveryAddress
} }
}) })

View File

@ -6,11 +6,18 @@ let map = null;
const loading = ref(true); const loading = ref(true);
onMounted(() => { const props = defineProps({
info: {
type: Object,
default: () => { }
}
})
const initMap = () => {
AMapLoader.load({ AMapLoader.load({
key: "4f8f55618010007147aab96fc72bb408", // WebKey load key: "4f8f55618010007147aab96fc72bb408", // WebKey load
version: "2.0", // JSAPI 1.4.15 version: "2.0", // JSAPI 1.4.15
plugins: ['AMap.ToolBar', 'AMap.Driving', 'AMap.AutoComplete'] // 使'AMap.Scale' plugins: ['AMap.ToolBar', 'AMap.Driving', 'AMap.AutoComplete', 'AMap.Geocoder'] // 使'AMap.Scale'
}) })
.then((AMap) => { .then((AMap) => {
map = new AMap.Map("container-left", { map = new AMap.Map("container-left", {
@ -28,6 +35,7 @@ onMounted(() => {
loading.value = false; loading.value = false;
}, 500) }, 500)
}); });
const driving = new AMap.Driving({ const driving = new AMap.Driving({
map: map, map: map,
// 线AMap.DrivingPolicy.LEAST_TIME // 线AMap.DrivingPolicy.LEAST_TIME
@ -37,20 +45,59 @@ onMounted(() => {
showTraffic: false, // showTraffic: false, //
// autoFitView: false // // autoFitView: false //
}) })
const points = [
{ keyword: '莲花池街道里海科技', city: '泸州' },
{ keyword: '万象汇', city: '泸州' }
]
driving.search(points, (status, result) => {
// result线 let str = props.info.user_address;
console.log('status=', status) str = str.replace(/[1-10]队/, '');
console.log('result=', result)
}) if (props.info.mer_lat && props.info.mer_long) {
let geocoder = new AMap.Geocoder({
city: "泸州"
});
geocoder.getLocation(str, function (status, result) {
if (status === 'complete' && result.info === 'OK') {
//
var geocode = result.geocodes[0];
let start = [props.info.mer_long, props.info.mer_lat];
let end = [geocode.location.lng, geocode.location.lat];
driving.search(start, end, (status, result) => {
// result线
// console.log('status=', status)
console.log('result=', result)
})
} else {
//
const points = [
{ keyword: props.info.mer_address, city: '泸州' },
{ keyword: str, city: '泸州' }
];
driving.search(points, (status, result) => {
// result线
// console.log('status=', status)
console.log('result=', result)
})
}
});
} else {
const points = [
{ keyword: props.info.mer_address, city: '泸州' },
{ keyword: str, city: '泸州' }
];
driving.search(points, (status, result) => {
// result线
// console.log('status=', status)
console.log('result=', result)
})
}
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.log(e);
}); });
}
onMounted(() => {
initMap();
}); });
onUnmounted(() => { onUnmounted(() => {

View File

@ -1,39 +1,38 @@
<script setup> <script setup>
import { onMounted, reactive, ref } from "vue" import { onMounted, reactive, ref, watch } from "vue"
import border from "@/components/border.vue"; import border from "@/components/border.vue";
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import mitt from "@/utils/mitt" import mitt from "@/utils/mitt";
import { dateCangeCrderCount, orderList as getOrderList } from "@/api/index.js";
import { useAppStore } from "@/store/app.js";
const initData = (aaa) => { const appStore = useAppStore();
for (let i = 0; i < 20; i++) {
if (i % 2 == 0) { const scrollBoardRef = ref(null);
aaa.data.push( const initData = (data) => {
[ let arr = [];
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(91, 219, 246, 0.20)'>排序</div>`, for (let i = 0; i < data.length; i++) {
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(91, 219, 246, 0.20)' >排sd序</div>`, let calss = 'div';
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(91, 219, 246, 0.20)'>排序</div>`, if (i % 2 != 0) {
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(91, 219, 246, 0.20)'>排序</div>`, calss = 'div div2'
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(91, 219, 246, 0.20)'>排序</div>`,
]
)
} else {
aaa.data.push(
[
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(0, 168, 255, 0.16)'>排序</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(0, 168, 255, 0.16)' >排sd序</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(0, 168, 255, 0.16)'>排序</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(0, 168, 255, 0.16)'>排序</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: rgba(0, 168, 255, 0.16)'>排序</div>`,
]
)
} }
arr.push(
[
`<div class="${calss}">${i + 1}</div>`,
`<div class="${calss}">${data[i].real_name || '-'}</div>`,
`<div class="${calss}">${data[i].user_phone || '-'}</div>`,
`<div class="${calss}">${data[i].store_name || '-'}</div>`,
`<div class="${calss}">${data[i].user_address || '-'}</div>`,
]
)
} }
list.data = arr;
scrollBoardRef.value?.updateRows(list.data);
} }
const list = reactive({ const list = reactive({
header: [ header: [
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>ID</div>`, `<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>序号</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>收货人</div>`, `<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>收货人</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>收货人电话</div>`, `<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>收货人电话</div>`,
`<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>商品名称</div>`, `<div style='width: 100%;text-align: center; height: 100%; color: aliceblue; background: linear-gradient(rgba(0, 168, 255, 0.76), rgba(0, 84, 128, 0.73));'>商品名称</div>`,
@ -46,32 +45,39 @@ const list = reactive({
// evenRowBGC: 'rgba(0, 168, 255, 0.16)', // evenRowBGC: 'rgba(0, 168, 255, 0.16)',
oddRowBGC: '', oddRowBGC: '',
evenRowBGC: "", evenRowBGC: "",
// columnWidth: [50], columnWidth: [40, 80],
align: ['center'], align: ['center'],
rowNum: 7 rowNum: 7
}) })
initData(list); initData(list);
const orderList = reactive([ const orderList = ref([
{ {
name: '今日订单', name: '今日订单',
value: '988' value: '0'
}, },
{ {
name: '取货订单', name: '取货订单',
value: '1523' value: '0'
}, },
{ {
name: '配送订单', name: '配送订单',
value: '55' value: '0'
}, },
{ {
name: '已完成订单', name: '已完成订单',
value: '3' value: '0'
}, },
]) ])
watch(() => appStore.delivery, (n, o) => {
orderList.value[0].value = n.order_count;
orderList.value[1].value = n.pending_order_count;
orderList.value[2].value = n.delivering_order_count;
orderList.value[3].value = n.finished_order_count;
}, { deep: true, immediate: true })
const cOrderValue = (e) => { const cOrderValue = (e) => {
let str = e; let str = e;
if (str > 9999) str = 9999 + ''; if (str > 9999) str = 9999 + '';
@ -87,18 +93,16 @@ const cOrderValue = (e) => {
return str; return str;
} }
const echartsRef = ref(null) const echartsRef = ref(null)
const initEcahrts = () => { const initEcahrts = (yData1 = [], yData2 = [], yData3 = [], yData4 = []) => {
let xData = ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'],
let xData = ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00'], // yData1 = [400, 410, 350, 320, 280, 340, 360, 400, 420, 410],
yData1 = [400, 410, 350, 320, 280, 340, 360, 400, 420, 410], // yData2 = [350, 320, 260, 240, 220, 280, 300, 360, 340, 340],
yData2 = [350, 320, 260, 240, 220, 280, 300, 360, 340, 340], // yData3 = [200, 260, 200, 190, 180, 220, 260, 300, 280, 300],
yData3 = [200, 260, 200, 190, 180, 220, 260, 300, 280, 300], // yData4 = [120, 300, 230, 240, 190, 290, 103, 456, 230, 270],
yData4 = [120, 300, 230, 240, 190, 290, 103, 456, 230, 270],
borderData = [], borderData = [],
legend = ["已取货订单", "未配送订单", "已完成订单", "小时订单数"], legend = ["未取货订单", "配送中订单", "已完成订单", "小时订单数"],
colorArr = [{ colorArr = [{
start: "rgba(0, 168, 255,", start: "rgba(0, 168, 255,",
end: "rgba(0, 168, 255, 1)" end: "rgba(0, 168, 255, 1)"
@ -356,8 +360,41 @@ const openList = () => {
mitt.emit('showBusinesses') mitt.emit('showBusinesses')
} }
const initInfo = () => {
dateCangeCrderCount({
areaCode: appStore.delivery_address.areaCode,
streetCode: appStore.delivery_address.streetCode,
}).then(({ data }) => {
let y1 = [], y2 = [], y3 = [], y4 = [];
data.forEach((item) => {
y1.push(item.pendingOrderCount);
y2.push(item.undeliveredOrderCount);
y3.push(item.doneOrderCount);
y4.push(item.hourOrderCount);
})
setTimeout(() => {
initEcahrts(y1, y2, y3, y4);
})
})
}
const pages = ref({
areaCode: appStore.delivery_address.areaCode,
streetCode: appStore.delivery_address.streetCode,
page: 1,
limit: 30
})
const loadOrderList = () => {
getOrderList(pages.value).then((res) => {
initData(res.data.currOrderList);
}).catch(err => {
console.error(err);
})
}
onMounted(() => { onMounted(() => {
initEcahrts() initInfo();
loadOrderList();
}) })
</script> </script>
@ -391,7 +428,11 @@ onMounted(() => {
<div>{{ "〉" }}</div> <div>{{ "〉" }}</div>
</div> </div>
</div> </div>
<dv-scroll-board :config="list" style="width: 100%; height: 90%" /> <dv-scroll-board
ref="scrollBoardRef"
:config="list"
style="width: 100%; height: 90%"
/>
</div> </div>
</div> </div>
</div> </div>
@ -493,6 +534,21 @@ onMounted(() => {
} }
} }
:deep(.div) {
width: 100%;
text-align: center;
height: 100%;
color: aliceblue;
background: rgba(91, 219, 246, 0.2);
white-space: nowrap; /* 防止文本换行 */
overflow: hidden; /* 溢出部分隐藏 */
text-overflow: ellipsis; /* 显示省略号 */
}
:deep(.div2) {
background: rgba(0, 168, 255, 0.16);
}
:deep(.ceil) { :deep(.ceil) {
padding: 0 !important; padding: 0 !important;
margin-bottom: 5px; margin-bottom: 5px;

View File

@ -1,11 +1,30 @@
<script setup> <script setup>
import { reactive, ref } from "vue" import { onMounted, reactive, ref } from "vue"
import border from "@/components/border.vue"; import border from "@/components/border.vue";
import AMap from "./AMap.vue"; import AMap from "./AMap.vue";
import { useAppStore } from "@/store/app.js"
import { logisticsMapCount } from "@/api/index.js";
const test = () => { const appStore = useAppStore();
console.log('ss');
const initInfo = () => {
logisticsMapCount({
areaCode: appStore.delivery_address.areaCode,
streetCode: appStore.delivery_address.streetCode,
courier_id: appStore.delivery_address.courier_id
}).then(res => {
console.log(res);
})
} }
const clickItem = () => {
console.log('点击按钮');
}
onMounted(() => {
initInfo()
})
</script> </script>
<template> <template>
@ -15,14 +34,20 @@ const test = () => {
</div> </div>
<div class="border"></div> <div class="border"></div>
<div class="btn"> <div class="btn">
<div class="c-b" @click.stop="test"> <div class="c-b" @click.stop="clickItem">
<div class="text">已取货(100)</div> <div class="text">
待取货({{ appStore.delivery.pending_order_count }})
</div>
</div> </div>
<div class="c-b" @click.stop="test"> <div class="c-b" @click.stop="clickItem">
<div class="text">已配送(100)</div> <div class="text">
配送中({{ appStore.delivery.delivering_order_count }})
</div>
</div> </div>
<div class="c-b" @click.stop="test"> <div class="c-b" @click.stop="clickItem">
<div class="text">已完成(100)</div> <div class="text">
已完成({{ appStore.delivery.finished_order_count }})
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,137 +5,164 @@ import AMapLeft from "./AMapLeft.vue";
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import { useRoute } from "vue-router" import { useRoute } from "vue-router"
import { latestLogistics } from "@/api/index.js"; import { latestLogistics } from "@/api/index.js";
import { logisticsCount } from "@/api/index.js";
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const route = useRoute(); const route = useRoute();
let noramlSize = 16; let noramlSize = 16;
var datas = {
textValue: "100%", const echartsRef = ref(null);
let datas = {
textValue: "",
colors: ["#31829d", "#009cff", "#4b5fdb"], colors: ["#31829d", "#009cff", "#4b5fdb"],
legendArr: ["待取货", "配送中", "已送达"], legendArr: ["待取货", "配送中", "已送达"],
dataArr: [ dataArr: [
{ value: 335, name: "待取货" }, { value: 0, name: "待取货" },
{ value: 210, name: "配送中" }, { value: 0, name: "配送中" },
{ value: 410, name: "已送达" }, { value: 0, name: "已送达" },
], ],
company: "" company: ""
}; };
const option = {
backgroundColor: "rgba(0,0,0,0)",
color: datas.colors,
grid: {
left: "0%",
right: "0%",
bottom: "0%",
top: "0%"
},
graphic: {
elements: [
{
type: 'text',
left: 'center', //
bottom: '50%', //
style: {
fill: '#fff',
text: datas.textValue,
font: '18px Microsoft YaHei'
}
}
]
},
tooltip: {
trigger: "item",
backgroundColor: "#f6f6f6",
textStyle: {
color: "#000"
},
formatter: "{b}: {c}" + datas.company + " ({d}%)"
},
legend: {
icon: "rect",
bottom: "5%",
left: "center",
itemWidth: 12,
itemHeight: 12,
// itemGap: 50, //
textStyle: {
color: "#fff",
fontSize: noramlSize
},
data: datas.legendArr
},
series: [
{
name: "",
type: "pie",
radius: ["45%", "60%"],
center: ["50%", "45%"],
itemStyle: {
normal: {
borderWidth: 10,
borderColor: "#092846"
}
},
avoidLabelOverlap: false,
label: {
show: false,
position: 'bottom'
},
labelLine: {
normal: {
show: true,
lineStyle: {
color: "#138af4"
},
length: 20,
length2: 50,
}
},
data: datas.dataArr
},
{
type: "pie",
radius: "40%",
center: ["50%", "45%"],
z: -2,
label: {
show: false
},
labelLine: {
show: false
},
itemStyle: {
color: 'rgba(255,255,255,0.2)'
},
data: [100]
},
]
};
const echartsRef = ref(null)
const initEcahrts = () => { const initEcahrts = () => {
// DOMecharts // DOMecharts
const chart = echarts.init(echartsRef.value); const chart = echarts.init(echartsRef.value);
let option = {
backgroundColor: "rgba(0,0,0,0)",
color: datas.colors,
grid: {
left: "0%",
right: "0%",
bottom: "0%",
top: "0%"
},
graphic: {
elements: [
{
type: 'text',
left: 'center', //
bottom: '50%', //
style: {
fill: '#fff',
text: datas.textValue,
font: '18px Microsoft YaHei'
}
}
]
},
tooltip: {
trigger: "item",
backgroundColor: 'rgba(18, 57, 60, .8)', //
textStyle: {
color: '#fff'
},
borderColor: "rgba(18, 57, 60, .8)",
axisPointer: {
type: 'shadow',
shadowStyle: {
color: 'rgba(0, 11, 34, .4)',
}
},
formatter: "{b}: {c}" + datas.company + " ({d}%)"
},
legend: {
icon: "rect",
bottom: "5%",
left: "center",
itemWidth: 12,
itemHeight: 12,
// itemGap: 50, //
textStyle: {
color: "#fff",
fontSize: noramlSize
},
data: datas.legendArr
},
series: [
{
name: "",
type: "pie",
radius: ["45%", "60%"],
center: ["50%", "45%"],
itemStyle: {
normal: {
borderWidth: 10,
borderColor: "#092846"
}
},
avoidLabelOverlap: false,
label: {
show: false,
position: 'bottom'
},
labelLine: {
normal: {
show: true,
lineStyle: {
color: "#138af4"
},
length: 20,
length2: 50,
}
},
data: datas.dataArr
},
{
type: "pie",
radius: "40%",
center: ["50%", "45%"],
z: -2,
tooltip: {
show: false
},
label: {
show: false
},
labelLine: {
show: false
},
itemStyle: {
color: 'rgba(255,255,255,0.2)'
},
data: [100]
},
]
};
// 使 // 使
chart.setOption(option); chart.setOption(option);
} }
const info = ref({}); const info = ref({});
const delivery = ref({});
const loadInfo = () => { const loadInfo = () => {
latestLogistics({ latestLogistics({
areaCode: 510524, areaCode: appStore.delivery_address.areaCode,
streetCode: 510524100, streetCode: appStore.delivery_address.streetCode,
}).then(res => { }).then(res => {
info.value = res.data; info.value = res.data;
}) })
logisticsCount({
areaCode: appStore.delivery_address.areaCode,
streetCode: appStore.delivery_address.streetCode
}).then(res => {
delivery.value = res.data;
datas.dataArr[0].value = res.data.pending_order_count;
datas.dataArr[1].value = res.data.delivering_order_count;
datas.dataArr[2].value = res.data.finished_order_count;
initEcahrts();
appStore.setDelivery(res.data);
})
} }
onMounted(() => { onMounted(() => {
loadInfo(); loadInfo();
initEcahrts();
}) })
</script> </script>
@ -237,7 +264,7 @@ onMounted(() => {
</div> </div>
</div> </div>
<div class="map"> <div class="map">
<AMapLeft></AMapLeft> <AMapLeft :info="info" v-if="info.user_address"></AMapLeft>
<div class="border"></div> <div class="border"></div>
</div> </div>
<div class="head-box b-box">物流信息</div> <div class="head-box b-box">物流信息</div>
@ -245,11 +272,15 @@ onMounted(() => {
<div class="left"> <div class="left">
<div class="left-item"> <div class="left-item">
<img class="img" src="/src/assets/delivery_img/icon7.png" /> <img class="img" src="/src/assets/delivery_img/icon7.png" />
<div>配送人员<span>里斯</span></div> <div>
配送人员<span>{{ delivery.courier_name || "-" }}</span>
</div>
</div> </div>
<div class="left-item"> <div class="left-item">
<img class="img" src="/src/assets/delivery_img/icon3.png" /> <img class="img" src="/src/assets/delivery_img/icon3.png" />
<div>配送车辆<span>川E G856Z</span></div> <div>
配送车辆<span>{{ delivery.car_license || "-" }}</span>
</div>
</div> </div>
</div> </div>
<div class="right echarts" ref="echartsRef"></div> <div class="right echarts" ref="echartsRef"></div>

View File

@ -1,31 +1,12 @@
<script setup> <script setup>
import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue" import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue"
import border from "../../../components/border.vue" import border from "../../../components/border.vue"
const items = reactive([ import { deliveredProductRanking } from "@/api/index.js"
{ id: 1, text: '莲花池 1' }, import { useAppStore } from "@/store/app.js"
{ id: 2, text: '莲花池 2' },
{ id: 3, text: '莲花池 3' }, const appStore = useAppStore();
{ id: 3, text: '莲花池 4' },
{ id: 3, text: '莲花池 5' }, const items = ref([])
{ id: 3, text: '莲花池 6' },
{ id: 3, text: '莲花池 7' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
{ id: 3, text: '莲花池 8' },
])
const scrollContainerRef = ref(null); const scrollContainerRef = ref(null);
let timer = null; let timer = null;
const autoScroll = () => { const autoScroll = () => {
@ -42,7 +23,30 @@ const autoScroll = () => {
}, 50) }, 50)
}, 1000) }, 1000)
} }
const max = ref(0)
const loadList = () => {
deliveredProductRanking({
areaCode: appStore.address.areaCode,
streetCode: appStore.address.streetCode,
}).then((res) => {
items.value = res.data;
res.data.forEach(e => {
if (+e.total_quantity >= max.value) {
max.value = +e.total_quantity;
}
});
})
}
const cWidth = (e) => {
return (e / max.value * 100).toFixed(0);
}
onMounted(() => { onMounted(() => {
loadList();
nextTick(() => { nextTick(() => {
autoScroll(); autoScroll();
}) })
@ -73,15 +77,17 @@ onUnmounted(() => {
<div class="rank" :class="index < 3 ? 'rank1' : 'rank2'"> <div class="rank" :class="index < 3 ? 'rank1' : 'rank2'">
{{ index + 1 }} {{ index + 1 }}
</div> </div>
<div class="name">{{ item.text }}</div> <div class="name">
<div>{{ item.store_name }}</div>
</div>
<div class="line"> <div class="line">
<div <div
class="line-body" class="line-body"
:style="{ width: '80%' }" :style="{ width: cWidth(item.total_quantity) + '%' }"
:class="{ 'line-body2': index >= 3 }" :class="{ 'line-body2': index >= 3 }"
></div> ></div>
</div> </div>
<div class="count">6000</div> <div class="count">{{ item.total_quantity }}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,6 +3,9 @@ import { onMounted, reactive, ref } from "vue";
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import border from "../../../components/border.vue" import border from "../../../components/border.vue"
import { orderRanking } from "@/api/index.js" import { orderRanking } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const xData2 = ref([]); const xData2 = ref([]);
const data1 = ref([]); const data1 = ref([]);
@ -157,8 +160,8 @@ const initMap = () => {
const loadOrderList = () => { const loadOrderList = () => {
orderRanking({ orderRanking({
areaCode: '510524', areaCode: appStore.address.areaCode,
streetCode: '510524100', streetCode: appStore.address.streetCode,
type: 2, // 1, 2 type: 2, // 1, 2
}).then((res) => { }).then((res) => {
orderCount.value = res.data.orderCount; orderCount.value = res.data.orderCount;

View File

@ -3,6 +3,9 @@ import { onMounted, reactive, ref } from "vue"
import border from "@/components/border.vue" import border from "@/components/border.vue"
import mitt from "@/utils/mitt" import mitt from "@/utils/mitt"
import { orderList } from "@/api/index.js" import { orderList } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const initData = (data) => { const initData = (data) => {
let arr = []; let arr = [];
@ -106,8 +109,8 @@ const cOrder = () => {
} }
const pages = ref({ const pages = ref({
areaCode: 510524, areaCode: appStore.address.areaCode,
streetCode: 510524100, streetCode: appStore.address.streetCode,
page: 1, page: 1,
limit: 30 limit: 30
}) })
@ -177,7 +180,7 @@ onMounted(() => {
<div class="num">{{ cell[1].count }}</div> <div class="num">{{ cell[1].count }}</div>
</div> </div>
<dv-percent-pond :config="cell[1]" class="cell" /> <dv-percent-pond :config="cell[1]" class="cell" />
<div class="type">配送订单数</div> <div class="type">配送订单数</div>
</div> </div>
<div class="cy"> <div class="cy">
<div class="text"> <div class="text">

View File

@ -2,6 +2,10 @@
import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue" import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue"
import border from "../../../components/border.vue" import border from "../../../components/border.vue"
import { orderRanking } from "@/api/index.js" import { orderRanking } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const items = ref([]) const items = ref([])
const scrollContainerRef = ref(null); const scrollContainerRef = ref(null);
let timer = null; let timer = null;
@ -24,8 +28,8 @@ const max = ref(0);
const loadOrderList = () => { const loadOrderList = () => {
orderRanking({ orderRanking({
areaCode: '510524', areaCode: appStore.address.areaCode,
streetCode: '510524100', streetCode: appStore.address.streetCode,
type: 1, // 1, 2 type: 1, // 1, 2
}).then((res) => { }).then((res) => {
items.value = res.data.townOrderList; items.value = res.data.townOrderList;

View File

@ -3,14 +3,17 @@ import border from "@/components/border.vue"
import { vehicleList } from "@/api/index.js"; import { vehicleList } from "@/api/index.js";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const list = ref([]) const list = ref([])
const count = ref(0); const count = ref(0);
const loadList = () => { const loadList = () => {
vehicleList({ vehicleList({
eaCode: '510524', areaCode: appStore.address.areaCode,
streetCode: '510524100', streetCode: appStore.address.streetCode,
}).then(res => { }).then(res => {
list.value = res.data.list; list.value = res.data.list;
count.value = res.data.count; count.value = res.data.count;
@ -23,14 +26,16 @@ const loadList = () => {
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const navToDelivery = (id) => { const navToDelivery = (item) => {
if (route.path == '/') router.push({ item.areaCode = item.area_code;
item.streetCode = item.street_code;
appStore.setDeliveryAddress(item);
router.push({
path: '/delivery', path: '/delivery',
query: { query: {
id id: item.id
} }
}); });
else router.back();
} }
@ -59,7 +64,7 @@ onMounted(() => {
:class="{ 'car-item2': index > 1 }" :class="{ 'car-item2': index > 1 }"
v-for="(item, index) in list.slice(0, 4)" v-for="(item, index) in list.slice(0, 4)"
:key="index" :key="index"
@click="navToDelivery(item.id)" @click="navToDelivery(item)"
> >
<img class="img" src="/src/assets/img/icon-car.png" /> <img class="img" src="/src/assets/img/icon-car.png" />
<div>{{ item.license }}</div> <div>{{ item.license }}</div>
@ -81,7 +86,7 @@ onMounted(() => {
:class="{ 'car-item2': index > 2 && index < 5 }" :class="{ 'car-item2': index > 2 && index < 5 }"
v-for="(item, index) in list.slice(4, 13)" v-for="(item, index) in list.slice(4, 13)"
:key="index" :key="index"
@click="navToDelivery(item.id)" @click="navToDelivery(item)"
> >
<img class="img" src="/src/assets/img/icon-car.png" /> <img class="img" src="/src/assets/img/icon-car.png" />
<div>{{ item.license }}</div> <div>{{ item.license }}</div>

View File

@ -2,6 +2,9 @@
import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue" import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue"
import border from "../../../components/border.vue" import border from "../../../components/border.vue"
import { deliveredProductRanking } from "@/api/index.js" import { deliveredProductRanking } from "@/api/index.js"
import { useAppStore } from "@/store/app.js"
const appStore = useAppStore();
const items = ref([]); const items = ref([]);
const max = ref(0); const max = ref(0);
@ -24,8 +27,8 @@ const autoScroll = () => {
const loadList = () => { const loadList = () => {
deliveredProductRanking({ deliveredProductRanking({
areaCode: 510524, areaCode: appStore.address.areaCode,
streetCode: 510524100, streetCode: appStore.address.streetCode,
}).then((res) => { }).then((res) => {
items.value = res.data; items.value = res.data;
res.data.forEach(e => { res.data.forEach(e => {

200
src/view/login/index.vue Normal file
View File

@ -0,0 +1,200 @@
<script setup>
import { ref, reactive } from "vue"
import { useRouter } from "vue-router";
import { loginAPI } from "@/api/api.js"
const router = useRouter()
const show = ref(false)
const account = ref('')
const password = ref('')
const isAccount = ref(false)
const isPassword = ref(false)
const submit = () => {
if (!account.value) {
isAccount.value = true;
return
}
else isAccount.value = false;
if (!password.value) {
isPassword.value = true;
return
}
else isPassword.value = false;
loginAPI({
account: account.value,
password: password.value
}).then(res => {
console.log(res);
// localStorage.setItem("TOKEN", 15455465465465)
// router.replace('/')
})
return
}
</script>
<template>
<dv-full-screen-container class="body">
<div class="login-box">
<div class="form">
<div class="content" style="padding-top: 2.5rem">
<div class="line-box">
<input
class="ipt"
type="text"
placeholder="请输入账号"
v-model="account"
/>
<div class="line">
<img
src="/src/assets/login_img/ZH.png"
alt=""
class="accont-icon"
/>
</div>
</div>
<div class="tips">
<span v-show="isAccount">请输入账号</span>
</div>
<div class="line-box">
<input
class="ipt"
placeholder="请输入密码"
:type="show ? 'text' : 'password'"
v-model="password"
/>
<div class="line">
<img
src="/src/assets/login_img/MM.png"
alt=""
class="accont-icon"
style=""
/>
<img
src="/src/assets/login_img/KJ.png"
v-if="show"
alt=""
@click="show = false"
class="accont-icon"
/>
<img
src="/src/assets/login_img/BKH.png"
v-else
@click="show = true"
class="accont-icon"
/>
</div>
</div>
<div class="tips">
<span v-show="isPassword">请输入密码</span>
</div>
<button class="btn" @click="submit">登录</button>
</div>
</div>
</div>
</dv-full-screen-container>
</template>
<style lang="scss" scoped>
.body {
background-image: url("/src/assets/img/bg.png");
background-size: 100% 100%;
color: #fff;
background-color: rgba($color: #000000, $alpha: 0.8);
}
.login-box {
width: 100%;
height: 100%;
background-image: url(../../assets/login_img/bg.png);
background-size: 100% 100%;
overflow: hidden;
}
.form {
width: 30%;
height: 45%;
position: absolute;
top: 25%;
right: 10%;
box-sizing: border-box;
background: url(../../assets/login_img/DLBG.png);
background-size: 100% 100%;
display: flex;
justify-content: center;
align-items: center;
.content {
width: 60%;
height: 60%;
.ipt {
border: 1px solid #194fa3;
background-color: #123266;
width: 100%;
box-sizing: border-box;
padding: 0.5rem 2.5rem;
outline: none;
-webkit-user-select: auto;
caret-color: #fff;
color: white;
}
.line-box {
position: relative;
width: 100%;
margin-top: 1rem;
.line {
width: 100%;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
left: 0;
display: flex;
justify-content: space-between;
padding: 0 0.5rem;
box-sizing: border-box;
align-items: center;
}
input {
font-size: 1rem;
}
}
input[type="password"]::-ms-reveal {
display: none;
}
.tips {
width: 100%;
height: 1.5rem;
margin-top: 0.3rem;
text-align: start;
color: red;
span {
margin-left: 2.5rem;
}
}
.btn {
width: 100%;
margin-top: 2rem;
background-color: #0040a1;
color: #fff;
border-radius: 0;
border: 0.1rem solid #2873ff;
}
.accont-icon {
width: 1rem;
height: 1rem;
pointer-events: all !important;
}
}
}
</style>