<template>
    <view class="container">
        <!-- 吸顶固定层：状态tab + 搜索 + 筛选 -->
        <view class="sticky-header">
            <!-- 顶部 Tab (待接送/服务中...) -->
            <view class="status-tabs">
                <view class="tab-item" v-for="(tab, index) in tabs" :key="index"
                    :class="{ active: currentTab === index }" @click="currentTab = index">
                    <text>{{ tab }}</text>
                    <view class="indicator" v-if="currentTab === index"></view>
                </view>
            </view>

            <!-- 搜索栏 -->
            <view class="search-bar">
                <view class="search-input-box">
                    <input class="search-input" v-model="searchContent" placeholder="搜索地址/电话/姓名"
                        placeholder-class="ph-style" />
                </view>
            </view>

            <!-- 筛选栏 (支持自定义下拉) -->
            <view class="filter-wrapper">
                <view class="filter-bar">
                    <!-- 订单类型下拉视图 -->
                    <view class="filter-item" :class="{ 'active': activeDropdown === 1 }" @click="toggleDropdown(1)">
                        <text :class="{ 'active-text': activeDropdown === 1 || currentTypeFilterIdx > 0 }">
                            {{ currentTypeFilterIdx > 0 ? typeFilterOptions[currentTypeFilterIdx] : '全部类型' }}
                        </text>
                        <view class="triangle" :class="activeDropdown === 1 ? 'up' : 'down'"></view>
                    </view>

                    <!-- 服务时间下拉视图 -->
                    <view class="filter-item" :class="{ 'active': activeDropdown === 2 }" @click="toggleDropdown(2)">
                        <text :class="{ 'active-text': activeDropdown === 2 || hasTimeFilter }">服务时间</text>
                        <view class="triangle" :class="activeDropdown === 2 ? 'up' : 'down'"></view>
                    </view>
                </view>

                <!-- 下拉内容面板与遮罩 -->
                <view class="dropdown-mask" v-if="activeDropdown !== 0" @click="closeDropdown"></view>
                <view class="dropdown-panel" v-if="activeDropdown === 1">
                    <view class="type-option" v-for="(item, index) in typeFilterOptions" :key="index"
                        :class="{ 'selected': currentTypeFilterIdx === index }" @click="selectType(index)">
                        <text>{{ item }}</text>
                    </view>
                </view>
                <view class="dropdown-panel calendar-panel" v-if="activeDropdown === 2">
                    <view class="custom-calendar-container">
                        <!-- 头部 -->
                        <view class="cal-header">
                            <text class="cal-nav-btn" @click="prevMonth">‹</text>
                            <text class="cal-title">{{ currentMonth }}</text>
                            <text class="cal-nav-btn" @click="nextMonth">›</text>
                        </view>
                        <!-- 星期条 -->
                        <view class="cal-weekdays">
                            <text v-for="(wk, idx) in weekDays" :key="idx" class="wk-item">{{ wk }}</text>
                        </view>
                        <!-- 日期网格 -->
                        <view class="cal-body">
                            <view v-for="(day, idx) in calendarDays" :key="idx" class="cal-day-box"
                                :class="day ? getDateClass(day) : ''" @click="day && selectDateItem(day)">
                                <view class="cal-day-text" v-if="day">{{ day }}</view>
                            </view>
                        </view>
                    </view>
                    <view class="calendar-actions">
                        <button class="cal-btn reset" @click="resetTimeFilter">重置</button>
                        <button class="cal-btn confirm" @click="confirmTimeFilter">确定</button>
                    </view>
                </view>
            </view><!-- end filter-wrapper -->
        </view><!-- end sticky-header -->

        <!-- 订单列表 -->
        <view class="order-list">
            <view class="order-card" v-for="(item, index) in orderList" :key="index">
                <view class="card-header">
                    <view class="type-badge">
                        <image class="type-icon" :src="item.typeIcon"></image>
                        <text class="type-text">{{ item.typeText }}</text>
                    </view>
                    <text class="status-badge" :class="getStatusClass(item)">{{ getDisplayStatus(item) }}</text>
                </view>

                <view class="card-body">
                    <view class="time-row">
                        <view class="time-col">
                            <text class="label">{{ item.timeLabel }}：</text>
                            <text class="value">{{ item.time }}</text>
                        </view>
                        <text class="fulfillmentCommission">¥{{ item.fulfillmentCommission }}</text>
                    </view>

                    <!-- 宠物信息 -->
                    <view class="pet-card">
                        <image class="pet-avatar" :src="item.petAvatarUrl || item.petAvatar" mode="aspectFill"></image>
                        <view class="pet-info">
                            <text class="pet-name">{{ item.petName }}</text>
                            <text class="pet-breed">品种: {{ item.petBreed }}</text>
                        </view>
                    </view>

                    <!-- 路线信息 (完全复用 Home 样式) -->
                    <view class="route-info">
                        <template v-if="item.type === 1">
                            <view class="route-item" @click.stop="openNavigation(item, 'start')">
                                <view class="icon-circle start">起</view>
                                <view class="route-line-vertical"></view>
                                <view class="address-box">
                                    <text class="addr-title">{{ item.startLocation }}</text>
                                    <text class="addr-desc">{{ item.startAddress }}</text>
                                </view>
                                <image class="nav-arrow" src="/static/icons/nav_arrow.svg"
                                    style="flex-shrink: 0; align-self: center;"></image>
                            </view>

                            <view class="route-item" @click.stop="openNavigation(item, 'end')">
                                <view class="icon-circle end">终</view>
                                <view class="address-box">
                                    <text class="addr-title">{{ item.endLocation }}</text>
                                    <text class="addr-desc">{{ item.endAddress }}</text>
                                </view>
                                <image class="nav-arrow" src="/static/icons/nav_arrow.svg"
                                    style="flex-shrink: 0; align-self: center;"></image>
                            </view>
                        </template>
                        <template v-else>
                            <view class="route-item" @click.stop="openNavigation(item, 'end')">
                                <view class="icon-circle service">服</view>
                                <view class="address-box">
                                    <text class="addr-title">{{ item.endLocation }}</text>
                                    <text class="addr-desc">{{ item.endAddress }}</text>
                                </view>
                                <image class="nav-arrow" src="/static/icons/nav_arrow.svg"
                                    style="flex-shrink: 0; align-self: center;"></image>
                            </view>
                            <view class="service-content" v-if="item.serviceContent">
                                <text class="content-label">服务内容:</text>
                                <text>{{ item.serviceContent }}</text>
                            </view>
                        </template>
                    </view>

                    <!-- 备注 -->
                    <view class="remark-box">
                        <text>备注：{{ item.remark || '-' }}</text>
                    </view>
                </view><!-- End of card-body -->

                <!-- 按钮组 (常驻显示六个按钮) -->
                <view class="action-btns" v-if="['到达打卡', '到达', '出发', '开始', '送达', '结束'].includes(item.statusText)">
                    <view class="action-row">
                        <button class="btn normal" @click.stop="reportAbnormal(item)">异常上报</button>
                        <button class="btn normal" @click.stop="addOrUpdateService(item)">服务变更</button>
                        <button class="btn normal danger" @click.stop="handleCancelOrder(item)">取消订单</button>
                    </view>
                    <view class="action-row">
                        <button class="btn normal" @click.stop="doCall('customer', item)">拨打电话</button>
                        <button class="btn normal" @click.stop="viewAppealProgress(item)">变更进度</button>
                        <button class="btn primary" @click.stop="mainAction(item)">{{ item.statusText }}</button>
                    </view>
                </view>
            </view>
            <!-- 已加载完提示文字 -->
            <view class="loading-text">已加载完</view>
            <view style="height: 160rpx;"></view>
        </view>
        <view class="call-mask" v-if="activeCallItem" @click="closeCallMenu"></view>
    </view>

    <!-- 宠物档案弹窗 (复用Home) -->
    <view class="pet-modal-mask" v-if="showPetModal" @click="closePetProfile">
        <view class="pet-modal-content" @click.stop>
            <view class="pet-modal-header">
                <text class="pet-modal-title">宠物档案</text>
                <view class="pm-header-actions">
                    <view class="pm-remark-btn" @click="openRemarkInput">备注</view>
                    <view class="close-icon-btn" @click="closePetProfile">×</view>
                </view>
            </view>
            <scroll-view scroll-y class="pet-modal-scroll">
                <!-- Basic Info -->
                <view class="pet-base-info">
                    <image class="pm-avatar" :src="currentPetInfo.petAvatar" mode="aspectFill"></image>
                    <view class="pm-info-text">
                        <view class="pm-name-row">
                            <text class="pm-name">{{ currentPetInfo.petName }}</text>
                            <view class="pm-gender" v-if="currentPetInfo.petGender === 'M'">
                                <text class="gender-icon">♂</text>
                                <text>公</text>
                            </view>
                            <view class="pm-gender female" v-else-if="currentPetInfo.petGender === 'F'">
                                <text class="gender-icon">♀</text>
                                <text>母</text>
                            </view>
                        </view>
                        <text class="pm-breed">品种：{{ currentPetInfo.petBreed }}</text>
                    </view>
                </view>
                <!-- Details Grid -->
                <view class="pm-detail-grid">
                    <view class="pm-grid-item half">
                        <text class="pm-label">年龄</text>
                        <text class="pm-val">{{ currentPetInfo.petAge || '未知' }}</text>
                    </view>
                    <view class="pm-grid-item half">
                        <text class="pm-label">体重</text>
                        <text class="pm-val">{{ currentPetInfo.petWeight || '未知' }}</text>
                    </view>
                    <view class="pm-grid-item full">
                        <text class="pm-label">性格</text>
                        <text class="pm-val">{{ currentPetInfo.petPersonality || '无' }}</text>
                    </view>
                    <view class="pm-grid-item full">
                        <text class="pm-label">爱好</text>
                        <text class="pm-val">{{ currentPetInfo.petHobby || '无' }}</text>
                    </view>
                    <view class="pm-grid-item full">
                        <text class="pm-label">备注</text>
                        <text class="pm-val">{{ currentPetInfo.petRemark || '无特殊过敏史' }}</text>
                    </view>
                </view>
                <!-- Tags -->
                <view class="pm-tags" v-if="currentPetInfo.petTags && currentPetInfo.petTags.length > 0">
                    <view class="pm-tag" v-for="(tag, index) in currentPetInfo.petTags" :key="index">{{ tag }}</view>
                </view>
                <!-- Log Section -->
                <view class="pm-section-title">
                    <view class="orange-bar"></view>
                    <text>备注日志</text>
                </view>
                <view class="pm-log-list">
                    <view class="pm-log-item" v-for="(log, lIndex) in currentPetInfo.petLogs" :key="lIndex">
                        <text class="pm-log-date">{{ log.date }}</text>
                        <text class="pm-log-text">{{ log.content }}</text>
                        <text class="pm-log-recorder">{{ log.recorder === '系统记录' ? '' : '记录人: ' }}{{ log.recorder
                        }}</text>
                    </view>
                </view>
                <view style="height: 30rpx;"></view>
            </scroll-view>
        </view>
    </view>

    <!-- 备注输入弹窗 -->
    <view class="remark-mask" v-if="showRemarkInput" @click="closeRemarkInput">
        <view class="remark-sheet" @click.stop>
            <view class="remark-sheet-header">
                <text class="remark-sheet-title">添加备注</text>
                <view class="close-icon-btn" @click="closeRemarkInput">×</view>
            </view>
            <textarea class="remark-textarea" v-model="remarkText" placeholder="请输入备注内容..." maxlength="500"
                auto-height />
            <view class="remark-submit-btn" @click="submitRemark">提交备注</view>
        </view>
    </view>

    <!-- 选择地图导航弹窗 (复用Home) -->
    <view class="nav-modal-mask" v-if="showNavModal" @click="closeNavModal">
        <view class="nav-action-sheet" @click.stop>
            <view class="nav-sheet-title">选择地图进行导航</view>
            <view class="nav-sheet-item" @click="chooseMap('高德')">高德地图</view>
            <view class="nav-sheet-item" @click="chooseMap('腾讯')">腾讯地图</view>
            <view class="nav-sheet-item" @click="chooseMap('百度')">百度地图</view>
            <view class="nav-sheet-gap"></view>
            <view class="nav-sheet-item cancel" @click="closeNavModal">取消</view>
        </view>
    </view>
    <!-- 取消订单确认弹窗 -->
    <view class="modal-mask" v-if="showCancelModal">
        <view class="custom-modal">
            <text class="modal-title">取消订单</text>
            <view class="textarea-container">
                <textarea class="reject-textarea" v-model="cancelReason" placeholder="请输入取消原因（必填）"
                    maxlength="100"></textarea>
                <text class="char-count">{{ cancelReason.length }}/100</text>
            </view>
            <view class="modal-btns mt-30">
                <button class="modal-btn cancel" @click="closeCancelModal">再想想</button>
                <button class="modal-btn confirm" :class="{ 'disabled': !cancelReason.trim() }"
                    @click="confirmCancel">确认取消</button>
            </view>
        </view>
    </view>

    <!-- 申诉进度弹窗 -->
    <view class="modal-mask" v-if="showAppealModal" @click="closeAppealModal">
        <view class="custom-modal appeal-modal" @click.stop>
            <view class="appeal-title-bar">
                <text class="modal-title">变更进度</text>
                <view class="appeal-close-btn" @click="closeAppealModal">
                    <text class="close-icon">✕</text>
                </view>
            </view>
            <scroll-view scroll-y class="appeal-scroll">
                <view class="appeal-empty" v-if="appealList.length === 0 && !appealLoading">
                    <text>暂无变更记录</text>
                </view>
                <view class="appeal-timeline" v-else>
                    <view class="appeal-item" v-for="(record, idx) in appealList" :key="idx">
                        <view class="timeline-dot" :class="getAppealStatusClass(record)"></view>
                        <view class="timeline-line" v-if="idx < appealList.length - 1"></view>
                        <view class="appeal-card">
                            <view class="appeal-header">
                                <text class="appeal-service">{{ record.service || '服务变更' }}</text>
                                <text class="appeal-status" :class="getAppealStatusClass(record)">{{
                                    getAppealStatusText(record) }}</text>
                            </view>

                            <view class="appeal-row" v-if="record.fulfillerName">
                                <text class="appeal-label">申请人：</text>
                                <text class="appeal-value">{{ record.fulfillerName }}</text>
                            </view>
                            <view class="appeal-row" v-if="record.serviceSpecification">
                                <text class="appeal-label">变更说明：</text>
                                <text class="appeal-value">{{ record.serviceSpecification }}</text>
                            </view>
                            <view class="appeal-row" v-if="record.reason">
                                <text class="appeal-label">申诉理由：</text>
                                <text class="appeal-value">{{ record.reason }}</text>
                            </view>
                            <view class="appeal-row" v-if="record.rejectReason">
                                <text class="appeal-label">驳回理由：</text>
                                <text class="appeal-value reject-reason">{{ record.rejectReason }}</text>
                            </view>
                            <view class="appeal-row" v-if="record.auditorName">
                                <text class="appeal-label">审核人：</text>
                                <text class="appeal-value">{{ record.auditorName }}</text>
                            </view>
                            <view class="appeal-time-row">
                                <text class="appeal-time">提交：{{ formatTime(record.createTime) }}</text>
                                <text class="appeal-time" v-if="record.auditTime">审核：{{ formatTime(record.auditTime)
                                }}</text>
                            </view>
                        </view>
                    </view>
                </view>
            </scroll-view>
        </view>
    </view>

    <custom-tabbar currentPath="pages/orders/index"></custom-tabbar>
</template>

<script>
import { getMyOrders, cancelOrderApi } from '@/api/order/subOrder'
import { getAppealListByOrderId } from '@/api/order/subOrderAppeal'
import { listAllService } from '@/api/service/list'
import { reportGps } from '@/utils/gps'
import customTabbar from '@/components/custom-tabbar/index.vue'

export default {
    components: {
        customTabbar
    },
    data() {
        return {
            currentTab: 0,
            tabs: ['待接送/服务', '配送/服务中', '已完成', '已取消'],
            typeFilterOptions: ['全部类型'],
            currentTypeFilterIdx: 0,
            activeDropdown: 0,
            hasTimeFilter: false,
            currentMonth: '',
            viewDate: new Date(),
            weekDays: ['日', '一', '二', '三', '四', '五', '六'],
            calendarDays: [],
            selectedDateRange: [],
            allOrderList: [],
            serviceList: [],
            searchContent: '',
            startServiceTime: '',
            endServiceTime: '',
            showPetModal: false,
            currentPetInfo: {},
            showNavModal: false,
            navTargetItem: null,
            navTargetPointType: '',
            activeCallItem: null,
            showRemarkInput: false,
            remarkText: '',
            showCancelModal: false,
            cancelReason: '',
            currentOrder: null,
            showAppealModal: false,
            appealList: [],
            appealLoading: false
        }
    },
    created() {
        this.initCalendar();
    },
    async onLoad() {
        await this.loadServiceList()
        await this.loadOrders()
        // 显式请求一次定位授权
        reportGps(true).catch(e => console.log('Init GPS check skipped', e));
    },
    onShow() {
        uni.hideTabBar()
        // 此处不需要重复调用，因为逻辑可能在onLoad已处理，
        // 或者如果需要每次进入都刷新，可以保留，但需确保顺序
        this.loadOrders()
    },
    async onPullDownRefresh() {
        try {
            await this.loadServiceList()
            await this.loadOrders()
        } finally {
            uni.stopPullDownRefresh()
        }
    },
    watch: {
        currentTab() {
            this.loadOrders()
        },
        currentTypeFilterIdx() {
            this.loadOrders()
        },
        searchContent() {
            // 搜索内容变化时，自动重新加载订单
            this.loadOrders()
        }
    },
    computed: {
        orderList() {
            return this.allOrderList;
        }
    },
    methods: {
        async loadServiceList() {
            try {
                const res = await listAllService()
                this.serviceList = res.data || []
                this.typeFilterOptions = ['全部类型', ...this.serviceList.map(s => s.name)]
            } catch (err) {
                console.error('获取服务类型失败:', err)
                uni.showToast({ title: err.message || err.msg || '获取服务失败', icon: 'none' })
            }
        },
        async loadOrders() {
            try {
                const statusMap = { 0: 2, 1: 3, 2: 4, 3: 5 }
                const serviceId = this.currentTypeFilterIdx > 0 ? this.serviceList[this.currentTypeFilterIdx - 1]?.id : undefined
                const params = {
                    status: statusMap[this.currentTab],
                    content: this.searchContent || undefined,
                    service: serviceId,
                    startServiceTime: this.startServiceTime || undefined,
                    endServiceTime: this.endServiceTime || undefined
                }
                console.log('订单列表请求参数:', params)
                const res = await getMyOrders(params)
                console.log('订单列表响应:', res)
                const orders = res.rows || []
                console.log('订单数量:', orders.length)
                this.allOrderList = orders.map(order => this.transformOrder(order, this.currentTab))
            } catch (err) {
                console.error('获取订单列表失败:', err)
                this.allOrderList = []
                uni.showToast({ title: err.message || err.msg || '加载订单失败', icon: 'none' })
            }
        },
        transformOrder(order, tabIndex) {
            const service = this.serviceList.find(s => s.id === order.service)
            const serviceText = service?.name || '未知'
            const serviceIcon = service?.iconUrl || ''
            const mode = service?.mode || 0
            const isRoundTrip = mode === 1

            // 待服务或服务中统一展示为“到达打卡”
            let statusText = ''
            if (tabIndex === 0 || tabIndex === 1) {
                statusText = '到达打卡'
            } else if (tabIndex === 2) {
                statusText = '已完成'
            } else if (tabIndex === 3) {
                statusText = '已取消'
            }
            return {
                id: order.id,
                status: order.status, // 保存原始 status 用于判断权限
                type: isRoundTrip ? 1 : 2,
                typeText: serviceText,
                typeIcon: serviceIcon,
                statusText: statusText,
                fulfillmentCommission: (order.fulfillmentCommission / 100).toFixed(2),
                timeLabel: '服务时间',
                time: order.serviceTime || '',
                petAvatar: order.petAvatar || '/static/dog.png',
                petAvatarUrl: order.petAvatarUrl || '',
                petName: order.petName || '',
                petBreed: order.breed || '',
                startLocation: order.fromAddress || '暂无起点',
                startAddress: order.fromAddress || '',
                fromAddress: order.fromAddress || '',
                fromLat: order.fromLat,
                fromLng: order.fromLng,
                startDistance: '0km',
                endLocation: (order.customerName || '') + ' ' + (order.customerPhone || ''),
                endAddress: order.toAddress || '',
                toAddress: order.toAddress || '',
                toLat: order.toLat,
                toLng: order.toLng,
                customerPhone: order.customerPhone || '',
                endDistance: '0km',
                serviceContent: order.remark || '',
                remark: order.remark || '',
                serviceFlag: !!order.serviceFlag // 是否允许服务（点击跳转）
            }
        },
        getDisplayStatus(item) {
            if (item.status === 4) return '已完成';
            if (item.status === 5 || item.status === 6) return '已取消';
            if (item.status === 2) return item.type === 1 ? '待接送' : '待服务';
            if (item.status === 3) return item.type === 1 ? '配送中' : '服务中';
            return item.statusText;
        },
        getStatusClass(item) {
            let display = this.getDisplayStatus(item);
            if (display === '已完成') return 'finish';
            if (display === '已取消') return 'reject';
            if (display === '配送中' || display === '服务中') return 'processing';
            return 'highlight';
        },
        goToDetail(item) {
            uni.navigateTo({ url: `/pages/orders/detail/index?id=${item.id}` });
        },
        showPetProfile(item) {
            this.currentPetInfo = {
                ...item,
                petGender: 'M',
                petAge: '2岁',
                petWeight: '15kg',
                petPersonality: '活泼亲人，精力旺盛',
                petHobby: '喜欢追飞盘，爱吃肉干',
                petRemark: '肠胃较弱，不能乱喂零食；出门易爆冲，请拉紧牵引绳。',
                petTags: ['拉响警报', '不能吃鸡肉', '精力旺盛'],
                petLogs: [
                    { date: '2026-02-09 14:00', content: '今天遛弯拉了两次粑粑，精神状态很好。', recorder: '王阿姨' },
                    { date: '2026-02-08 10:30', content: '有些挑食，剩了小半碗狗粮。', recorder: '李师傅' },
                    { date: '2026-02-05 09:00', content: '建档。', recorder: '系统记录' }
                ]
            };
            this.showPetModal = true;
        },
        closePetProfile() {
            this.showPetModal = false;
        },
        openNavigation(item, pointType) {
            if (!item.serviceFlag) {
                uni.showToast({ title: '该订单暂未开通服务，无法操作', icon: 'none' });
                return;
            }
            this.navTargetItem = item;
            this.navTargetPointType = pointType;
            this.showNavModal = true;
        },
        closeNavModal() {
            this.showNavModal = false;
        },
        chooseMap(mapType) {
            let item = this.navTargetItem;
            let pointType = this.navTargetPointType;
            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 openApp = (lat, lng, addrName, addrDesc) => {
                let url = '';
                // #ifdef APP-PLUS
                if (mapType === '高德') {
                    url = `androidamap://viewMap?sourceApplication=yingpaipay&poiname=${encodeURIComponent(addrName)}&lat=${lat}&lon=${lng}&dev=0`;
                } else if (mapType === '腾讯') {
                    url = `qqmap://map/marker?marker=coord:${lat},${lng};title:${encodeURIComponent(addrName)};addr:${encodeURIComponent(addrDesc)}&referer=yingpaipay`;
                } else if (mapType === '百度') {
                    url = `baidumap://map/marker?location=${lat},${lng}&title=${encodeURIComponent(addrName)}&content=${encodeURIComponent(addrDesc)}&src=yingpaipay`;
                }
                plus.runtime.openURL(url, (e) => {
                    console.error('打开' + mapType + '地图失败:', e);
                });
                // #endif
                // #ifdef H5
                if (mapType === '高德') {
                    url = `https://uri.amap.com/marker?position=${lng},${lat}&name=${encodeURIComponent(addrName)}`;
                } else if (mapType === '腾讯') {
                    url = `https://apis.map.qq.com/uri/v1/marker?marker=coord:${lat},${lng};title:${encodeURIComponent(addrName)}&referer=yingpaipay`;
                } else if (mapType === '百度') {
                    url = `https://api.map.baidu.com/marker?location=${lat},${lng}&title=${encodeURIComponent(addrName)}&content=${encodeURIComponent(addrDesc)}&output=html&src=yingpaipay`;
                }
                window.open(url, '_blank');
                // #endif
            };

            if (latitude && longitude && !isNaN(latitude) && !isNaN(longitude)) {
                openApp(latitude, longitude, name, address);
            } else {
                uni.showLoading({ title: '获取当前位置...', mask: true });
                reportGps(true).then(res => {
                    uni.hideLoading();
                    openApp(res.latitude, res.longitude, name, address);
                }).catch(err => {
                    uni.hideLoading();
                    console.error('获取地理位置失败:', err);
                });
            }
        },
        toggleCallMenu(item) {
            if (this.activeCallItem === item) {
                this.activeCallItem = null;
            } else {
                this.activeCallItem = item;
            }
        },
        closeCallMenu() {
            this.activeCallItem = null;
        },
        doCall(type, item) {
            if (!item.serviceFlag) {
                uni.showToast({ title: '该订单暂未开通服务，无法操作', icon: 'none' });
                return;
            }
            let phoneNum = '';
            const targetItem = item || this.activeCallItem;

            // 1. 获取电话号码
            if (type === 'merchant') {
                phoneNum = '18900008451';
            } else if (type === 'customer') {
                phoneNum = targetItem?.customerPhone;
            }

            // 2. 基础校验
            if (!phoneNum) {
                uni.showToast({ title: '未找到电话号码', icon: 'none' });
                this.activeCallItem = null;
                return;
            }

            // 3. 清洗号码 (去除空格、横杠等非数字字符)
            phoneNum = phoneNum.replace(/[^\d]/g, '');

            // 二次校验：确保清洗后仍有数字
            if (phoneNum.length < 3) {
                uni.showToast({ title: '电话号码格式错误', icon: 'none' });
                this.activeCallItem = null;
                return;
            }

            console.log('正在发起直接呼叫:', phoneNum);

            // 4. 核心逻辑：区分环境处理
            // #ifdef APP-PLUS
            // App 端：使用 uni.makePhoneCall 直接发起呼叫
            uni.makePhoneCall({
                phoneNumber: phoneNum,
                success: () => {
                    console.log('成功唤起系统拨号盘');
                },
                fail: (err) => {
                    console.error('拨号失败:', err);
                    // 常见错误：Permission denied (权限被拒) 或 Activity not found
                    let msg = '拨号失败';
                    if (err.message && err.message.includes('permission')) {
                        msg = '请在手机设置中允许"电话"权限';
                    }
                    uni.showToast({ title: msg, icon: 'none', duration: 3000 });

                    // 如果失败，尝试引导用户去设置页 (仅限 Android)
                    // #ifdef APP-ANDROID
                    if (err.message && err.message.includes('permission')) {
                        uni.showModal({
                            title: '权限提示',
                            content: '拨打电话需要电话权限，是否前往设置开启？',
                            success: (res) => {
                                if (res.confirm) {
                                    plus.runtime.openURL("app-settings:");
                                }
                            }
                        });
                    }
                    // #endif
                },
                complete: () => {
                    this.activeCallItem = null; // 关闭弹窗
                }
            });
            // #endif

            // #ifdef H5
            // H5 端：使用 tel: 协议
            window.location.href = `tel:${phoneNum}`;
            this.activeCallItem = null;
            // #endif

            // #ifdef MP-WEIXIN
            // 小程序端：直接调用 makePhoneCall (微信小程序支持直接弹框确认拨打)
            uni.makePhoneCall({
                phoneNumber: phoneNum,
                fail: () => {
                    uni.showToast({ title: '拨号失败', icon: 'none' });
                },
                complete: () => {
                    this.activeCallItem = null;
                }
            });
            // #endif
        },
        reportAbnormal(item) {
            if (!item.serviceFlag) {
                uni.showToast({ title: '该订单暂未开通服务，无法操作', icon: 'none' });
                return;
            }
            uni.navigateTo({ url: '/pages/orders/anomaly/index?orderId=' + (item.id || '') });
        },
        mainAction(item) {
            if (!item.serviceFlag) {
                uni.showToast({ title: '该订单暂未开通服务，无法操作', icon: 'none' });
                return;
            }
            uni.navigateTo({ url: `/pages/orders/detail/index?id=${item.id}` });
        },
        addOrUpdateService(item) {
            // 跳转到申诉（增改服务项）页面
            uni.navigateTo({ url: `/pages/orders/appeal/index?id=${item.id}` });
        },
        toggleDropdown(idx) {
            if (this.activeDropdown === idx) {
                this.activeDropdown = 0;
            } else {
                this.activeDropdown = idx;
            }
        },
        closeDropdown() {
            this.activeDropdown = 0;
        },
        selectType(index) {
            this.currentTypeFilterIdx = index;
            this.closeDropdown();
        },
        initCalendar() {
            const year = this.viewDate.getFullYear();
            const month = this.viewDate.getMonth();
            this.currentMonth = `${year}年${month + 1}月`;

            // 获取该月第一天是周几 (0-6)
            const firstDay = new Date(year, month, 1).getDay();
            // 获取该月有多少天
            const daysInMonth = new Date(year, month + 1, 0).getDate();

            let days = [];
            // 填充开头的空白
            for (let i = 0; i < firstDay; i++) {
                days.push(0);
            }
            // 填充真实日期
            for (let i = 1; i <= daysInMonth; i++) {
                days.push(i);
            }
            this.calendarDays = days;
        },
        prevMonth() {
            this.viewDate.setMonth(this.viewDate.getMonth() - 1);
            // 切换月份时强制重新创建 Date 对象以触发 Vue 响应式（如果需要）或者简单调用 init
            this.viewDate = new Date(this.viewDate);
            this.initCalendar();
        },
        nextMonth() {
            this.viewDate.setMonth(this.viewDate.getMonth() + 1);
            this.viewDate = new Date(this.viewDate);
            this.initCalendar();
        },
        selectDateItem(day) {
            if (this.selectedDateRange.length === 2) {
                this.selectedDateRange = [day];
            } else if (this.selectedDateRange.length === 1) {
                let start = this.selectedDateRange[0];
                if (day > start) {
                    this.selectedDateRange = [start, day];
                } else if (day < start) {
                    this.selectedDateRange = [day, start];
                } else {
                    this.selectedDateRange = [];
                }
            } else {
                this.selectedDateRange = [day];
            }
        },
        getDateClass(day) {
            if (!day || this.selectedDateRange.length === 0) return '';
            if (this.selectedDateRange.length === 1) {
                return day === this.selectedDateRange[0] ? 'is-start' : '';
            }
            let start = this.selectedDateRange[0];
            let end = this.selectedDateRange[1];
            if (day === start) return 'is-start';
            if (day === end) return 'is-end';
            if (day > start && day < end) return 'is-between';
            return '';
        },
        resetTimeFilter() {
            this.hasTimeFilter = false;
            this.selectedDateRange = [];
            this.startServiceTime = '';
            this.endServiceTime = '';
            this.closeDropdown();
            this.loadOrders();
        },
        confirmTimeFilter() {
            if (this.selectedDateRange.length === 0) {
                uni.showToast({ title: '请先选择日期', icon: 'none' });
                return;
            }
            // 构建时间范围参数
            const year = this.currentMonth.replace(/[^0-9]/g, '').substring(0, 4);
            const month = this.currentMonth.replace(/[^0-9]/g, '').substring(4);
            const pad = (n) => String(n).padStart(2, '0');
            if (this.selectedDateRange.length === 2) {
                this.startServiceTime = `${year}-${pad(month)}-${pad(this.selectedDateRange[0])} 00:00:00`;
                this.endServiceTime = `${year}-${pad(month)}-${pad(this.selectedDateRange[1])} 23:59:59`;
            } else {
                this.startServiceTime = `${year}-${pad(month)}-${pad(this.selectedDateRange[0])} 00:00:00`;
                this.endServiceTime = `${year}-${pad(month)}-${pad(this.selectedDateRange[0])} 23:59:59`;
            }
            this.hasTimeFilter = true;
            this.closeDropdown();
            this.loadOrders();
        },
        getMainActionText(item) {
            return '查看详情';
        },
        mainAction(item) {
            uni.navigateTo({ url: `/pages/orders/detail/index?id=${item.id}` });
        },
        addOrUpdateService(item) {
            // 跳转到申诉（增改服务项）页面
            uni.navigateTo({ url: `/pages/orders/appeal/index?id=${item.id}` });
        },
        openRemarkInput() {
            this.remarkText = '';
            this.showRemarkInput = true;
        },
        closeRemarkInput() {
            this.showRemarkInput = false;
            this.remarkText = '';
        },
        submitRemark() {
            const text = this.remarkText.trim();
            if (!text) {
                uni.showToast({ title: '备注内容不能为空', icon: 'none' });
                return;
            }
            const now = new Date();
            const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
            if (!this.currentPetInfo.petLogs) {
                this.$set(this.currentPetInfo, 'petLogs', []);
            }
            this.currentPetInfo.petLogs.unshift({
                date: dateStr,
                content: text,
                recorder: '我'
            });
            uni.showToast({ title: '备注已添加', icon: 'success' });
            this.closeRemarkInput();
        },
        /**
         * 取消订单处理逻辑 - 打开弹窗
         * @param {Object} item - 订单项
         */
        handleCancelOrder(item) {
            if (!item.serviceFlag) {
                uni.showToast({ title: '该订单暂未开通服务，无法操作', icon: 'none' });
                return;
            }
            this.currentOrder = item;
            this.cancelReason = '';
            this.showCancelModal = true;
        },
        closeCancelModal() {
            this.showCancelModal = false;
            this.currentOrder = null;
        },
        async confirmCancel() {
            if (!this.cancelReason.trim()) {
                uni.showToast({ title: '请输入取消原因', icon: 'none' });
                return;
            }
            try {
                uni.showLoading({ title: '取消中...', mask: true });
                await cancelOrderApi({
                    orderId: this.currentOrder.id,
                    reason: this.cancelReason
                });
                uni.showToast({ title: '已取消接单', icon: 'success' });
                this.showCancelModal = false;
                this.currentOrder = null;
                // 延时刷新列表，防止提示框闪现
                setTimeout(() => {
                    this.loadOrders();
                }, 1000);
            } catch (err) {
                console.error('取消订单失败:', err);
                uni.showToast({ title: err.message || err.msg || '取消失败', icon: 'none' });
            } finally {
                uni.hideLoading();
            }
        },
        async viewAppealProgress(item) {
            this.appealList = [];
            this.appealLoading = true;
            this.showAppealModal = true;
            try {
                const res = await getAppealListByOrderId(item.id);
                this.appealList = res.data || [];
            } catch (err) {
                console.error('获取申诉记录失败:', err);
                uni.showToast({ title: '获取申诉进度失败', icon: 'none' });
            } finally {
                this.appealLoading = false;
            }
        },
        closeAppealModal() {
            this.showAppealModal = false;
            this.appealList = [];
        },
        getAppealStatusText(record) {
            // auditStatus: 0=待审核, 1=通过, 2=驳回
            if (record.auditStatus === 0 || record.auditStatus === null || record.auditStatus === undefined) return '待审核';
            if (record.auditStatus === 1) return '已通过';
            if (record.auditStatus === 2) return '已驳回';
            return '未知';
        },
        getAppealStatusClass(record) {
            if (record.auditStatus === 0 || record.auditStatus === null || record.auditStatus === undefined) return 'pending';
            if (record.auditStatus === 1) return 'approved';
            if (record.auditStatus === 2) return 'rejected';
            return '';
        },
        formatTime(timeStr) {
            if (!timeStr) return '';
            // 后端返回格式: 2026-04-23T15:40:00 或 2026-04-23 15:40:00
            return timeStr.replace('T', ' ').substring(0, 16);
        }
    }
}
</script>

<style>
page {
    background-color: #F8F8F8;
}

.custom-nav-bar {
    padding: 80rpx 30rpx 20rpx;
    background-color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
}

.nav-title {
    font-size: 34rpx;
    font-weight: bold;
    color: #333;
}

.sticky-header {
    position: sticky;
    top: 0;
    z-index: 999;
    background-color: #F8F8F8;
}

.container {
    background-color: #F8F8F8;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.status-tabs {
    display: flex;
    background-color: #fff;
    padding: 0 30rpx;
    justify-content: space-between;
}

.tab-item {
    position: relative;
    padding: 20rpx 0;
    font-size: 26rpx;
    color: #666;
    font-weight: 500;
}

.tab-item.active {
    color: #FF5722;
    font-weight: bold;
}

.indicator {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 40rpx;
    height: 6rpx;
    background-color: #FF5722;
    border-radius: 3rpx;
}

.search-bar {
    padding: 10rpx 30rpx;
    background-color: #fff;
}

.search-input-box {
    display: flex;
    align-items: center;
    background-color: #F8F8F8;
    height: 64rpx;
    border-radius: 32rpx;
    padding: 0 30rpx;
}

.search-input {
    flex: 1;
    font-size: 26rpx;
    color: #333;
    padding-left: 20rpx;
}

.ph-style {
    font-size: 26rpx;
    color: #999;
}

.filter-wrapper {
    position: relative;
    z-index: 998;
}

.filter-bar {
    display: flex;
    background-color: #fff;
    padding: 5rpx 30rpx 10rpx 30rpx;
    justify-content: space-between;
    position: relative;
    z-index: 998;
}

.filter-item {
    width: 48%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26rpx;
    color: #666;
    background-color: #F8F8F8;
    height: 56rpx;
    border-radius: 12rpx;
    transition: all 0.2s;
}

.filter-item.active {
    background-color: #FFF3E0;
}

.active-text {
    color: #FF5722;
    font-weight: 500;
}

.triangle {
    width: 0;
    height: 0;
    border-left: 8rpx solid transparent;
    border-right: 8rpx solid transparent;
    margin-left: 10rpx;
    transition: all 0.2s;
}

.triangle.down {
    border-top: 10rpx solid #dcdcdc;
}

.filter-item.active .triangle.down,
.active-text+.triangle.down {
    border-top-color: #FF5722;
}

.triangle.up {
    border-bottom: 10rpx solid #FF5722;
}

.dropdown-mask {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.4);
    z-index: 80;
}

.dropdown-panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background-color: #fff;
    z-index: 90;
    border-radius: 0 0 20rpx 20rpx;
    box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.05);
    overflow: hidden;
}

.type-option {
    padding: 30rpx 40rpx;
    font-size: 28rpx;
    color: #333;
    border-bottom: 1px solid #f5f5f5;
}

.type-option:last-child {
    border-bottom: none;
}

.type-option.selected text {
    color: #FF5722;
    font-weight: bold;
}

.calendar-panel {
    padding-bottom: 30rpx;
}

.custom-calendar-container {
    padding: 20rpx 30rpx 0;
}

.cal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20rpx 0;
}

.cal-title {
    font-size: 32rpx;
    font-weight: bold;
    color: #333;
}

.cal-weekdays {
    display: flex;
    justify-content: space-around;
    padding: 20rpx 0;
    border-bottom: 1px solid #f5f5f5;
}

.wk-item {
    font-size: 24rpx;
    color: #999;
    width: 14.28%;
    text-align: center;
}

.cal-body {
    display: flex;
    flex-wrap: wrap;
    padding-top: 20rpx;
}

.cal-day-box {
    width: 14.28%;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 10rpx;
    position: relative;
}

.cal-day-text {
    width: 64rpx;
    height: 64rpx;
    line-height: 64rpx;
    text-align: center;
    font-size: 28rpx;
    color: #333;
    border-radius: 8rpx;
    position: relative;
    z-index: 2;
}

.cal-day-box.is-start .cal-day-text,
.cal-day-box.is-end .cal-day-text {
    background-color: #FF5722;
    color: #fff;
    font-weight: bold;
}

.cal-day-box.is-start::after {
    content: '';
    position: absolute;
    right: 0;
    top: 8rpx;
    bottom: 8rpx;
    width: 50%;
    background-color: #FFF3E0;
    z-index: 1;
}

.cal-day-box.is-end::after {
    content: '';
    position: absolute;
    left: 0;
    top: 8rpx;
    bottom: 8rpx;
    width: 50%;
    background-color: #FFF3E0;
    z-index: 1;
}

.cal-day-box.is-start.is-end::after {
    display: none;
}

.cal-day-box.is-between {
    background-color: #FFF3E0;
    margin-top: 8rpx;
    height: 64rpx;
    margin-bottom: 18rpx;
}

.cal-day-box.is-between .cal-day-text {
    color: #FF5722;
}

.calendar-actions {
    display: flex;
    justify-content: space-between;
    padding: 0 30rpx;
    margin-top: 20rpx;
}

.cal-btn {
    width: 48%;
    height: 70rpx;
    line-height: 70rpx;
    text-align: center;
    border-radius: 10rpx;
    font-size: 28rpx;
    margin: 0;
}

.cal-btn.reset {
    background-color: #f5f5f5;
    color: #666;
}

.cal-btn.confirm {
    background-color: #FF5722;
    color: #fff;
}

.order-list {
    padding: 0 30rpx;
    width: 100%;
    box-sizing: border-box;
}

.order-card {
    background-color: #fff;
    border-radius: 24rpx;
    padding: 20rpx 20rpx;
    margin-bottom: 20rpx;
    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
}

.order-card:first-child {
    margin-top: 20rpx;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15rpx;
}

.type-badge {
    display: flex;
    align-items: center;
}

.type-icon {
    width: 44rpx;
    height: 44rpx;
    margin-right: 15rpx;
    background-color: #FFF3E0;
    border-radius: 50%;
    padding: 6rpx;
    box-sizing: border-box;
}

.type-text {
    font-size: 30rpx;
    font-weight: bold;
    color: #333;
}

.status-badge {
    font-size: 28rpx;
}

.status-badge.highlight {
    color: #FF5722;
}

.status-badge.processing {
    color: #2196F3;
}

.status-badge.finish {
    color: #4CAF50;
}

.status-badge.reject {
    color: #9E9E9E;
}

.time-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 25rpx;
}

.time-row .time-col {
    display: flex;
    align-items: center;
    font-size: 26rpx;
    color: #333;
}

.time-row .label {
    color: #666;
    margin-right: 10rpx;
}

.fulfillmentCommission {
    font-size: 36rpx;
    font-weight: bold;
    color: #FF5722;
}

.pet-card {
    background-color: #FFF8F0;
    border-radius: 16rpx;
    padding: 15rpx 20rpx;
    display: flex;
    align-items: center;
    margin-bottom: 20rpx;
}

.pet-avatar {
    width: 80rpx;
    height: 80rpx;
    border-radius: 50%;
    margin-right: 20rpx;
}

.pet-info {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.pet-name {
    font-size: 28rpx;
    font-weight: bold;
    color: #333;
    margin-bottom: 5rpx;
}

.pet-breed {
    font-size: 24rpx;
    color: #999;
}

.pet-profile-btn {
    font-size: 24rpx;
    color: #FF9800;
    border: 1px solid #FF9800;
    padding: 6rpx 20rpx;
    border-radius: 50rpx;
    background-color: #fff;
}

.route-info {
    margin-bottom: 25rpx;
}

.route-item {
    display: flex;
    align-items: flex-start;
    padding-bottom: 12rpx;
    position: relative;
    width: 100%;
}

.route-item:not(:last-child) {
    margin-bottom: 5rpx;
}

.route-item:last-child {
    padding-bottom: 0;
    margin-bottom: 0;
}

.route-line-vertical {
    position: absolute;
    left: 19rpx;
    top: 46rpx;
    bottom: -15rpx;
    border-left: 2rpx dashed #E0E0E0;
    width: 0;
    z-index: 0;
}

.icon-circle {
    width: 40rpx;
    height: 40rpx;
    border-radius: 50%;
    color: #fff;
    font-size: 22rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 20rpx;
    flex-shrink: 0;
    font-weight: bold;
    margin-top: 6rpx;
    position: relative;
    z-index: 1;
}

.icon-circle.service {
    background-color: #81C784;
}

.icon-circle.start {
    background-color: #FFB74D;
}

.icon-circle.end {
    background-color: #81C784;
}

.address-box {
    flex: 1;
    display: flex;
    flex-direction: column;
    margin-right: 20rpx;
}

.addr-title {
    font-size: 28rpx;
    font-weight: bold;
    color: #333;
    margin-bottom: 4rpx;
}

.addr-desc {
    font-size: 24rpx;
    color: #999;
    line-height: 1.4;
}

.distance-tag {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;
    min-width: 80rpx;
}

.distance-text {
    font-size: 24rpx;
    color: #FF5722;
    margin-right: 15rpx;
    font-weight: 500;
}

.nav-icon-circle {
    width: 48rpx;
    height: 48rpx;
    background-color: #FFF3E0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.nav-arrow {
    width: 24rpx;
    height: 24rpx;
}

.service-content {
    margin-top: -10rpx;
    font-size: 24rpx;
    color: #666;
    padding-left: 60rpx;
}

.content-label {
    color: #999;
    margin-right: 10rpx;
}

.remark-box {
    background-color: #F8F8F8;
    padding: 15rpx 20rpx;
    border-radius: 8rpx;
    font-size: 24rpx;
    color: #666;
    margin-bottom: 20rpx;
}

.action-btns {
    display: flex;
    flex-direction: column;
    gap: 16rpx;
    margin-top: 20rpx;
}

.action-row {
    display: flex;
    gap: 16rpx;
    align-items: center;
    width: 100%;
}

.btn {
    flex: 1;
    height: 64rpx;
    line-height: 64rpx;
    border-radius: 32rpx;
    font-size: 24rpx;
    padding: 0;
    margin: 0;
    text-align: center;
    min-width: 0;
}

.action-right .btn:not(:last-child) {
    margin-right: 20rpx;
}

.btn::after {
    border: none;
}

.btn.normal {
    background-color: #F8F8F8;
    color: #666;
    border: none;
}

.btn.primary {
    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
    color: #fff;
    box-shadow: 0 4rpx 12rpx rgba(255, 87, 34, 0.2);
    border: none;
}

.btn.normal.danger {
    background-color: #FFF2F0;
    color: #F5222D;
}

.pet-modal-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.4);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pet-modal-content {
    width: 680rpx;
    height: 85vh;
    background-color: #fff;
    border-radius: 20rpx;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.pet-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 30rpx;
    border-bottom: 1rpx solid #F0F0F0;
}

.pet-modal-title {
    font-size: 34rpx;
    font-weight: bold;
    color: #333;
}

.pet-modal-scroll {
    flex: 1;
    height: 0;
    padding: 30rpx;
    box-sizing: border-box;
}

.pet-base-info {
    display: flex;
    align-items: center;
    margin-bottom: 40rpx;
}

.pm-avatar {
    width: 120rpx;
    height: 120rpx;
    border-radius: 50%;
    margin-right: 30rpx;
    border: 2rpx solid #f5f5f5;
}

.pm-info-text {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.pm-name-row {
    display: flex;
    align-items: center;
    margin-bottom: 15rpx;
}

.pm-name {
    font-size: 36rpx;
    font-weight: bold;
    color: #333;
    margin-right: 20rpx;
}

.pm-gender {
    display: flex;
    align-items: center;
    background-color: #E3F2FD;
    padding: 4rpx 12rpx;
    border-radius: 20rpx;
}

.pm-gender text {
    font-size: 22rpx;
    color: #1E88E5;
}

.pm-gender .gender-icon {
    font-weight: bold;
    margin-right: 4rpx;
}

.pm-gender.female {
    background-color: #FCE4EC;
}

.pm-gender.female text {
    color: #D81B60;
}

.pm-breed {
    font-size: 26rpx;
    color: #999;
}

.pm-detail-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

.pm-grid-item {
    background-color: #F8F8F8;
    border-radius: 16rpx;
    padding: 24rpx;
    margin-bottom: 20rpx;
    display: flex;
    flex-direction: column;
}

.pm-grid-item.half {
    width: 48%;
    box-sizing: border-box;
}

.pm-grid-item.full {
    width: 100%;
    box-sizing: border-box;
}

.pm-label {
    font-size: 24rpx;
    color: #999;
    margin-bottom: 10rpx;
}

.pm-val {
    font-size: 28rpx;
    color: #333;
    font-weight: 500;
}

.pm-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 20rpx;
    margin-bottom: 40rpx;
}

.pm-tag {
    background-color: #FFF8EB;
    border: 2rpx solid #FFCC80;
    color: #FF9800;
    font-size: 22rpx;
    padding: 8rpx 24rpx;
    border-radius: 30rpx;
}

.pm-section-title {
    display: flex;
    align-items: center;
    margin-bottom: 30rpx;
    padding-top: 30rpx;
    border-top: 2rpx dashed #F0F0F0;
}

.pm-section-title .orange-bar {
    width: 8rpx;
    height: 32rpx;
    background-color: #FF9800;
    margin-right: 16rpx;
    border-radius: 4rpx;
}

.pm-section-title text {
    font-size: 30rpx;
    font-weight: bold;
    color: #333;
}

.pm-log-list {
    display: flex;
    flex-direction: column;
}

.pm-log-item {
    display: flex;
    flex-direction: column;
    padding: 24rpx 0;
    border-bottom: 1rpx solid #F0F0F0;
}

.pm-log-item:last-child {
    border-bottom: none;
}

.pm-log-date {
    font-size: 24rpx;
    color: #999;
    margin-bottom: 16rpx;
}

.pm-log-text {
    font-size: 28rpx;
    color: #333;
    line-height: 1.6;
    margin-bottom: 20rpx;
}

.pm-log-recorder {
    font-size: 24rpx;
    color: #FF9800;
    align-self: flex-end;
}

.pm-bottom-close {
    width: 100%;
    height: 80rpx;
    line-height: 80rpx;
    background-color: #F5F5F5;
    color: #666;
    border-radius: 40rpx;
    font-size: 30rpx;
    font-weight: bold;
    margin: 0;
}

.pm-bottom-close::after {
    border: none;
}

.close-icon-btn {
    font-size: 48rpx;
    color: #999;
    line-height: 1;
    padding: 0 10rpx;
}

.nav-modal-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 1000;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

.nav-action-sheet {
    background-color: #fff;
    width: 100%;
    border-top-left-radius: 24rpx;
    border-top-right-radius: 24rpx;
    overflow: hidden;
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}

.nav-sheet-title {
    text-align: center;
    padding: 30rpx 0;
    font-size: 13px;
    color: #999;
    border-bottom: 1rpx solid #efefef;
}

.nav-sheet-item {
    text-align: center;
    padding: 30rpx 0;
    font-size: 13px;
    color: #333;
    background-color: #fff;
    border-bottom: 1rpx solid #efefef;
}

.nav-sheet-item.cancel {
    border-bottom: none;
    color: #666;
}

.nav-sheet-gap {
    height: 16rpx;
    background-color: #F8F8F8;
}

.order-list {
    flex: 1;
    overflow-y: auto;
    width: 100%;
    padding: 0 30rpx;
    box-sizing: border-box;
}

.loading-text {
    text-align: center;
    font-size: 24rpx;
    color: #999;
    padding: 30rpx 0;
}

.pm-header-actions {
    display: flex;
    align-items: center;
    gap: 16rpx;
}

.pm-remark-btn {
    font-size: 24rpx;
    color: #fff;
    background-color: #FF9800;
    padding: 6rpx 18rpx;
    border-radius: 20rpx;
}

.remark-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 3000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.remark-sheet {
    width: 600rpx;
    background-color: #fff;
    border-radius: 24rpx;
    padding: 40rpx;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.remark-sheet-header {
    width: 100%;
    text-align: center;
    margin-bottom: 30rpx;
    position: relative;
}

.remark-sheet-header .close-icon-btn {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
}

.remark-sheet-title {
    font-size: 32rpx;
    font-weight: bold;
    color: #333;
}

.remark-textarea {
    width: 100%;
    height: 160rpx;
    border: 1rpx solid #eee;
    border-radius: 12rpx;
    padding: 20rpx;
    font-size: 28rpx;
    color: #333;
    box-sizing: border-box;
    margin-bottom: 40rpx;
}

.remark-submit-btn {
    width: 100%;
    background-color: #FF5722;
    color: #fff;
    font-size: 32rpx;
    font-weight: bold;
    text-align: center;
    padding: 24rpx 0;
    border-radius: 16rpx;
}

.action-left {
    position: relative;
    z-index: 10;
}

.action-left .btn.normal {
    font-size: 26rpx;
}

.call-popover {
    position: absolute;
    top: calc(100% + 10rpx);
    left: 0;
    background-color: #fff;
    border-radius: 12rpx;
    box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
    z-index: 999;
    display: flex;
    flex-direction: column;
    width: 200rpx;
}

.call-pop-item {
    font-size: 26rpx;
    color: #333;
    text-align: center;
    padding: 24rpx 0;
    border-bottom: 1rpx solid #eee;
}

.call-pop-item:last-child {
    border-bottom: none;
}

.call-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 900;
    background: transparent;
}

/* 全局通用对话框样式 (复用首页思路) */
.modal-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 5000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.custom-modal {
    width: 600rpx;
    background-color: #fff;
    border-radius: 24rpx;
    padding: 40rpx 50rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.modal-title {
    font-size: 36rpx;
    font-weight: bold;
    color: #333;
    margin-bottom: 30rpx;
}

.modal-btns {
    width: 100%;
    display: flex;
    justify-content: space-between;
}

.modal-btn {
    width: 45%;
    height: 80rpx;
    line-height: 80rpx;
    border-radius: 40rpx;
    font-size: 30rpx;
    font-weight: bold;
    margin: 0;
}

.modal-btn::after {
    border: none;
}

.modal-btn.cancel {
    background-color: #F5F5F5;
    color: #999;
}

.modal-btn.confirm {
    background: linear-gradient(90deg, #FF9800 0%, #FF5722 100%);
    color: #fff;
    box-shadow: 0 5rpx 15rpx rgba(255, 87, 34, 0.3);
}

.textarea-container {
    padding: 0 4rpx;
    width: 100%;
    position: relative;
    margin-bottom: 20rpx;
}

.reject-textarea {
    width: 100%;
    height: 240rpx;
    background-color: #F9F9F9;
    border: 1rpx solid #E0E0E0;
    border-radius: 16rpx;
    padding: 24rpx;
    padding-bottom: 60rpx;
    font-size: 28rpx;
    line-height: 1.6;
    box-sizing: border-box;
    transition: all 0.3s;
}

.reject-textarea:focus {
    border-color: #FF9800;
    background-color: #fff;
}

.char-count {
    position: absolute;
    right: 44rpx;
    bottom: 24rpx;
    font-size: 22rpx;
    color: #999;
}

.modal-btn.confirm.disabled {
    background: #FFD180;
    box-shadow: none;
    opacity: 0.8;
}

.mt-30 {
    margin-top: 30rpx;
}

.disabled-card .card-header,
.disabled-card .card-body {
    opacity: 0.6;
    filter: grayscale(80%);
}

.service-disabled-tip {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20rpx 0;
    background-color: #FFF8E1;
    border-radius: 12rpx;
    border: 2rpx dashed #FFCC00;
}

.service-disabled-tip text {
    font-size: 24rpx;
    color: #F57C00;
}

.appeal-progress-btn {
    width: 100% !important;
}

/* 申诉进度弹窗 */
.appeal-modal {
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    position: relative;
}

.appeal-title-bar {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    margin-bottom: 20rpx;
}

.appeal-title-bar .modal-title {
    margin-bottom: 0;
}

.appeal-close-btn {
    position: absolute;
    right: -10rpx;
    top: 50%;
    transform: translateY(-50%);
    width: 56rpx;
    height: 56rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background-color: #f5f5f5;
}

.appeal-close-btn:active {
    background-color: #e8e8e8;
}

.close-icon {
    font-size: 28rpx;
    color: #999;
    line-height: 1;
}

.appeal-scroll {
    max-height: 60vh;
    padding: 10rpx 0;
}

.appeal-empty {
    padding: 80rpx 0;
    text-align: center;
    color: #999;
    font-size: 26rpx;
}

.appeal-timeline {
    padding: 0 10rpx;
}

.appeal-item {
    position: relative;
    padding-left: 40rpx;
    padding-bottom: 30rpx;
}

.timeline-dot {
    position: absolute;
    left: 4rpx;
    top: 12rpx;
    width: 20rpx;
    height: 20rpx;
    border-radius: 50%;
    background-color: #e6a23c;
    border: 4rpx solid #faecd8;
}

.timeline-dot.approved {
    background-color: #67c23a;
    border-color: #e1f3d8;
}

.timeline-dot.rejected {
    background-color: #f56c6c;
    border-color: #fde2e2;
}

.timeline-line {
    position: absolute;
    left: 13rpx;
    top: 36rpx;
    bottom: 0;
    width: 2rpx;
    background-color: #e4e7ed;
}

.appeal-card {
    background: #f8f8f8;
    border-radius: 16rpx;
    padding: 20rpx 24rpx;
}

.appeal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12rpx;
}

.appeal-service {
    font-size: 28rpx;
    font-weight: bold;
    color: #333;
}

.appeal-status {
    font-size: 22rpx;
    padding: 4rpx 16rpx;
    border-radius: 20rpx;
    font-weight: bold;
}

.appeal-status.pending {
    color: #e6a23c;
    background-color: #faecd8;
}

.appeal-status.approved {
    color: #67c23a;
    background-color: #e1f3d8;
}

.appeal-status.rejected {
    color: #f56c6c;
    background-color: #fde2e2;
}

.appeal-row {
    display: flex;
    margin-bottom: 8rpx;
    font-size: 24rpx;
}

.appeal-label {
    color: #999;
    flex-shrink: 0;
}

.appeal-value {
    color: #333;
    flex: 1;
    word-break: break-all;
}

.appeal-value.reject-reason {
    color: #f56c6c;
}

.appeal-time-row {
    display: flex;
    gap: 24rpx;
    margin-top: 12rpx;
    padding-top: 12rpx;
    border-top: 2rpx solid #eee;
}

.appeal-time {
    font-size: 22rpx;
    color: #bbb;
}
</style>
