zjk
2026-01-04 d34065d6a789724580295e34a6de1dce5f986913
feat: 开票
6个文件已添加
2个文件已修改
755 ■■■■■ 已修改文件
miniprogram/pages.json 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages/invoice/addInvoice.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages/invoice/applyInvoice.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages/invoice/invoice.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages/invoice/invoiceDetail.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages/tourist/tourist.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/static/image/mine/arrowRight.png 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/static/image/mine/modify.png 补丁 | 查看 | 原始文档 | blame | 历史
miniprogram/pages.json
@@ -136,6 +136,31 @@
            "style": {
                "navigationBarTitleText": ""
            }
        },
        {
            "path": "pages/invoice/invoice",
            "style": {
                "navigationBarTitleText": "发票管理"
            }
        },
        {
            "path": "pages/invoice/addInvoice",
            "style": {
                "navigationBarTitleText": "我要开票"
            }
        },
        {
            "path": "pages/invoice/invoiceDetail",
            "style": {
                "navigationBarTitleText": "发票详情",
                "navigationStyle": "custom"
            }
        },
        {
            "path": "pages/invoice/applyInvoice",
            "style": {
                "navigationBarTitleText": "申请开票"
            }
        }
    ],
    "subPackages": [{
miniprogram/pages/invoice/addInvoice.vue
New file
@@ -0,0 +1,182 @@
<template>
    <view class="container">
        <view class="px-27">
            <view class="list-item" v-for="(item, index) in invoiceList" :key="index"  @click="toDetail(item)">
                <view class="flex a-center j-between">
                    <view class="time">{{ item.time || '' }}</view>
                    <view class="status flex a-center j-center">开票中</view>
                </view>
                <view class="flex a-center j-between">
                    <view class="name">{{ item.name || '' }}</view>
                    <view class="price"><text>¥ </text>{{ item.price || '' }}</view>
                </view>
            </view>
        </view>
    </view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onLoad, onUnload, onShow, onReachBottom } from "@dcloudio/uni-app";
const invoiceList = ref([
    {
        time: '2023-08-01 10:00:00',
        name: '成人票',
        price: '100.00',
        img: '/static/image/mine/contact.png'
    }
]);
const finished = ref(false);
const loading = ref(false);
const searchParams = ref({
    pageNum: 1,
    pageSize: 10
})
const toAdd = () => {
    uni.navigateTo({
        url: '/pages/invoice/addInvoice',
    })
}
const toDetail = (item) => {
    uni.navigateTo({
        url: '/pages/invoice/invoiceDetail?id=' + item.id,
    })
}
const fetchList = () => {
    //         // if (loading.value || finished.value) return
    //         loading.value = true
    //         getMonitorList({
    //             nameOrCode: keyword.value || '',
    //             pageNum: searchParams.value.pageNum,
    //             pageSize: searchParams.value.pageSize
    //         }).then(res => {
    //             // PC 端类型定义:{ records, total, current, size }
    //             const data = res.data || res || {}
    //             const records = data.records || []
    //             const total = data.total || 0
    //             if (searchParams.value.pageNum === 1) {
    //                 list.value = records
    //             } else {
    //                 list.value = list.value.concat(records)
    //             }
    //             // 判断是否已全部加载
    //             if (!records.length || list.value.length >= total) {
    //                 finished.value = true
    //             } else {
    //                 searchParams.value.pageNum += 1
    //             }
    //         }).catch(() => {
    //             uni.showToast({
    //                 title: '获取巡检列表失败',
    //                 icon: 'none'
    //             })
    //         }).finally(() => {
    //             loading.value = false
    //         })
}
onReachBottom(() => {
})
</script>
<style>
    page{
        background-color: #FFFFFF;
    }
</style>
<style scoped lang="scss">
.container {
    width: 100%;
    height: 100%;
    position: relative;
    .footer {
        width: 100%;
        height: 96rpx;
        background: #FFFFFF;
        box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(0, 0, 0, 0.05);
        position: sticky;
        bottom: 0;
        left: 0;
        padding: 0 27rpx;
        box-sizing: border-box;
        font-family: PingFangSC, PingFang SC;
        font-weight: 600;
        font-size: 31rpx;
        color: #303133;
        line-height: 42rpx;
        text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        .invoice {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 27rpx;
            color: #4F4F4F;
            line-height: 38rpx;
            text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        }
        image {
            margin-left: 12rpx;
        }
    }
    .list-item {
        margin-top: 27rpx;
        width: 696rpx;
        height: 173rpx;
        background: #FFFFFF;
        border-radius: 19rpx;
        padding: 25rpx 31rpx;
        .time {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 23rpx;
            color: #8C8C8C;
            line-height: 23rpx;
        }
        .status {
            width: 104rpx;
            height: 46rpx;
            background: #D9FFF2;
            border-radius: 12rpx;
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 25rpx;
            color: #06C584;
            line-height: 23rpx;
            letter-spacing: 1px;
            margin-bottom: 17rpx;
        }
        .name {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #303133;
            line-height: 54rpx;
        }
        .price {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #FF6257;
            line-height: 38rpx;
            text {
                font-size: 27rpx;
            }
        }
    }
}
</style>
miniprogram/pages/invoice/applyInvoice.vue
New file
@@ -0,0 +1,182 @@
<template>
    <view class="container">
        <view class="head flex a-center j-between">
            <view>开票记录</view>
            <view class="flex a-center invoice" @click="toAdd">我要开票 <image src="/static/image/mine/arrowRight.png" class="w-23 h-23">
                </image>
            </view>
        </view>
        <view class="px-27">
            <view class="list-item" v-for="(item, index) in invoiceList" :key="index"  @click="toDetail(item)">
                <view class="flex a-center j-between">
                    <view class="time">{{ item.time || '' }}</view>
                    <view class="status flex a-center j-center">开票中</view>
                </view>
                <view class="flex a-center j-between">
                    <view class="name">{{ item.name || '' }}</view>
                    <view class="price"><text>¥ </text>{{ item.price || '' }}</view>
                </view>
            </view>
        </view>
    </view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onLoad, onUnload, onShow, onReachBottom } from "@dcloudio/uni-app";
const invoiceList = ref([
    {
        time: '2023-08-01 10:00:00',
        name: '成人票',
        price: '100.00'
    }
]);
const finished = ref(false);
const loading = ref(false);
const searchParams = ref({
    pageNum: 1,
    pageSize: 10
})
const toAdd = () => {
    uni.navigateTo({
        url: '/pages/invoice/addInvoice',
    })
}
const toDetail = (item) => {
    uni.navigateTo({
        url: '/pages/invoice/invoiceDetail?id=' + item.id,
    })
}
const fetchList = () => {
    //         // if (loading.value || finished.value) return
    //         loading.value = true
    //         getMonitorList({
    //             nameOrCode: keyword.value || '',
    //             pageNum: searchParams.value.pageNum,
    //             pageSize: searchParams.value.pageSize
    //         }).then(res => {
    //             // PC 端类型定义:{ records, total, current, size }
    //             const data = res.data || res || {}
    //             const records = data.records || []
    //             const total = data.total || 0
    //             if (searchParams.value.pageNum === 1) {
    //                 list.value = records
    //             } else {
    //                 list.value = list.value.concat(records)
    //             }
    //             // 判断是否已全部加载
    //             if (!records.length || list.value.length >= total) {
    //                 finished.value = true
    //             } else {
    //                 searchParams.value.pageNum += 1
    //             }
    //         }).catch(() => {
    //             uni.showToast({
    //                 title: '获取巡检列表失败',
    //                 icon: 'none'
    //             })
    //         }).finally(() => {
    //             loading.value = false
    //         })
}
onReachBottom(() => {
})
</script>
<style scoped lang="scss">
.container {
    width: 100%;
    height: 100%;
    position: relative;
    .head {
        width: 100%;
        height: 96rpx;
        background: #FFFFFF;
        box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(0, 0, 0, 0.05);
        position: sticky;
        top: 0;
        left: 0;
        padding: 0 27rpx;
        box-sizing: border-box;
        font-family: PingFangSC, PingFang SC;
        font-weight: 600;
        font-size: 31rpx;
        color: #303133;
        line-height: 42rpx;
        text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        .invoice {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 27rpx;
            color: #4F4F4F;
            line-height: 38rpx;
            text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        }
        image {
            margin-left: 12rpx;
        }
    }
    .list-item {
        margin-top: 27rpx;
        width: 696rpx;
        height: 173rpx;
        background: #FFFFFF;
        border-radius: 19rpx;
        padding: 25rpx 31rpx;
        .time {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 23rpx;
            color: #8C8C8C;
            line-height: 23rpx;
        }
        .status {
            width: 104rpx;
            height: 46rpx;
            background: #D9FFF2;
            border-radius: 12rpx;
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 25rpx;
            color: #06C584;
            line-height: 23rpx;
            letter-spacing: 1px;
            margin-bottom: 17rpx;
        }
        .name {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #303133;
            line-height: 54rpx;
        }
        .price {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #FF6257;
            line-height: 38rpx;
            text {
                font-size: 27rpx;
            }
        }
    }
}
</style>
miniprogram/pages/invoice/invoice.vue
New file
@@ -0,0 +1,182 @@
<template>
    <view class="container">
        <view class="head flex a-center j-between">
            <view>开票记录</view>
            <view class="flex a-center invoice" @click="toAdd">我要开票 <image src="/static/image/mine/arrowRight.png" class="w-23 h-23">
                </image>
            </view>
        </view>
        <view class="px-27">
            <view class="list-item" v-for="(item, index) in invoiceList" :key="index"  @click="toDetail(item)">
                <view class="flex a-center j-between">
                    <view class="time">{{ item.time || '' }}</view>
                    <view class="status flex a-center j-center">开票中</view>
                </view>
                <view class="flex a-center j-between">
                    <view class="name">{{ item.name || '' }}</view>
                    <view class="price"><text>¥ </text>{{ item.price || '' }}</view>
                </view>
            </view>
        </view>
    </view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onLoad, onUnload, onShow, onReachBottom } from "@dcloudio/uni-app";
const invoiceList = ref([
    {
        time: '2023-08-01 10:00:00',
        name: '成人票',
        price: '100.00'
    }
]);
const finished = ref(false);
const loading = ref(false);
const searchParams = ref({
    pageNum: 1,
    pageSize: 10
})
const toAdd = () => {
    uni.navigateTo({
        url: '/pages/invoice/addInvoice',
    })
}
const toDetail = (item) => {
    uni.navigateTo({
        url: '/pages/invoice/invoiceDetail?id=' + item.id,
    })
}
const fetchList = () => {
    //         // if (loading.value || finished.value) return
    //         loading.value = true
    //         getMonitorList({
    //             nameOrCode: keyword.value || '',
    //             pageNum: searchParams.value.pageNum,
    //             pageSize: searchParams.value.pageSize
    //         }).then(res => {
    //             // PC 端类型定义:{ records, total, current, size }
    //             const data = res.data || res || {}
    //             const records = data.records || []
    //             const total = data.total || 0
    //             if (searchParams.value.pageNum === 1) {
    //                 list.value = records
    //             } else {
    //                 list.value = list.value.concat(records)
    //             }
    //             // 判断是否已全部加载
    //             if (!records.length || list.value.length >= total) {
    //                 finished.value = true
    //             } else {
    //                 searchParams.value.pageNum += 1
    //             }
    //         }).catch(() => {
    //             uni.showToast({
    //                 title: '获取巡检列表失败',
    //                 icon: 'none'
    //             })
    //         }).finally(() => {
    //             loading.value = false
    //         })
}
onReachBottom(() => {
})
</script>
<style scoped lang="scss">
.container {
    width: 100%;
    height: 100%;
    position: relative;
    .head {
        width: 100%;
        height: 96rpx;
        background: #FFFFFF;
        box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(0, 0, 0, 0.05);
        position: sticky;
        top: 0;
        left: 0;
        padding: 0 27rpx;
        box-sizing: border-box;
        font-family: PingFangSC, PingFang SC;
        font-weight: 600;
        font-size: 31rpx;
        color: #303133;
        line-height: 42rpx;
        text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        .invoice {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 27rpx;
            color: #4F4F4F;
            line-height: 38rpx;
            text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        }
        image {
            margin-left: 12rpx;
        }
    }
    .list-item {
        margin-top: 27rpx;
        width: 696rpx;
        height: 173rpx;
        background: #FFFFFF;
        border-radius: 19rpx;
        padding: 25rpx 31rpx;
        .time {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 23rpx;
            color: #8C8C8C;
            line-height: 23rpx;
        }
        .status {
            width: 104rpx;
            height: 46rpx;
            background: #D9FFF2;
            border-radius: 12rpx;
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 25rpx;
            color: #06C584;
            line-height: 23rpx;
            letter-spacing: 1px;
            margin-bottom: 17rpx;
        }
        .name {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #303133;
            line-height: 54rpx;
        }
        .price {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #FF6257;
            line-height: 38rpx;
            text {
                font-size: 27rpx;
            }
        }
    }
}
</style>
miniprogram/pages/invoice/invoiceDetail.vue
New file
@@ -0,0 +1,182 @@
<template>
    <view class="container">
        <view class="head flex a-center j-between">
            <view>开票记录</view>
            <view class="flex a-center invoice" @click="toAdd">我要开票 <image src="/static/image/mine/arrowRight.png" class="w-23 h-23">
                </image>
            </view>
        </view>
        <view class="px-27">
            <view class="list-item" v-for="(item, index) in invoiceList" :key="index"  @click="toDetail(item)">
                <view class="flex a-center j-between">
                    <view class="time">{{ item.time || '' }}</view>
                    <view class="status flex a-center j-center">开票中</view>
                </view>
                <view class="flex a-center j-between">
                    <view class="name">{{ item.name || '' }}</view>
                    <view class="price"><text>¥ </text>{{ item.price || '' }}</view>
                </view>
            </view>
        </view>
    </view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onLoad, onUnload, onShow, onReachBottom } from "@dcloudio/uni-app";
const invoiceList = ref([
    {
        time: '2023-08-01 10:00:00',
        name: '成人票',
        price: '100.00'
    }
]);
const finished = ref(false);
const loading = ref(false);
const searchParams = ref({
    pageNum: 1,
    pageSize: 10
})
const toAdd = () => {
    uni.navigateTo({
        url: '/pages/invoice/addInvoice',
    })
}
const toDetail = (item) => {
    uni.navigateTo({
        url: '/pages/invoice/invoiceDetail?id=' + item.id,
    })
}
const fetchList = () => {
    //         // if (loading.value || finished.value) return
    //         loading.value = true
    //         getMonitorList({
    //             nameOrCode: keyword.value || '',
    //             pageNum: searchParams.value.pageNum,
    //             pageSize: searchParams.value.pageSize
    //         }).then(res => {
    //             // PC 端类型定义:{ records, total, current, size }
    //             const data = res.data || res || {}
    //             const records = data.records || []
    //             const total = data.total || 0
    //             if (searchParams.value.pageNum === 1) {
    //                 list.value = records
    //             } else {
    //                 list.value = list.value.concat(records)
    //             }
    //             // 判断是否已全部加载
    //             if (!records.length || list.value.length >= total) {
    //                 finished.value = true
    //             } else {
    //                 searchParams.value.pageNum += 1
    //             }
    //         }).catch(() => {
    //             uni.showToast({
    //                 title: '获取巡检列表失败',
    //                 icon: 'none'
    //             })
    //         }).finally(() => {
    //             loading.value = false
    //         })
}
onReachBottom(() => {
})
</script>
<style scoped lang="scss">
.container {
    width: 100%;
    height: 100%;
    position: relative;
    .head {
        width: 100%;
        height: 96rpx;
        background: #FFFFFF;
        box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(0, 0, 0, 0.05);
        position: sticky;
        top: 0;
        left: 0;
        padding: 0 27rpx;
        box-sizing: border-box;
        font-family: PingFangSC, PingFang SC;
        font-weight: 600;
        font-size: 31rpx;
        color: #303133;
        line-height: 42rpx;
        text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        .invoice {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 27rpx;
            color: #4F4F4F;
            line-height: 38rpx;
            text-shadow: 0px 6px 6px rgba(0, 0, 0, 0.05);
        }
        image {
            margin-left: 12rpx;
        }
    }
    .list-item {
        margin-top: 27rpx;
        width: 696rpx;
        height: 173rpx;
        background: #FFFFFF;
        border-radius: 19rpx;
        padding: 25rpx 31rpx;
        .time {
            font-family: PingFangSC, PingFang SC;
            font-weight: 500;
            font-size: 23rpx;
            color: #8C8C8C;
            line-height: 23rpx;
        }
        .status {
            width: 104rpx;
            height: 46rpx;
            background: #D9FFF2;
            border-radius: 12rpx;
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 25rpx;
            color: #06C584;
            line-height: 23rpx;
            letter-spacing: 1px;
            margin-bottom: 17rpx;
        }
        .name {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #303133;
            line-height: 54rpx;
        }
        .price {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 38rpx;
            color: #FF6257;
            line-height: 38rpx;
            text {
                font-size: 27rpx;
            }
        }
    }
}
</style>
miniprogram/pages/tourist/tourist.vue
@@ -8,7 +8,7 @@
            <view v-for="(item, index) in list" :key="index" class="item" @click="selectTourist(item)">
                <view class="flex a-center">
                    <view class="name">{{ item.name }}</view>
                    <image src="../../static/image/mine/edit.png" class="w-23 h-23 ml-38" @click.stop="toAddTourist(item.id)"></image>
                    <image src="../../static/image/mine/modify.png" class="w-23 h-23 ml-38" @click.stop="toAddTourist(item.id)"></image>
                </view>
                <view class="flex a-center j-between info">
                    <view>身份证 {{ item.idCard }}</view>
miniprogram/static/image/mine/arrowRight.png
miniprogram/static/image/mine/modify.png