| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- import { getMyProfile } from '@/api/fulfiller/fulfiller'
- import { getPendingOrders, acceptOrder, getOrderCount, rejectOrderApi } from '@/api/order/subOrder'
- import { listAllService } from '@/api/service/list'
- import { getAreaStationList } from '@/api/system/areaStation'
- import { isLoggedIn } from '@/utils/auth'
- import { reportGps } from '@/utils/gps'
- import customTabbar from '@/components/custom-tabbar/index.vue'
- export default {
- components: {
- customTabbar
- },
- data() {
- return {
- taskList: [],
- currentFilter: 'default', // default, distance, time
- filterCondition: '筛选条件',
- sortDistance: 'asc', // asc, desc
- sortTime: 'asc',
- scrollTop: 0, // Track scroll position
- isFilterShow: false,
- tempFilter: {
- service: null,
- distance: '全部',
- amount: '全部'
- },
- activeFilter: {
- service: null,
- distance: '全部',
- amount: '全部'
- },
- workStatus: 'resting', // resting | busy | disabled
- showConfirmModal: false,
- showPetModal: false,
- currentPetInfo: {},
- showRejectModal: false,
- rejectReason: '',
- currentOrder: null,
- showAcceptConfirmModal: false,
- showNavModal: false,
- navTargetItem: null,
- navTargetPointType: '',
- profile: null,
- profileLoading: false,
- serviceList: [],
- orderStats: {
- total: 0,
- reject: 0,
- completed: 0,
- price: 0
- }
- }
- },
- onPageScroll(e) {
- this.scrollTop = e.scrollTop;
- },
- async onLoad() {
- // Initial load
- this.checkWorkStatus();
- await this.loadServiceList();
- this.loadTaskList();
-
- // 显式请求一次定位授权
- reportGps(true).catch(e => console.log('Init GPS check skipped', e));
- },
- onShow() {
- uni.hideTabBar()
- this.checkWorkStatus();
- if (isLoggedIn()) {
- // 每次进入页面强制刷新所有展示数据
- this.loadProfile()
- this.loadOrderStats()
- this.loadTaskList()
- this.loadServiceList() // 确保服务配置也是最新的
- }
- },
- async onPullDownRefresh() {
- this.checkWorkStatus();
- try {
- await this.loadServiceList();
- const tasks = [
- this.loadTaskList()
- ];
- if (isLoggedIn()) {
- tasks.push(this.loadProfile());
- tasks.push(this.loadOrderStats());
- }
- await Promise.all(tasks);
- } catch (err) {
- console.error('刷新异常:', err);
- } finally {
- uni.stopPullDownRefresh();
- uni.showToast({ title: '刷新成功', icon: 'success' });
- }
- },
- methods: {
- async loadProfile() {
- if (this.profileLoading) return
- this.profileLoading = true
- try {
- const res = await getMyProfile()
- const data = res.data || null
-
- if (data) {
- // 以服务器返回的状态为准进行更新
- if (data.status) {
- this.workStatus = data.status;
- uni.setStorageSync('workStatus', data.status);
- }
- // 需求:头部的接单城市使用站点往上找到城市,而非直接显示站点
- if (data.stationId) {
- try {
- const stationRes = await getAreaStationList();
- const list = stationRes.data || [];
- const currentStation = list.find(i => i.id === data.stationId);
- if (currentStation) {
- // 向上溯源:直到找到 parentId 为 0 的节点(即顶层城市)
- let node = currentStation;
- while (node && node.parentId !== 0) {
- let parent = list.find(i => i.id === node.parentId);
- if (parent) {
- node = parent;
- } else {
- break;
- }
- }
- // 将溯源到的节点名称作为显示城市
- data.cityName = node.name;
- }
- } catch (e) {
- console.error('溯源城市失败:', e);
- }
- }
- }
-
- this.profile = data
- } catch (err) {
- console.error('获取个人信息失败:', err)
- } finally {
- this.profileLoading = false
- }
- },
- async loadServiceList() {
- try {
- const res = await listAllService()
- this.serviceList = res.data || []
- } catch (err) {
- console.error('获取服务类型失败:', err)
- }
- },
- async loadOrderStats() {
- try {
- const res = await getOrderCount()
- this.orderStats = res.data || { total: 0, reject: 0, completed: 0, price: 0 }
- } catch (err) {
- console.error('获取订单统计失败:', err)
- }
- },
- checkWorkStatus() {
- const status = uni.getStorageSync('workStatus');
- if (status) {
- this.workStatus = status;
- } else {
- // 默认状态为休息
- this.workStatus = 'resting';
- uni.setStorageSync('workStatus', 'resting');
- }
- },
- toggleFilter() {
- if (this.workStatus === 'resting') return; // Disable filter when resting? Or keep it? User didn't specify, but usually disabled. Let's keep it enabled for now as they might look at filters before working.
- this.isFilterShow = !this.isFilterShow;
- },
- goToWorkStatus() {
- uni.navigateTo({
- url: '/pages/home/work-status'
- });
- },
- async handleManualLocation() {
- try {
- uni.showLoading({ title: '定位获取中...', mask: true });
- await reportGps(true);
- uni.showToast({ title: '位置已更新', icon: 'success' });
- } catch (e) {
- console.error('Manual location failed', e);
- } finally {
- uni.hideLoading();
- }
- },
- startWork() {
- this.showConfirmModal = true;
- },
- confirmStartWork() {
- this.workStatus = 'busy';
- uni.setStorageSync('workStatus', 'busy');
- this.loadTaskList();
- this.showConfirmModal = false;
- uni.showToast({ title: '已开始接单', icon: 'success' });
- },
- closeConfirmModal() {
- this.showConfirmModal = false;
- },
- showPetProfile(item) {
- this.currentPetInfo = item;
- this.showPetModal = true;
- },
- closePetProfile() {
- this.showPetModal = false;
- },
- openRejectModal(item) {
- this.currentOrder = item;
- this.rejectReason = '';
- this.showRejectModal = true;
- },
- closeRejectModal() {
- this.showRejectModal = false;
- this.currentOrder = null;
- },
- async confirmReject() {
- if (!this.rejectReason.trim()) {
- uni.showToast({ title: '请输入拒绝理由', icon: 'none' });
- return;
- }
- if (!this.currentOrder?.id) return
- try {
- uni.showLoading({ title: '提交中...', mask: true });
- await rejectOrderApi({
- orderId: this.currentOrder.id,
- rejectReason: this.rejectReason
- });
- uni.showToast({ title: '已拒绝接单', icon: 'success' });
- this.showRejectModal = false;
- this.currentOrder = null;
- this.loadTaskList();
- this.loadOrderStats();
- } catch (err) {
- console.error('拒绝接单失败:', err);
- uni.showToast({ title: '操作失败', icon: 'none' });
- } finally {
- uni.hideLoading();
- }
- },
- openAcceptModal(item) {
- this.currentOrder = item;
- this.showAcceptConfirmModal = true;
- },
- closeAcceptModal() {
- this.showAcceptConfirmModal = false;
- this.currentOrder = null;
- },
- async confirmAccept() {
- if (!this.currentOrder?.id) return
- try {
- await acceptOrder(this.currentOrder.id)
- uni.showToast({ title: '接单成功', icon: 'success' })
- this.showAcceptConfirmModal = false
- this.currentOrder = null
- this.loadTaskList()
- this.loadProfile()
- this.loadOrderStats()
- } catch (err) {
- console.error('接单失败:', err)
- uni.showToast({ title: '接单失败', icon: 'none' })
- }
- },
- openNavigation(item, pointType) {
- this.navTargetItem = item;
- this.navTargetPointType = pointType;
- this.showNavModal = true;
- },
- closeNavModal() {
- this.showNavModal = false;
- },
- chooseMap(mapType) {
- let item = this.navTargetItem;
- let pointType = this.navTargetPointType;
- // 起 -> fromAddress ; 终 -> toAddress
- let name = pointType === 'start' ? (item.fromAddress || '起点') : (item.toAddress || '终点');
- let address = pointType === 'start' ? (item.fromAddress || '起点地址') : (item.toAddress || '终点地址');
- let latitude = pointType === 'start' ? Number(item.fromLat) : Number(item.toLat);
- let longitude = pointType === 'start' ? Number(item.fromLng) : Number(item.toLng);
- this.showNavModal = false;
- // 统一定义打开地图的函数
- const navigateTo = (lat, lng, addrName, addrDesc) => {
- uni.openLocation({
- latitude: lat,
- longitude: lng,
- name: addrName,
- address: addrDesc || '无法获取详细地址',
- success: function () {
- console.log('打开导航成功: ' + mapType);
- },
- fail: function (err) {
- console.error('打开导航失败:', err);
- uni.showToast({ title: '打开地图失败', icon: 'none' });
- }
- });
- };
- // 如果有目标经纬度,直接打开
- if (latitude && longitude && !isNaN(latitude) && !isNaN(longitude)) {
- navigateTo(latitude, longitude, name, address);
- } else {
- // 如果没有经纬度,按照需求:使用自己当前的经纬度,然后搜索 fromAddress 或者 toAddress
- uni.showLoading({ title: '获取当前位置...', mask: true });
- uni.getLocation({
- type: 'gcj02',
- success: (res) => {
- uni.hideLoading();
- // 使用用户当前经纬度作为锚点打开地图,展示目标地址信息
- navigateTo(res.latitude, res.longitude, name, address);
- },
- fail: (err) => {
- uni.hideLoading();
- console.error('获取地理位置失败:', err);
- uni.showToast({ title: '无法获取当前位置信息', icon: 'none' });
- }
- });
- }
- },
- selectService(type) {
- this.tempFilter.service = type;
- },
- selectDistance(type) {
- this.tempFilter.distance = type;
- },
- selectAmount(type) {
- this.tempFilter.amount = type;
- },
- resetFilter() {
- this.tempFilter = {
- service: null,
- distance: '全部',
- amount: '全部'
- };
- },
- confirmFilter() {
- this.activeFilter = { ...this.tempFilter };
- this.isFilterShow = false;
- this.loadTaskList();
- },
- closeFilter() {
- this.isFilterShow = false;
- },
- goToDetail(item) {
- console.log('Go to detail', item);
- },
- async loadTaskList() {
- try {
- const params = {
- service: this.activeFilter.service,
- minPrice: this.getMinPrice(),
- maxPrice: this.getMaxPrice(),
- pageNum: 1,
- pageSize: 20
- }
- const res = await getPendingOrders(params)
- this.taskList = (res.rows || []).map(item => this.transformOrder(item))
- } catch (err) {
- console.error('获取订单列表失败:', err)
- uni.showToast({ title: '加载失败', icon: 'none' })
- this.taskList = []
- }
- },
- getMinPrice() {
- const amount = this.activeFilter.amount
- if (amount === '100以下') return 0
- if (amount === '100-200') return 10000
- if (amount === '200-500') return 20000
- if (amount === '500以上') return 50000
- return undefined
- },
- getMaxPrice() {
- const amount = this.activeFilter.amount
- if (amount === '100以下') return 10000
- if (amount === '100-200') return 20000
- if (amount === '200-500') return 50000
- return undefined
- },
- transformOrder(item) {
- const service = this.serviceList.find(s => s.id === item.service)
- const serviceText = service?.name || '未知'
- const serviceIcon = service?.iconUrl || ''
- const mode = service?.mode || 0
- const isRoundTrip = mode === 1
- return {
- id: item.id,
- type: isRoundTrip ? 1 : item.service,
- typeText: serviceText,
- typeIcon: serviceIcon,
- price: (item.price / 100).toFixed(2),
- timeLabel: '服务时间',
- time: item.serviceTime,
- petAvatar: item.petAvatar || '/static/dog.png',
- petAvatarUrl: item.petAvatarUrl || '',
- petName: item.petName,
- petBreed: item.breed,
- petGender: 'M',
- petAge: '',
- petWeight: '',
- petPersonality: '',
- petHobby: '',
- petRemark: '',
- petTags: [],
- petLogs: [],
- startLocation: item.fromAddress || '暂无起点',
- startAddress: item.fromAddress || '',
- fromAddress: item.fromAddress || '',
- fromLat: item.fromLat,
- fromLng: item.fromLng,
- startDistance: '0km',
- endLocation: (item.customerName || item.contact || '') + ' ' + (item.customerPhone || ''),
- endAddress: item.toAddress || '',
- toAddress: item.toAddress || '',
- toLat: item.toLat,
- toLng: item.toLng,
- endDistance: '0km',
- serviceContent: '',
- remark: item.remark || ''
- }
- },
- setFilter(type) {
- this.currentFilter = type;
- if (type === 'distance') {
- this.sortDistance = this.sortDistance === 'asc' ? 'desc' : 'asc';
- uni.showToast({ title: `按距离${this.sortDistance === 'asc' ? '升序' : '降序'}`, icon: 'none' });
- } else if (type === 'time') {
- this.sortTime = this.sortTime === 'asc' ? 'desc' : 'asc';
- uni.showToast({ title: `按时间${this.sortTime === 'asc' ? '升序' : '降序'}`, icon: 'none' });
- }
- },
- showFilterDropdown() {
- this.toggleFilter();
- }
- }
- }
|