doum
2025-09-08 55ba702c1df240929e68df3b42fa9cb0607378b8
Merge remote-tracking branch 'origin/2.0.1' into 2.0.1

# Conflicts:
# admin/.env.development
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/common/main.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-icon/u-icon.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-line/u-line.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-loading-icon/u-loading-icon.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-modal/u-modal.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-overlay/u-overlay.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-popup/u-popup.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-safe-bottom/u-safe-bottom.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-status-bar/u-status-bar.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/node-modules/uview-ui/components/u-transition/u-transition.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/consumptionDetails/consumptionDetails.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/maps/maps.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/pricingRules/pricingRules.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/problemReporting/problemReporting.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/ridingDetails/ridingDetails.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/settlementDetails/settlementDetails.js.map
# bicycle/unpackage/dist/dev/.sourcemap/mp-weixin/pages/specification/specification.js.map
# bicycle/unpackage/dist/dev/mp-weixin/common/vendor.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-icon/u-icon.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-line/u-line.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-loading-icon/u-loading-icon.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-modal/u-modal.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-overlay/u-overlay.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-popup/u-popup.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-safe-bottom/u-safe-bottom.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-status-bar/u-status-bar.js
# bicycle/unpackage/dist/dev/mp-weixin/node-modules/uview-ui/components/u-transition/u-transition.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/consumptionDetails/consumptionDetails.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/index/index.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/maps/maps.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/pricingRules/pricingRules.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/problemReporting/problemReporting.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/ridingDetails/ridingDetails.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/settlementDetails/settlementDetails.js
# bicycle/unpackage/dist/dev/mp-weixin/pages/specification/specification.js
# server/services/src/main/java/com/doumee/service/business/impl/BikesServiceImpl.java
已添加19个文件
已修改32个文件
1745 ■■■■■ 文件已修改
admin/src/api/business/goodsorder.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/billDetail.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/analysis.vue 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/goodsorder.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/onlinePayStatistics.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/wxBill.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/wxBillDetail.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/combo/record.vue 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/operation/components/AMap.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/operation/components/TramEdit.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/operation/site.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/main.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/manifest.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/pages.json 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/pages/index/index.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/pages/operationList/operationList.vue 680 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/pages/operationLogin/operationLogin.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/pages/operationsCenter/operationsCenter.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/home_ic_mingxi.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_close@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_guansuo@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_kaisuo@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_search@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_shaixuan@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_shangjia@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/ic_xiajia@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/list_checkbox@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/list_checkbox_sel@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/login_ic_name@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/icon/login_ic_password@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/static/images/home_i1mg_zulingxuzhi@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/unpackage/dist/dev/mp-weixin/app.json 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/unpackage/dist/dev/mp-weixin/common/main.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/unpackage/dist/dev/mp-weixin/pages/index/index.wxml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/unpackage/dist/dev/mp-weixin/pages/index/index.wxss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/unpackage/dist/dev/mp-weixin/project.private.config.json 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bicycle/utils/http.api.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/platform/src/main/java/com/doumee/api/business/GoodsorderController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelExporter.java 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/core/utils/DateUtil.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/DiscountMember.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/model/Goodsorder.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/vo/BikeIncomeDetailReportVO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/vo/BikeIncomeReportVO.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/vo/GoodsorderExportVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/dao/business/web/response/RidesDetailResponse.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/GoodsorderService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/DiscountMemberServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/GoodsorderServiceImpl.java 192 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/services/src/main/java/com/doumee/service/business/impl/WxBillServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/web/src/main/java/com/doumee/task/ScheduleTool.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/goodsorder.js
@@ -35,7 +35,19 @@
export function closerGoodsorder (id) {
  return request.post('/business/goodsorder/closerGoodsorder', {id})
}
// è½¦åž‹æ”¶å…¥åˆ†æž
export function getBikeIncomeReportVOList (data) {
  return request.post('/business/goodsorder/getBikeIncomeReportVOList', data)
}
// èŽ·å–å¯é€€æ¬¾ä¿¡æ¯
export function getGoodsorderCanBanlanceDTO (params) {
  return request.get('/business/goodsorder/getGoodsorderCanBanlanceDTO', {params})
}
// å¯¼å‡ºExcel
export function bikeIncomeExportExcel (data) {
  return request.post('/business/goodsorder/bikeIncomeExportExcel', data, {
    trim: true,
    download: true
  })
}
admin/src/components/business/billDetail.vue
@@ -12,11 +12,24 @@
      >
        <el-table-column prop="openid" label="用户" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="code" label="订单编号" min-width="100px" align="center"></el-table-column>
        <el-table-column label="订单类型" min-width="100px" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.bikeType === 1">套餐订单</span>
            <span v-else-if="scope.row.bikeType === 3">自行车订单</span>
            <span v-else-if="scope.row.bikeType === 4">电动车订单</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column prop="payDate" label="支付时间" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="money" label="支付金额" width="80px" align="center"></el-table-column>
        <el-table-column prop="refundDate" label="退款时间" width="150px" align="center"></el-table-column>
        <el-table-column prop="refundMoney" label="退款金额" width="80px" align="center"></el-table-column>
        <el-table-column prop="closeMoney" label="结算金额" width="80px" align="center"></el-table-column>
        <el-table-column label="结算金额" width="80px" align="center">
          <template slot-scope="scope">
            <span v-if="scope.row.bikeType === 1">-</span>
            <span v-else>{{scope.row.closeMoney}}</span>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
admin/src/views/business/analysis.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
<template>
    <TableLayout :permissions="['business:wxbill:query']">
        <!-- æœç´¢è¡¨å• -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="对账日期" prop="name">
                <el-date-picker
                    v-model="value1"
                    type="daterange"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    :picker-options="pickerOptions"
                    format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss"
                    @change="selectDate"
                ></el-date-picker>
            </el-form-item>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
                <el-button @click="reset">重置</el-button>
                <el-button type="primary" @click="daochu">导出</el-button>
            </section>
        </el-form>
        <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
        <template v-slot:table-wrap>
            <el-table
                v-loading="isWorking.search"
                :data="list"
                stripe
                border
            >
                <el-table-column :prop="item" :label="item" align="center" v-for="(item, index) in column" :key="index"></el-table-column>
            </el-table>
        </template>
    </TableLayout>
</template>
<script>
  import BaseTable from '@/components/base/BaseTable'
  import TableLayout from '@/layouts/TableLayout'
  import Pagination from '@/components/common/Pagination'
  import { getBikeIncomeReportVOList, bikeIncomeExportExcel } from '@/api/business/goodsorder'
  export default {
    name: 'analysis',
    extends: BaseTable,
    components: { TableLayout, Pagination },
    data () {
      return {
        value1: [],
        list: [],
        column: [],
        // æœç´¢
        searchForm: {
          endDate: '',
          startDate: ''
        },
        sumData: {
        },
        pickerOptions: {}
      }
    },
    created () {
      this.config({
        module: '',
        api: '/business/wxBill',
        'field.id': 'id',
        'field.main': 'id'
      })
      this.pickerOptions.disabledDate = (time) => {
        // ä¸€å¤©
        const tempTime = 3600 * 1000 * 24
        return time.getTime() > new Date() - tempTime
      }
      const yesterday = new Date();
      yesterday.setDate(yesterday.getDate() - 1);
      const startDate = new Date(yesterday);
      startDate.setDate(startDate.getDate() - 30);
      this.searchForm.startDate = startDate.toISOString().split('T')[0] + ' 00:00:00'
      this.searchForm.endDate = yesterday.toISOString().split('T')[0] + ' 00:00:00'
      this.value1 = [this.searchForm.startDate, this.searchForm.endDate]
      this.search()
    },
    methods: {
      search() {
        getBikeIncomeReportVOList({
          startDate: this.searchForm.startDate,
          endDate: this.searchForm.endDate
        }).then(res => {
          this.column = res.map(item => item[0])
          const keys = res.map(row => row[0]); // èŽ·å–é”®å
          const values = res.map(row => row.slice(1, row.length)); // èŽ·å–å€¼
          this.list = values[0].map((_, index) => {
            return keys.reduce((obj, key, i) => {
              obj[key] = values[i][index];
              return obj;
            }, {});
          });
        })
      },
      daochu() {
        bikeIncomeExportExcel({
          startDate: this.searchForm.startDate,
          endDate: this.searchForm.endDate
        }).then(res => {
          this.download(res)
          console.log(res.data)
        })
      },
      reset () {
        const yesterday = new Date();
        yesterday.setDate(yesterday.getDate() - 1);
        const startDate = new Date(yesterday);
        startDate.setDate(startDate.getDate() - 30);
        this.searchForm.startDate = startDate.toISOString().split('T')[0] + ' 00:00:00'
        this.searchForm.endDate = yesterday.toISOString().split('T')[0] + ' 00:00:00'
        this.value1 = [this.searchForm.startDate, this.searchForm.endDate]
        this.search()
      },
      getDays(startDate, endDate) {
        const date1 = new Date(startDate); // ç¬¬ä¸€ä¸ªæ—¥æœŸ
        const date2 = new Date(endDate); // ç¬¬äºŒä¸ªæ—¥æœŸ
        const timeDifference = date2 - date1;
        return timeDifference / (1000 * 3600 * 24);
      },
      selectDate (v) {
        // this.searchForm.startDate = ''
        // this.searchForm.endDate = ''
        if (v) {
          if (this.getDays(v[0], v[1]) > 30) {
            this.$message.warning('最多只能选择30天')
            const yesterday = new Date();
            yesterday.setDate(yesterday.getDate() - 1);
            const startDate = new Date(yesterday);
            startDate.setDate(startDate.getDate() - 30);
            this.searchForm.startDate = startDate.toISOString().split('T')[0] + ' 00:00:00'
            this.searchForm.endDate = yesterday.toISOString().split('T')[0] + ' 00:00:00'
            this.value1 = [this.searchForm.startDate, this.searchForm.endDate]
          } else {
            this.searchForm.startDate = v[0]
            this.searchForm.endDate = v[1]
          }
        }
        this.search()
      },
      // é¡µç å˜æ›´å¤„理
      handlePageChange (pageIndex) {
        this.__checkApi()
        this.tableData.pagination.pageIndex = pageIndex || this.tableData.pagination.pageIndex
        this.isWorking.search = true
        this.api.fetchList({
          page: this.tableData.pagination.pageIndex,
          capacity: this.tableData.pagination.pageSize,
          model: this.searchForm,
          sorts: this.tableData.sorts
        })
          .then(data => {
            this.tableData.list = data.records
            this.tableData.pagination.total = data.total
            this.sumData = data.extData
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
          .finally(() => {
            this.isWorking.search = false
          })
      }
    }
  }
</script>
<style lang="scss" scoped>
    ::v-deep .el-table tbody tr:last-child {
        font-size: 16px;
        font-weight: bold;
        background-color: #f3f3fb;
    }
    .sum {
        display: flex;
        font-size: 16px;
        margin-bottom: 10px;
        background-color: rgb(243, 243, 251);
        .sum-title {
            flex-shrink: 0;
            background-color: rgb(111, 129, 198);
            color: #fff;
            font-weight: 500;
            text-align: center;
            padding: 15px;
        }
        .sum-value {
            padding: 15px 30px;
            :first-child {
                font-size: 14px;
            }
            :last-child {
                font-weight: 600;
            }
        }
    }
</style>
admin/src/views/business/goodsorder.vue
@@ -155,7 +155,7 @@
        payStatus: '',
        payWay: '',
        payDate: '',
        type: '',
        type: 0,
        closeMoney: '',
        startDate: '',
        endDate: '',
admin/src/views/business/onlinePayStatistics.vue
@@ -2,12 +2,12 @@
  <TableLayout>
    <!-- æœç´¢è¡¨å• -->
    <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
      <el-form-item label="创建时间" prop="name">
        <el-date-picker
          v-model="value1"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
@@ -15,7 +15,7 @@
          @change="selectDate"
        ></el-date-picker>
      </el-form-item>
      <section>
        <el-button type="primary" @click="search">搜索</el-button>
        <el-button @click="reset">重置</el-button>
@@ -45,7 +45,7 @@
          ></el-table-column>
        </el-table-column>
      </el-table>
    </template>
    <!-- æ–°å»º/修改 -->
  </TableLayout>
@@ -83,11 +83,12 @@
      this.$refs.searchForm.resetFields()
      this.search()
    },
    search() {
      fetchList(this.searchForm)
        .then(res => {
          this.tableData.list = [
            { name: '套餐收入', payNum: res.discountNum, payMoney: res.discountMoney },
            { name: '支付押金', payNum: res.payNum, payMoney: res.payMoney },
            { name: '退款', payNum: res.refundNum, payMoney: res.refundMoney },
            { name: '未结算', payNum: res.unClosedNum, payMoney: res.unClosedMoney },
admin/src/views/business/wxBill.vue
@@ -55,6 +55,14 @@
          <div>结算金额(元)</div>
          <div>{{ sumData.total }}</div>
        </div>
        <div class="sum-value">
          <div>骑行收入(元)</div>
          <div>{{ sumData.bikeFee }}</div>
        </div>
        <div class="sum-value">
          <div>套餐收入(元)</div>
          <div>{{ sumData.discountFee }}</div>
        </div>
      </div>
      <el-table
        v-loading="isWorking.search"
@@ -70,12 +78,9 @@
        <el-table-column prop="sumRefundBill" label="退款笔数" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="sumRefundFee" label="退款金额(元)" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="sumRefundCmmsAmt" label="退款手续费(元)" min-width="100px" align="center"></el-table-column>
        <!-- <el-table-column prop="sumSuccessFee" label="应结订单总金额" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="sumCouponRefundFee" label="充值券退款总金额" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="sumApplyRefundFee" label="申请退款总金额" min-width="100px" align="center"></el-table-column> -->
        <el-table-column prop="total" label="结算金额(元)" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="bikeFee" label="自行车收入(元)" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="bikeFee" label="骑行收入(元)" min-width="100px" align="center"></el-table-column>
        <el-table-column prop="discountFee" label="套餐收入(元)" min-width="100px" align="center"></el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
admin/src/views/business/wxBillDetail.vue
@@ -60,9 +60,15 @@
            <span>{{scope.row.total == 0 ? '-' : scope.row.total }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="bikefee" label="自行车收入(元)" min-width="100px" align="center">
        <el-table-column prop="bikefee" label="骑行收入(元)" min-width="100px" align="center">
          <template slot-scope="scope">
            <span>{{scope.row.bikeFee == 0 ? '-' : scope.row.bikeFee }}</span>
          </template>
        </el-table-column>
        <el-table-column label="套餐收入(元)" min-width="100px" align="center">
          <template slot-scope="scope">
<!--            <span>{{scope.row.discountFee >= 0 ? scope.row.discountFee : '-' }}</span>-->
            <span>{{ [0,2].includes(scope.$index) ? scope.row.discountFee : '-' }}</span>
          </template>
        </el-table-column>
        <!-- v-if="containPermissions(['business:pricingparam:update', 'business:pricingparam:delete'])" -->
@@ -81,7 +87,6 @@
          </template>
        </el-table-column>
      </el-table>
    </template>
    <BillDetailWindow ref="billDetailWindow"/>
  </TableLayout>
@@ -192,7 +197,6 @@
    search () {
      fetchList(this.searchForm)
        .then(res => {
          console.log(res)
          this.tableData.list = [
            { billType: '交易实收', ...res[0], cmmsAmt: (res[0].sumCmmsAmt + res[0].sumRefundCmmsAmt).toFixed(2) },
            { billType: '退款', ...res[1], cmmsAmt: (res[1].sumCmmsAmt + res[1].sumRefundCmmsAmt).toFixed(2) },
@@ -212,7 +216,7 @@
      this.search()
    },
    arraySpanMethod ({ row, column, rowIndex, columnIndex }) {
      if (rowIndex == 3) {
      if (rowIndex === 3) {
        if (columnIndex === 0) {
          return [1, 8]
        } else {
admin/src/views/combo/record.vue
@@ -6,7 +6,7 @@
    <div class="table_btns">
      <el-button plain type="primary" @click="handleEx">导出</el-button>
      <el-button plain type="danger" @click="openModal('zuofei')">作废</el-button>
      <el-button plain @click="openModal('tiaozheng')">套餐调整</el-button>
      <el-button plain type="primary" @click="openModal('tiaozheng')">套餐调整</el-button>
    </div>
    <el-table v-loading="loading" :data="list" stripe border @selection-change="handleSelectionChange">
      <el-table-column fixed="left" align="center" type="selection" :selectable="handleDisable" width="55" />
@@ -32,6 +32,7 @@
          <span>{{ scope.row.useStartDate }}至{{ scope.row.useEndDate }}</span>
        </template>
      </el-table-column>
      <el-table-column align="center" label="创建时间" min-width="150" prop="createDate" show-overflow-tooltip />
      <el-table-column align="center" label="套餐状态" min-width="80">
        <template v-slot="scope">
          <span v-if="scope.row.status == '0'" class="text_success">正常</span>
@@ -144,8 +145,17 @@
          clearable: true,
          options: [
            { value: '0', label: '正常' },
            { value: '1', label: '作废' },
            // { value: '2', label: '待支付' }
            { value: '1', label: '作废' }
          ]
        },{
          filed: 'createDate',
          type: 'daterange',
          label: '创建日期',
          placeholder: '请选择状态',
          clearable: true,
          options: [
            { value: '0', label: '正常' },
            { value: '1', label: '作废' }
          ]
        }],
        online: true
@@ -171,7 +181,6 @@
      remarkCan: '',
      // â¬‡ï¸adjust调整相关
      isShowAdjust: false,
      isShowCan: false,
      canList: [],
      adjustData: {
        flag: 0,
@@ -200,13 +209,19 @@
    },
    handleEx() {
      const { pagination, filters } = this
      let form = JSON.parse(JSON.stringify(filters))
      if (form.createDate && form.createDate.length > 0) {
        form.startCreateDate = form.createDate[0] + ' 00:00:00'
        form.endCreateDate = form.createDate[1] + ' 23:59:59'
        delete form.createDate
      }
      this.$dialog.exportConfirm('确认导出吗?')
        .then(() => {
          this.loading = true
          comboSaleEx({
            page: 1,
            capacity: 1000000,
            model: filters
            model: form
          })
            .then(response => {
              this.download(response)
@@ -233,9 +248,15 @@
      const { pagination, filters } = this
      this.loading = true
      if (page) { pagination.page = page }
      let form = JSON.parse(JSON.stringify(filters))
      if (form.createDate && form.createDate.length > 0) {
        form.startCreateDate = form.createDate[0] + ' 00:00:00'
        form.endCreateDate = form.createDate[1] + ' 23:59:59'
        delete form.createDate
      }
      comboSalePage({
        model: {
          ...filters
          ...form
        },
        capacity: pagination.pageSize,
        page: pagination.page,
admin/src/views/operation/components/AMap.vue
@@ -1,6 +1,6 @@
<template>
  <GlobalWindow title="绘制运营区域" :visible.sync="isShowModal" :confirm-working="isWorking" @close="close"
    @confirm="confirm" width="1000px">
    @confirm="confirm" width="100%">
    <div class="map_title">绘制:鼠标左键点击及移动即可绘制图形,绘制过程中按下esc键可中断该过程</div>
    <div class="map_title">鼠标左键双击即可结束当前多边形绘制,多边形会自动闭合;</div>
    <div class="map_wrap">
@@ -52,11 +52,11 @@
      //     maximumAge: 0 // ç¦ç”¨ç¼“å­˜
      //   }
      // )
      console.log('-----')
      console.log('-----', this.row)
      map = new TMap.Map("containera", {
        zoom: 16, // è®¾ç½®åœ°å›¾ç¼©æ”¾çº§åˆ«
        center: new TMap.LatLng(31.722763, 117.385480) // è®¾ç½®åœ°å›¾ä¸­å¿ƒç‚¹åæ ‡
        zoom: this.polygons.length > 0 ? 20 : 16, // è®¾ç½®åœ°å›¾ç¼©æ”¾çº§åˆ«
        center: this.polygons.length > 0 ? new TMap.LatLng(this.polygons[0].lat, this.polygons[0].lng) : new TMap.LatLng(31.722763, 117.385480) // è®¾ç½®åœ°å›¾ä¸­å¿ƒç‚¹åæ ‡
      })
      var tempList = []
      if (this.polygons.length > 0) {
@@ -157,4 +157,4 @@
    z-index: 99999999999;
  }
}
</style>
</style>
admin/src/views/operation/components/TramEdit.vue
@@ -34,6 +34,7 @@
    return {
      // è¡¨å•数据
      form: {
        id: null,
        paramId: '',
        code: '',
        deviceSn: '',
admin/src/views/operation/site.vue
@@ -92,7 +92,6 @@
  },
  methods: {
    changeMap(e, row) {
      console.log(e);
      updateById({ ...row, electronicFence: JSON.stringify(e) }).then(res => {
        if (res) {
          Message.success('设置成功')
@@ -104,9 +103,9 @@
      this.$refs.MapRef.isShowModal = true
      this.$nextTick(() => {
        this.$refs.MapRef.row = row
        // if (row.electronicFence) {
        //   this.$refs.MapRef.polygons = JSON.parse(row.electronicFence)
        // }
        if (row.electronicFence) {
          this.$refs.MapRef.polygons = JSON.parse(row.electronicFence)
        }
        this.$refs.MapRef.initMap()
      })
bicycle/main.js
@@ -16,8 +16,9 @@
    Vue.prototype.$isResolve = resolve;
})
// Vue.prototype.$baseUrl = 'http://192.168.0.129:10025/'
Vue.prototype.$baseUrl = 'https://dmtest.ahapp.net/bike_h5_api/'
Vue.prototype.$baseUrl = 'http://192.168.1.46:10025/'
// Vue.prototype.$baseUrl = 'https://bikes.yxbhlt.cn/bike_h5_api/'
// Vue.prototype.$baseUrl = 'https://dmtest.ahapp.net/bike_h5_api/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu2.natapp1.cc/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu.natapp1.cc/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu3.natapp1.cc/'
bicycle/manifest.json
@@ -5,6 +5,7 @@
    "versionName" : "1.0.0",
    "versionCode" : "100",
    "transformPx" : false,
    "sassImplementationName" : "node-sass",
    /* 5+App特有相关 */
    "app-plus" : {
        "usingComponents" : true,
bicycle/pages.json
@@ -114,6 +114,27 @@
                "navigationBarTitleText" : "支付订单",
                "navigationBarBackgroundColor": "#ffffff"
            }
        },
        {
            "path" : "pages/operationLogin/operationLogin",
            "style" :
            {
                "navigationBarTitleText" : "运营中心"
            }
        },
        {
            "path" : "pages/operationsCenter/operationsCenter",
            "style" :
            {
                "navigationBarTitleText" : "运营中心"
            }
        },
        {
            "path" : "pages/operationList/operationList",
            "style" :
            {
                "navigationBarTitleText" : "运营中心"
            }
        }
    ],
    "globalStyle": {
bicycle/pages/index/index.vue
@@ -38,7 +38,7 @@
                    </image>
                </view>
                <view class="index_box_function">
                    <view class="cXYC" v-for="(item, index) in functionList" :key="index" @click.stop="jump(item)">
                    <view class="cXYC" :style="{ marginTop: item.id === 5 ? '30rpx' : '' }" v-for="(item, index) in functionList" :key="index" @click.stop="jump(item)">
                        <button open-type="getPhoneNumber" @getphonenumber="getPhone" v-if="!userInfo.mobile"></button>
                        <image class="img80" :src="item.icon" mode="widthFix"></image>
                        <text class="f26 c3 mt10">{{item.name}}</text>
@@ -314,6 +314,11 @@
                        id: 4,
                        name: '消费明细',
                        icon: require('@/static/images/home_ic_mingxi@2x.png')
                    },
                    {
                        id: 5,
                        name: '运营中心',
                        icon: require('@/static/icon/home_ic_mingxi.png')
                    },
                ],
@@ -715,6 +720,16 @@
                    uni.navigateTo({
                        url: '/pages/consumptionDetails/consumptionDetails'
                    }); 
                } else if (item.id === 5) {
                    if (!this.userInfo.sysuser) {
                        uni.navigateTo({
                            url: '/pages/operationLogin/operationLogin'
                        });
                    } else {
                        uni.navigateTo({
                            url: '/pages/operationsCenter/operationsCenter'
                        });
                    }
                } else if (item.id === 2) {
                    if (!this.userInfo.mobile) return
                    if (this.info.rideStatus === 1) {
@@ -1419,12 +1434,14 @@
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    flex-wrap: wrap;
                    position: relative;
                    top: -24rpx;
                    text {
                        font-weight: 400;
                    }
                    .cXYC {
                        width: 23%;
                        position: relative;
                        button {
                            width: 100%;
bicycle/pages/operationList/operationList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,680 @@
<template>
    <view class="box">
        <view class="search">
            <view class="search_sou">
                <image src="/static/icon/ic_search@2x.png" mode="widthFix"></image>
                <input type="text" v-model="form.code" placeholder="搜索车辆编号" @confirm="getList(1)" />
            </view>
            <view class="search_shai" @click="show = true">
                <text>筛选</text>
                <image src="/static/icon/ic_shaixuan@2x.png" mode="widthFix"></image>
            </view>
        </view>
        <view class="list">
            <view class="list_item" v-for="(item, index) in list" :key="index">
                <view class="list_item_title">
                    <view class="list_item_title_left">车辆编号:{{item.code}}</view>
                    <view class="list_item_title_cate">
                        <view class="list_item_title_cate_row" :style="{ background: item.isOnline === 1 ? '#E7F8F7' : 'rgba(255, 90, 49, 0.10)', color: item.isOnline === 1 ? '#01B6AD' : '#FF5A31' }">{{item.isOnline === 1 ? '在线' : '离线'}}</view>
                        <view class="list_item_title_cate_row" :style="{ background: item.lockStatus === 1 ? '#E7F8F7' : 'rgba(255, 90, 49, 0.10)', color: item.lockStatus === 1 ? '#01B6AD' : '#FF5A31' }">{{item.lockStatus === 1 ? '开锁' : '关锁'}}</view>
                        <view class="list_item_title_cate_row" :style="{ background: item.status === 0 ? '#E7F8F7' : item.status === 1 ? '#D9EBFF' : 'rgba(255, 90, 49, 0.10)', color: item.status === 0 ? '#01B6AD' : item.status === 1 ? '#1185FF' : '#FF5A31' }">{{item.status === 0 ? '空闲' : item.status === 1 ? '骑行中' : '禁用'}}</view>
                    </view>
                </view>
                <view class="list_item_infos">
                    <view class="list_item_infos_row">
                        <view class="list_item_infos_row_label">车辆类型:</view>
                        <view class="list_item_infos_row_val">{{item.type === 1 ? '电车' : '自行车'}}</view>
                    </view>
                    <view class="list_item_infos_row">
                        <view class="list_item_infos_row_label">运营情况:</view>
                        <view class="list_item_infos_row_val">{{item.bikeStatus === 1 ? '运营中' : '已停运'}}</view>
                    </view>
                    <view class="list_item_infos_row">
                        <view class="list_item_infos_row_label">电压电量:</view>
                        <view class="list_item_infos_row_val">{{item.voltage}}V</view>
                    </view>
                    <view class="list_item_infos_row">
                        <view class="list_item_infos_row_label">当前站点:</view>
                        <view class="list_item_infos_row_val">{{item.siteName}}</view>
                    </view>
                    <view class="list_item_infos_row">
                        <view class="list_item_infos_row_label">最后通讯:</view>
                        <view class="list_item_infos_row_val">{{item.heartDate}}</view>
                    </view>
                </view>
                <view class="list_item_x"></view>
                <view class="list_item_btns">
                    <image :src="selectIds.includes(item.id) ? '/static/icon/list_checkbox_sel@2x.png' : '/static/icon/list_checkbox@2x.png'" mode="widthFix" @click="seleRow(index)"></image>
                    <view class="list_item_btns_list">
                        <view class="list_item_btns_list_item" @click="openMap(item)">地图</view>
                        <view class="list_item_btns_list_item" @click="bikeChangeStatus(item.id, item.bikeStatus, index)">{{item.bikeStatus === 0 ? '上架' : '下架'}}</view>
                        <view class="list_item_btns_list_item active" @click="bikeChangeLockStatus(item.id, item.lockStatus, index)">{{item.lockStatus === 0 ? '开锁' : '关锁'}}</view>
                    </view>
                </view>
            </view>
            <view class="list_wu" v-if="!next">没有更多数据了~</view>
        </view>
        <view style="width: 100%; height: calc(env(safe-area-inset-bottom) + 130rpx);"></view>
        <view class="footer">
            <view class="footer_hz">
                <view class="footer_hz_left" @click="quanxuan">
                    <image :src="selectAll ? '/static/icon/list_checkbox_sel@2x.png' : '/static/icon/list_checkbox@2x.png'" mode="widthFix"></image>
                    <text>全选</text>
                </view>
                <view class="footer_hz_btn" @click="show1 = true">批量操作</view>
            </view>
            <view style="width: 100%; height: env(safe-area-inset-bottom);"></view>
        </view>
        <!-- ç­›é€‰ -->
        <u-popup :show="show" :round="10" mode="bottom">
            <view class="shaixuan">
                <view class="shaixuan_head">
                    <text></text>
                    <text>筛选</text>
                    <image @click="show = false" src="/static/icon/ic_close@2x.png" mode="widthFix"></image>
                </view>
                <view class="shaixuan_item">
                    <view class="shaixuan_item_label">车辆状态</view>
                    <view class="shaixuan_item_val">
                        <view :class="form.isOnline === 1 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.isOnline = 1">在线</view>
                        <view :class="form.isOnline === 0 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.isOnline = 0">离线</view>
                        <view class="shaixuan_item_val_zw"></view>
                    </view>
                </view>
                <view class="shaixuan_item">
                    <view class="shaixuan_item_label">运营状态</view>
                    <view class="shaixuan_item_val">
                        <view :class="form.bikeStatus === 1 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.bikeStatus = 1">运营中</view>
                        <view :class="form.bikeStatus === 0 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.bikeStatus = 0">已停运</view>
                        <view class="shaixuan_item_val_zw"></view>
                    </view>
                </view>
                <view class="shaixuan_item">
                    <view class="shaixuan_item_label">锁头状态</view>
                    <view class="shaixuan_item_val">
                        <view :class="form.lockStatus === 1 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.lockStatus = 1">开锁</view>
                        <view :class="form.lockStatus === 0 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.lockStatus = 0">关锁</view>
                        <view class="shaixuan_item_val_zw"></view>
                    </view>
                </view>
                <view class="shaixuan_item">
                    <view class="shaixuan_item_label">骑行状态</view>
                    <view class="shaixuan_item_val">
                        <view :class="form.status === 1 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.status = 1">骑行中</view>
                        <view :class="form.status === 0 ? 'shaixuan_item_val_row active' : 'shaixuan_item_val_row'" @click="form.status = 0">空闲中</view>
                        <view class="shaixuan_item_val_zw"></view>
                    </view>
                </view>
                 <view class="shaixuan_footer">
                     <view class="shaixuan_footer_btn" @click="show = false">取消</view>
                     <view class="shaixuan_footer_btn1" @click="getList(1)">确定</view>
                 </view>
            </view>
        </u-popup>
        <!-- é€‰æ‹©æ“ä½œ -->
        <u-popup :show="show1" :round="10" mode="bottom">
            <view class="shaixuan">
                <view class="shaixuan_head">
                    <text></text>
                    <text>选择操作</text>
                    <image @click="show1 = false" src="/static/icon/ic_close@2x.png" mode="widthFix"></image>
                </view>
                <view class="shaixuan_row" @click="bikeChangeStatusBatch(0)">
                    <image src="/static/icon/ic_shangjia@2x.png" mode="widthFix"></image>
                    <text>批量上架</text>
                </view>
                <view class="shaixuan_row" @click="bikeChangeStatusBatch(1)">
                    <image src="/static/icon/ic_xiajia@2x.png" mode="widthFix"></image>
                    <text>批量下架</text>
                </view>
                <view class="shaixuan_row" @click="bikeChangeLockStatusBatch(0)">
                    <image src="/static/icon/ic_kaisuo@2x.png" mode="widthFix"></image>
                    <text>批量开锁</text>
                </view>
                <view class="shaixuan_row" @click="bikeChangeLockStatusBatch(1)">
                    <image src="/static/icon/ic_guansuo@2x.png" mode="widthFix"></image>
                    <text>批量关锁</text>
                </view>
            </view>
        </u-popup>
        <!-- æ¸©é¦¨æç¤º -->
        <u-popup :show="show2" :round="10" mode="bottom">
            <view class="shaixuan">
                <view class="shaixuan_head">
                    <text></text>
                    <text>温馨提示</text>
                    <text></text>
                </view>
                <view class="shaixuan_info">确定开始运营选中车辆吗?</view>
                <view class="shaixuan_footer" style="margin-top: 94rpx;">
                    <view class="shaixuan_footer_btn" @click="show2 = false">取消</view>
                    <view class="shaixuan_footer_btn1">确定</view>
                </view>
            </view>
        </u-popup>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                show: false,
                show1: false,
                show2: false,
                page: 1,
                form: {
                    code: '',
                    isOnline: '',
                    status: '',
                    lockStatus: '',
                    bikeStatus: ''
                },
                list: [],
                selectIds: [],
                next: true
            };
        },
        computed: {
            selectAll() {
                return this.selectIds.length === this.list.length
            }
        },
        onLoad() {
            this.getList()
        },
        onReachBottom() {
            this.getList()
        },
        methods: {
            getList(type) {
                if (type === 1) {
                    this.page = 1
                    this.list = []
                    this.show = false
                    this.next = true
                }
                if (!this.next) return;
                uni.showLoading({ title: '加载中' });
                this.$u.api.pageBikes({
                    capacity: 10,
                    page: this.page,
                    model: this.form
                }).then(res => {
                    if (res.code === 200) {
                        uni.hideLoading();
                        this.list.push(...res.data.records)
                        this.page += 1
                        if (Number(res.data.total) === this.list.length) {
                            this.next = false
                        }
                    }
                })
            },
            seleRow(index) {
                if (!this.selectIds.includes(this.list[index].id)) {
                    this.selectIds.push(this.list[index].id)
                } else {
                    this.selectIds.forEach((item, i) => {
                        if (item === this.list[index].id) {
                            this.selectIds.splice(i, 1)
                        }
                    })
                }
            },
            quanxuan() {
                if (this.selectAll) {
                    this.selectIds = []
                } else {
                    this.selectIds = this.list.map(item => item.id)
                }
            },
            openMap(item) {
                uni.openLocation({
                    latitude: item.latitude,
                    longitude: item.longitude,
                    name: item.siteName,
                    success: () => {
                        console.log('打开成功');
                    },
                    fail: () => {
                        console.log('打开失败');
                    }
                });
            },
            bikeChangeStatusBatch(bikeStatus) {
                var that = this;
                uni.showModal({
                    title: '提示',
                    content: `是否确认批量${bikeStatus === 0 ? '上架' : '下架'}车辆`,
                    success: function (res) {
                        if (res.confirm) {
                            that.$u.api.updateBikeStatus({
                                ids: that.selectIds.join(','),
                                bikeStatus: bikeStatus === 0 ? 1 : 0
                            }).then(res => {
                                if (res.code === 200) {
                                    that.show1 = false
                                    that.selectIds = []
                                    that.getList(1)
                                }
                            })
                        } else if (res.cancel) {
                        }
                    }
                });
            },
            bikeChangeStatus(id, bikeStatus, index) {
                var that = this;
                uni.showModal({
                    title: '提示',
                    content: `是否确认${bikeStatus === 0 ? '上架' : '下架'}该车辆`,
                    success: function (res) {
                        if (res.confirm) {
                            that.$u.api.updateBikeStatus({
                                ids: id,
                                bikeStatus: bikeStatus === 0 ? 1 : 0
                            }).then(res => {
                                if (res.code === 200) {
                                    that.getList(1)
                                }
                            })
                        } else if (res.cancel) {
                        }
                    }
                });
            },
            bikeChangeLockStatus(id, lockStatus, index) {
                var that = this;
                uni.showModal({
                    title: '提示',
                    content: `是否确认${lockStatus === 0 ? '开锁' : '关锁'}该车辆`,
                    success: function (res) {
                        if (res.confirm) {
                            that.$u.api.updateLockStatus({
                                ids: id,
                                lockStatus: lockStatus === 0 ? 1 : 0
                            }).then(res => {
                                if (res.code === 200) {
                                    that.getList(1)
                                }
                            })
                        } else if (res.cancel) {
                        }
                    }
                });
            },
            bikeChangeLockStatusBatch(lockStatus) {
                var that = this;
                uni.showModal({
                    title: '提示',
                    content: `是否确认批量${lockStatus === 0 ? '开锁' : '关锁'}车辆`,
                    success: function (res) {
                        if (res.confirm) {
                            that.$u.api.updateLockStatus({
                                ids: that.selectIds.join(','),
                                lockStatus: lockStatus === 0 ? 1 : 0
                            }).then(res => {
                                if (res.code === 200) {
                                    that.show1 = false
                                    that.selectIds = []
                                    that.getList(1)
                                }
                            })
                        } else if (res.cancel) {
                        }
                    }
                });
            }
        }
    }
</script>
<style>
    page {
        background-color: #F7F7F7;
    }
</style>
<style lang="scss" scoped>
    .box {
        width: 100%;
        .shaixuan {
            width: 100%;
            .shaixuan_head {
                padding: 40rpx;
                width: 100%;
                box-sizing: border-box;
                display: flex;
                align-items: center;
                justify-content: space-between;
                text {
                    font-weight: 500;
                    font-size: 32rpx;
                    color: #222222;
                }
                image {
                    width: 32rpx;
                    height: 32rpx;
                }
            }
            .shaixuan_info {
                width: 100%;
                text-align: center;
                font-weight: 400;
                font-size: 30rpx;
                color: #333333;
                margin-top: 76rpx;
            }
            .shaixuan_row {
                width: calc(100% - 60rpx);
                margin: 0 auto;
                height: 88rpx;
                background: rgba(1,182,173,0.14);
                border-radius: 44rpx;
                border: 1rpx solid #01B6AD;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-bottom: 30rpx;
                image {
                    width: 36rpx;
                    height: 36rpx;
                    margin-right: 16rpx;
                }
                text {
                    font-weight: 600;
                    font-size: 32rpx;
                    color: #01B6AD;
                }
            }
            .shaixuan_item {
                width: 100%;
                padding: 0 30rpx;
                box-sizing: border-box;
                display: flex;
                flex-direction: column;
                margin-bottom: 48rpx;
                &:last-child {
                    margin:  0 !important;
                }
                .shaixuan_item_label {
                    font-weight: 500;
                    font-size: 32rpx;
                    color: #111111;
                    margin-bottom: 30rpx;
                }
                .shaixuan_item_val {
                    width: 100%;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    flex-wrap: wrap;
                    .shaixuan_item_val_zw {
                        width: 208rpx;
                        height: 0;
                    }
                    .active {
                        background-color: #01B6AD !important;
                        color: #FFFFFF !important;
                    }
                    .shaixuan_item_val_row {
                        width: 208rpx;
                        height: 72rpx;
                        line-height: 72rpx;
                        text-align: center;
                        background: #F7F7F7;
                        border-radius: 36rpx;
                        font-weight: 400;
                        font-size: 28rpx;
                        color: #333333;
                    }
                }
            }
            .shaixuan_footer {
                width: 100%;
                height: 96rpx;
                padding: 0 20rpx;
                box-sizing: border-box;
                display: flex;
                align-items: center;
                justify-content: space-between;
                margin-top: 60rpx;
                .shaixuan_footer_btn {
                    width: 344rpx;
                    height: 96rpx;
                    line-height: 96rpx;
                    text-align: center;
                    font-weight: 500;
                    font-size: 32rpx;
                    color: #01B6AD;
                    border-radius: 46rpx;
                    border: 1rpx solid #01B6AD;
                }
                .shaixuan_footer_btn1 {
                    width: 344rpx;
                    height: 96rpx;
                    line-height: 96rpx;
                    text-align: center;
                    background: #01B6AD;
                    border-radius: 46rpx;
                    font-weight: 500;
                    font-size: 32rpx;
                    color: #FFFFFF;
                }
            }
        }
        .footer {
            width: 100%;
            position: fixed;
            bottom: 0;
            left: 0;
            z-index: 9;
            padding: 0 30rpx;
            box-sizing: border-box;
            height: calc(100rpx + env(safe-area-inset-bottom));
            background: #FFFFFF;
            box-shadow: 0rpx -2rpx 4rpx 0rpx rgba(0,0,0,0.06);
            .footer_hz {
                width: 100%;
                height: 100rpx;
                display: flex;
                align-items: center;
                justify-content: space-between;
                .footer_hz_left {
                    display: flex;
                    align-items: center;
                    image {
                        width: 40rpx;
                        height: 40rpx;
                        margin-right: 20rpx;
                    }
                    text {
                        font-weight: 400;
                        font-size: 28rpx;
                        color: #333333;
                    }
                }
                .footer_hz_btn {
                    width: 160rpx;
                    height: 68rpx;
                    font-weight: 400;
                    font-size: 28rpx;
                    color: #FFFFFF;
                    line-height: 68rpx;
                    text-align: center;
                    background: #01B6AD;
                    border-radius: 34rpx;
                }
            }
        }
        .search {
            width: 100%;
            height: 96rpx;
            padding: 0 30rpx;
            box-sizing: border-box;
            background: #FFFFFF;
            display: flex;
            align-items: center;
            justify-content: space-between;
            position: sticky;
            top: 0;
            left: 0;
            z-index: 9;
            .search_sou {
                flex: 1;
                height: 72rpx;
                background: #F7F7F7;
                border-radius: 36rpx;
                padding: 0 40rpx;
                box-sizing: border-box;
                display: flex;
                align-items: center;
                image {
                    width: 28rpx;
                    height: 28rpx;
                    flex-shrink: 0;
                    margin-right: 16rpx;
                }
                input {
                    flex: 1;
                    height: 100%;
                    font-weight: 400;
                    font-size: 26rpx;
                    color: #222222;
                }
            }
            .search_shai {
                flex-shrink: 0;
                margin-left: 30rpx;
                display: flex;
                align-items: center;
                text {
                    font-weight: 400;
                    font-size: 28rpx;
                    color: #666666;
                }
                image {
                    width: 28rpx;
                    height: 28rpx;
                }
            }
        }
        .list {
            width: 100%;
            padding: 0 30rpx;
            box-sizing: border-box;
            .list_wu {
                width: 100%;
                text-align: center;
                margin-top: 30rpx;
                font-weight: 400;
                font-size: 26rpx;
                color: #666666;
            }
            .list_item {
                width: 100%;
                background: #FFFFFF;
                border-radius: 20rpx;
                margin-top: 30rpx;
                .list_item_x {
                    width: 100%;
                    height: 1rpx;
                    background-color: #E5E5E5;
                    margin-top: 30rpx;
                }
                .list_item_btns {
                    width: 100%;
                    margin-top: 14rpx;
                    padding: 0 30rpx 18rpx 30rpx;
                    box-sizing: border-box;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    image {
                        width: 40rpx;
                        height: 40rpx;
                        flex-shrink: 0;
                    }
                    .list_item_btns_list {
                        flex: 1;
                        display: flex;
                        align-items: center;
                        justify-content: flex-end;
                        .active {
                            background-color: rgba(1, 182, 173, 1) !important;
                            color: #FFFFFF !important;
                        }
                        .list_item_btns_list_item {
                            width: 120rpx;
                            height: 68rpx;
                            line-height: 68rpx;
                            text-align: center;
                            border-radius: 34rpx;
                            font-weight: 400;
                            font-size: 28rpx;
                            color: #01B6AD;
                            border: 1rpx solid #01B6AD;
                            margin-left: 20rpx;
                        }
                    }
                }
                .list_item_infos {
                    margin-top: 16rpx;
                    padding: 0 30rpx 0 30rpx;
                    box-sizing: border-box;
                    .list_item_infos_row {
                        width: 100%;
                        display: flex;
                        align-items: center;
                        margin-bottom: 20rpx;
                        &:last-child {
                            margin: 0 !important;
                        }
                        .list_item_infos_row_label {
                            flex-shrink: 0;
                            font-weight: 400;
                            font-size: 26rpx;
                            color: #666666;
                        }
                        .list_item_infos_row_val {
                            font-weight: 400;
                            font-size: 26rpx;
                            color: #666666;
                        }
                    }
                }
                .list_item_title {
                    width: 100%;
                    padding: 30rpx 30rpx 0 30rpx;
                    box-sizing: border-box;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    .list_item_title_left {
                        font-weight: 600;
                        font-size: 32rpx;
                        color: #222222;
                    }
                    .list_item_title_cate {
                        display: flex;
                        align-items: center;
                        .list_item_title_cate_row {
                            padding: 6rpx 12rpx;
                            border-radius: 8rpx;
                            font-weight: 400;
                            font-size: 24rpx;
                            background: #E7F8F7;
                            color: #01B6AD;
                            margin-left: 10rpx;
                        }
                    }
                }
            }
        }
    }
</style>
bicycle/pages/operationLogin/operationLogin.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
<template>
    <view class="login">
        <view class="login_title">欢迎登录</view>
        <view class="login_info">滨湖森林公园运营中心</view>
        <view class="login_form">
            <view class="login_form_item">
                <image src="@/static/icon/login_ic_name@2x.png" mode="widthFix"></image>
                <input type="text" v-model="from.account" placeholder="账号" />
            </view>
            <view class="login_form_item">
                <image src="@/static/icon/login_ic_password@2x.png" mode="widthFix"></image>
                <input type="safe-password" v-model="from.password" placeholder="密码" />
            </view>
        </view>
        <view class="login_btn" @click="login">登录</view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                from: {
                    account: '',
                    password: ''
                }
            };
        },
        methods: {
            login() {
                var that = this;
                if (!this.from.account) return uni.showToast({
                    title: '请输入账号',
                    icon: 'none'
                })
                if (!this.from.password) return uni.showToast({
                    title: '请输入密码',
                    icon: 'none'
                })
                uni.showLoading({ title: '加载中' });
                that.$u.api.login({
                    password: that.from.password,
                    username: that.from.account
                }).then(res => {
                    if (res.code === 200) {
                        uni.hideLoading();
                        that.$store.commit('setUserInfo', res.data)
                        uni.navigateTo({
                            url: '/pages/operationsCenter/operationsCenter'
                        })
                    }
                })
            }
        }
    }
</script>
<style lang="scss" scoped>
    .login {
        width: 100vw;
        height: 100vh;
        padding: 80rpx 60rpx;
        box-sizing: border-box;
        background: linear-gradient( 179deg, #E1FBFA 0%, #FBFEFE 17%, #FFFFFF 100%);
        .login_title {
            font-weight: 600;
            font-size: 52rpx;
            color: #333333;
        }
        .login_info {
            font-weight: 400;
            font-size: 28rpx;
            color: #999999;
            margin-top: 16rpx;
        }
        .login_form {
            width: 100%;
            margin-top: 80rpx;
            .login_form_item {
                width: 100%;
                height: 98rpx;
                padding: 0 40rpx;
                box-sizing: border-box;
                background: #F4F9F8;
                border-radius: 50rpx;
                border: 1rpx solid #E4EFED;
                margin-bottom: 40rpx;
                display: flex;
                align-items: center;
                &:last-child {
                    margin: 0 !important;
                }
                image {
                    width: 40rpx;
                    height: 40rpx;
                    margin-right: 24rpx;
                    flex-shrink: 0;
                }
                input {
                    flex: 1;
                    height: 100%;
                    font-weight: 400;
                    font-size: 30rpx;
                    color: #222222;
                }
            }
        }
        .login_btn {
            width: 100%;
            height: 96rpx;
            line-height: 96rpx;
            text-align: center;
            font-weight: 600;
            font-size: 32rpx;
            color: #FFFFFF;
            background: #01B6AD;
            box-shadow: 0rpx 6rpx 16rpx 0rpx rgba(1,182,173,0.24);
            border-radius: 50rpx;
            margin-top: 80rpx;
        }
    }
</style>
bicycle/pages/operationsCenter/operationsCenter.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
<template>
    <view class="login">
        <view class="login_title">欢迎回来,{{userInfo.sysuser.username}}~</view>
        <view class="login_info">{{getWeek()}}</view>
        <view class="login_func" @click="jump">
            <image src="/static/images/home_i1mg_zulingxuzhi@2x.png" mode="widthFix"></image>
        </view>
        <view class="login_btn" @click="logout">退出登录</view>
    </view>
</template>
<script>
    import { mapState } from 'vuex'
    export default {
        computed: {
            ...mapState(['userInfo'])
        },
        data() {
            return {
            };
        },
        methods: {
            jump() {
                uni.navigateTo({
                    url: '/pages/operationList/operationList'
                })
            },
            getWeek() {
                let today = new Date();
                let dayOfWeek = today.getDay();
                let weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
                let weekdayName = weekdays[dayOfWeek];
                const date = new Date();
                const month = date.getMonth() + 1;
                const day = date.getDate();
                return month + '月' + day + '日' + ',' + weekdayName;
            },
            logout() {
                uni.showLoading({ title: '加载中' });
                this.$u.api.logout()
                    .then(res => {
                        if (res.code === 200) {
                            uni.hideLoading();
                            this.$store.commit('setUserInfo', res.data)
                            uni.navigateBack({ delta: 1 });
                        }
                    })
            }
        }
    }
</script>
<style lang="scss" scoped>
    .login {
        width: 100vw;
        height: 100vh;
        padding: 40rpx 30rpx;
        box-sizing: border-box;
        background: #ffffff;
        .login_title {
            font-weight: 600;
            font-size: 40rpx;
            color: #333333;
        }
        .login_info {
            font-weight: 400;
            font-size: 28rpx;
            color: #999999;
            margin-top: 16rpx;
        }
        .login_func {
            width: 100%;
            height: 182rpx;
            margin-top: 40rpx;
            image {
                width: 100%;
                height: 100%;
            }
        }
        .login_btn {
            width: 200rpx;
            height: 72rpx;
            line-height: 72rpx;
            text-align: center;
            border-radius: 36rpx;
            border: 1rpx solid #01B6AD;
            font-weight: 400;
            font-size: 28rpx;
            color: #01B6AD;
            position: fixed;
            bottom: calc(env(safe-area-inset-bottom) + 30rpx);
            left: 50%;
            transform: translate(-50%, 0);
        }
    }
</style>
bicycle/static/icon/home_ic_mingxi.png
bicycle/static/icon/ic_close@2x.png
bicycle/static/icon/ic_guansuo@2x.png
bicycle/static/icon/ic_kaisuo@2x.png
bicycle/static/icon/ic_search@2x.png
bicycle/static/icon/ic_shaixuan@2x.png
bicycle/static/icon/ic_shangjia@2x.png
bicycle/static/icon/ic_xiajia@2x.png
bicycle/static/icon/list_checkbox@2x.png
bicycle/static/icon/list_checkbox_sel@2x.png
bicycle/static/icon/login_ic_name@2x.png
bicycle/static/icon/login_ic_password@2x.png
bicycle/static/images/home_i1mg_zulingxuzhi@2x.png
bicycle/unpackage/dist/dev/mp-weixin/app.json
@@ -12,7 +12,10 @@
    "pages/leaseNotice/leaseNotice",
    "pages/setMenu/setMenu",
    "pages/packageDetails/packageDetails",
    "pages/paymentPage/paymentPage"
    "pages/paymentPage/paymentPage",
    "pages/operationLogin/operationLogin",
    "pages/operationsCenter/operationsCenter",
    "pages/operationList/operationList"
  ],
  "subPackages": [],
  "window": {
bicycle/unpackage/dist/dev/mp-weixin/common/main.js
@@ -31,9 +31,9 @@
_vue.default.prototype.$onLaunched = new Promise(function (resolve) {
  _vue.default.prototype.$isResolve = resolve;
});
// Vue.prototype.$baseUrl = 'http://192.168.0.129:10025/'
_vue.default.prototype.$baseUrl = 'https://dmtest.ahapp.net/bike_h5_api/';
_vue.default.prototype.$baseUrl = 'http://192.168.1.46:10025/';
// Vue.prototype.$baseUrl = 'https://bikes.yxbhlt.cn/bike_h5_api/'
// Vue.prototype.$baseUrl = 'https://dmtest.ahapp.net/bike_h5_api/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu2.natapp1.cc/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu.natapp1.cc/'
// Vue.prototype.$baseUrl = 'http://xiaopiqiu3.natapp1.cc/'
bicycle/unpackage/dist/dev/mp-weixin/pages/index/index.wxml
@@ -1 +1 @@
<view class="index data-v-57280228"><view class="index_nav data-v-57280228" style="{{'height:'+('calc('+(statusbarHeight+navHeight)+'px'+' + '+'224rpx'+')')+';'}}"><view class="index_nav_a data-v-57280228" style="{{'height:'+(statusbarHeight+'px')+';'}}"></view><view style="{{'height:'+(navHeight+'px')+';'}}" class="data-v-57280228"></view><view class="index_nav_box data-v-57280228" style="{{'background:'+(top>0?'#9AE2DF':'rgba(0,0,0,0)')+';'}}"><view class="index_nav_a data-v-57280228" style="{{'height:'+(statusbarHeight+'px')+';'}}"></view><view style="{{'height:'+(navHeight+'px')+';'}}" class="data-v-57280228"></view><view class="index_nav_b data-v-57280228" style="{{'height:'+(navHeight+'px')+';'+('line-height:'+(navHeight+'px')+';')+('top:'+(statusbarHeight+'px')+';')}}"><text class="data-v-57280228">印象滨湖趣味自行车</text></view></view><view class="index_box data-v-57280228"><view class="index_box_map data-v-57280228"><map class="map data-v-57280228" id="mapId" scale="15" show-location="{{true}}" polygons="{{eleBusinessArea}}" markers="{{markers}}" latitude="{{latitude}}" longitude="{{longitude}}"></map><view class="index_box_map_type data-v-57280228"><block wx:for="{{types}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view data-event-opts="{{[['tap',[['clickType',['$0'],[[['types','',index,'id']]]]]]]}}" class="{{['data-v-57280228',type===item.id?'index_box_map_type_row active':'index_box_map_type_row']}}" bindtap="__e">{{item.name}}</view></block></view><view data-event-opts="{{[['tap',[['jumpMap',['$event']]]]]}}" class="index_box_icon data-v-57280228" bindtap="__e"><image src="/static/icon/ic_fullscreen@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><view class="index_box_title data-v-57280228"><view class="index_box_title_left data-v-57280228"><text class="data-v-57280228">{{info.parkName}}</text><text class="data-v-57280228">{{"服务电话:"+info.serverPhone}}</text></view><image src="/static/icon/ic_call@2x.png" mode="widthFix" data-event-opts="{{[['tap',[['calling',['$0'],['info.serverPhone']]]]]}}" bindtap="__e" class="data-v-57280228"></image></view><view class="index_box_function data-v-57280228"><block wx:for="{{functionList}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view data-event-opts="{{[['tap',[['jump',['$0'],[[['functionList','',index]]]]]]]}}" class="cXYC data-v-57280228" catchtap="__e"><block wx:if="{{!userInfo.mobile}}"><button open-type="getPhoneNumber" data-event-opts="{{[['getphonenumber',[['getPhone',['$event']]]]]}}" bindgetphonenumber="__e" class="data-v-57280228"></button></block><image class="img80 data-v-57280228" src="{{item.icon}}" mode="widthFix"></image><text class="f26 c3 mt10 data-v-57280228">{{item.name}}</text></view></block></view><view class="index_box_vip data-v-57280228"><view class="index_box_vip_head data-v-57280228"><text class="data-v-57280228">热销套餐</text><text data-event-opts="{{[['tap',[['jumpTC',['$event']]]]]}}" bindtap="__e" class="data-v-57280228">更多优惠 ></text></view><scroll-view class="scrollView data-v-57280228" scroll-x="{{true}}"><block wx:for="{{tcList}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view class="index_box_vip_row data-v-57280228"><view class="vip1 data-v-57280228"><view class="vip1_left data-v-57280228">{{''+(item.name||'')+''}}</view><view class="vip1_right data-v-57280228">{{''+(item.price||'')+''}}</view></view><view class="vip2 data-v-57280228"><text class="data-v-57280228">{{item.descs||''}}</text><view class="_u data-v-57280228">{{"Â¥"+(item.linePrice||'')}}</view></view><view class="vip3 data-v-57280228"><view class="vip3_info data-v-57280228">{{"低至"+item.dayPrice+"元/天"}}</view><view data-event-opts="{{[['tap',[['purchase',['$0'],[[['tcList','',index,'id']]]]]]]}}" class="vip3_button data-v-57280228" bindtap="__e">è´­ä¹°</view></view></view></block></scroll-view></view><view data-event-opts="{{[['tap',[['jumpX',['$event']]]]]}}" class="index_box_poster data-v-57280228" bindtap="__e"><image class="imgfull data-v-57280228" src="{{info.leaseNoticeUrl}}" mode="widthFix"></image></view><block wx:if="{{info.leaseVideoUrl}}"><view class="index_box_video data-v-57280228"><video class="img100b data-v-57280228" src="{{info.leaseVideoUrl}}" enable-danmu="{{true}}" danmu-btn="{{true}}" controls="{{true}}"></video></view></block><block wx:if="{{info.memberRidesResponse&&info.memberRidesResponse.ridesType===0}}"><block wx:if="{{show5}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 600rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show6}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show2}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show1}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 580rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show3}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 500rpx);" class="data-v-57280228"></view></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block></block></block></block></block><block wx:else><block wx:if="{{info.memberRidesResponse&&info.memberRidesResponse.ridesType===1}}"><block wx:if="{{$refs.d_tram.d_show3||$refs.d_tram.d_show4}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block></view></view><view class="index_scancode data-v-57280228"><view class="index_scancode_top data-v-57280228"><view class="index_scancode_top_left data-v-57280228"><text class="data-v-57280228">遵守交规,安全骑行</text><text class="data-v-57280228">骑行时请遵守交通规则,安全骑行</text></view><image src="/static/images/ic_safe@2x.png" mode="widthFix" class="data-v-57280228"></image></view><block wx:if="{{!userInfo.mobile}}"><button class="index_scancode_bottom data-v-57280228" open-type="getPhoneNumber" data-event-opts="{{[['getphonenumber',[['getPhone',['$event']]]]]}}" bindgetphonenumber="__e">扫码租车</button></block><block wx:else><view data-event-opts="{{[['tap',[['carRental',['$event']]]]]}}" class="index_scancode_bottom data-v-57280228" bindtap="__e">扫码租车</view></block><view class="index_scancode_zw data-v-57280228"></view></view><u-popup vue-id="8dd740cc-1" show="{{show1}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e0']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="deposit data-v-57280228"><view class="deposit_text data-v-57280228"><text class="data-v-57280228">温馨提示</text><text class="data-v-57280228">{{"骑行需要缴纳"+$root.g0+"元自行车押金"}}</text><text class="data-v-57280228">(押金随时可退)</text></view><view data-event-opts="{{[['tap',[['e1',['$event']]]]]}}" class="deposit_read data-v-57280228" bindtap="__e"><block wx:if="{{!active}}"><image src="/static/icon/ic_select@2x.png" mode="widthFix" class="data-v-57280228"></image></block><block wx:else><image src="/static/icon/ic_selected@2x.png" mode="widthFix" class="data-v-57280228"></image></block><view class="deposit_read_z data-v-57280228">我已阅读<text data-event-opts="{{[['tap',[['jumpX',['$event']]]]]}}" catchtap="__e" class="data-v-57280228">《租赁须知》</text>和<text data-event-opts="{{[['tap',[['jumpgz',['$event']]]]]}}" catchtap="__e" class="data-v-57280228">《计价规则》</text></view></view><view class="deposit_footer data-v-57280228"><view data-event-opts="{{[['tap',[['e2',['$event']]]]]}}" class="deposit_footer_item data-v-57280228" bindtap="__e">返回</view><view data-event-opts="{{[['tap',[['depositPayment',['$event']]]]]}}" class="deposit_footer_item c data-v-57280228" bindtap="__e">充值</view></view></view></u-popup><u-popup vue-id="8dd740cc-2" show="{{show5}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e3']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="loading data-v-57280228"><view class="loading_box data-v-57280228"><view class="loading_box_top data-v-57280228"><image src="/static/icon/ic_loading.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">开锁中</text></view><view class="loading_box_info data-v-57280228">请按照交规行驶</view></view></view></u-popup><u-popup vue-id="8dd740cc-3" show="{{show2}}" overlay="{{false}}" overlayOpacity="0" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e4']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="ride data-v-57280228"><view class="ride_head data-v-57280228"><view class="ride_head_item option data-v-57280228"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view><view class="ride_head_center data-v-57280228"><image src="/static/icon/ic_riding@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">骑行中</text></view><view data-event-opts="{{[['tap',[['toRidingDetails']]]]}}" class="ride_head_item data-v-57280228" bindtap="__e"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><block wx:if="{{info&&info.memberRidesResponse&&info.memberRidesResponse.discountMember}}"><view class="info_des_tc data-v-57280228"><u-icon vue-id="{{('8dd740cc-4')+','+('8dd740cc-3')}}" name="info-circle" color="#FF5A31" size="18" class="data-v-57280228" bind:__l="__l"></u-icon><block wx:if="{{info.memberRidesResponse.discountMember.limitType===0}}"><text class="data-v-57280228">您有骑行套餐,本次行程免费骑行</text></block><block wx:if="{{info.memberRidesResponse.discountMember.limitType===1}}"><text class="data-v-57280228">{{"您已购买骑行套餐,本次行程免费骑行"+$root.m0+"~"}}</text></block></view></block><block wx:if="{{info.memberRidesResponse}}"><view class="ride_content data-v-57280228"><view class="ride_content_a data-v-57280228"><text class="data-v-57280228">{{"开始时间:"+info.memberRidesResponse.rideStartTimeStr}}</text><text class="data-v-57280228">{{"本次已骑行:"+info.memberRidesResponse.rideTime+"分钟"}}</text></view><view class="ride_content_b data-v-57280228"><text class="data-v-57280228">{{"车型:"+info.memberRidesResponse.bikeType+"(编号:"+info.memberRidesResponse.bikeCode+")"}}</text><text class="data-v-57280228">{{info.memberRidesResponse.priceRole}}</text></view><view class="ride_content_info data-v-57280228"><image src="/static/icon/ic_tip@2x.png" mode="widthFix" class="data-v-57280228"></image><block wx:if="{{info.tips}}"><text class="data-v-57280228">{{info.tips}}</text></block></view></view></block><view data-event-opts="{{[['tap',[['navigationReturn',['$event']]]]]}}" class="ride_btn data-v-57280228" bindtap="__e">导航至园区站还车点</view><view data-event-opts="{{[['tap',[['toFaultReporting',['$event']]]]]}}" class="ride_err data-v-57280228" bindtap="__e"><image src="/static/icon/ic_guzhang@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">车辆故障上报</text></view></view></u-popup><u-popup vue-id="8dd740cc-5" show="{{show6}}" overlay="{{false}}" overlayOpacity="0" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e5']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="ride data-v-57280228"><view class="ride_head data-v-57280228"><view class="ride_head_item option data-v-57280228"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view><view class="ride_head_center data-v-57280228"><image src="/static/icon/ic_riding@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">已还车</text></view><view data-event-opts="{{[['tap',[['toRidingDetails']]]]}}" class="ride_head_item data-v-57280228" bindtap="__e"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><block wx:if="{{info&&info.memberRidesResponse&&info.memberRidesResponse.discountMember}}"><view class="info_des_tc data-v-57280228"><u-icon vue-id="{{('8dd740cc-6')+','+('8dd740cc-5')}}" name="info-circle" color="#FF5A31" size="18" class="data-v-57280228" bind:__l="__l"></u-icon><block wx:if="{{info.memberRidesResponse.discountMember.limitType===0}}"><text class="data-v-57280228">您有骑行套餐,本次行程免费骑行</text></block><block wx:if="{{info.memberRidesResponse.discountMember.limitType===1}}"><text class="data-v-57280228">{{"您已购买骑行套餐,本次行程免费骑行"+$root.m1+"~"}}</text></block></view></block><block wx:if="{{info.memberRidesResponse}}"><view class="ride_content data-v-57280228"><view class="ride_content_a data-v-57280228"><text class="data-v-57280228">{{"最后骑行:"+info.memberRidesResponse.rideStartTimeStr+"~"+info.memberRidesResponse.rideEndTimeStr+"("+info.memberRidesResponse.rideTime+"分钟)"}}</text></view><view class="ride_content_b data-v-57280228"><text class="data-v-57280228">{{"车型:"+info.memberRidesResponse.bikeType+"(编号:"+info.memberRidesResponse.bikeCode+")"}}</text><text class="data-v-57280228">{{info.memberRidesResponse.priceRole}}</text></view><view class="ride_content_info data-v-57280228"><image src="/static/icon/ic_tip@2x.png" mode="widthFix" class="data-v-57280228"></image><block wx:if="{{info.tips}}"><text class="data-v-57280228">{{info.tips}}</text></block></view></view></block><view data-event-opts="{{[['tap',[['carRental',['$event']]]]]}}" class="ride_btn data-v-57280228" bindtap="__e">扫码继续骑行</view><view data-event-opts="{{[['tap',[['settlement',['$event']]]]]}}" class="ride_settlement data-v-57280228" bindtap="__e">结束骑行,结算退押金</view></view></u-popup><u-popup vue-id="8dd740cc-7" show="{{show3}}" overlay="{{false}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e6']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="deposit1 data-v-57280228"><view class="deposit_text data-v-57280228"><text class="data-v-57280228">温馨提示</text><text class="red data-v-57280228">结算后,如果继续骑行会重新开始计费</text><text class="red data-v-57280228">确认结算么?</text></view><view class="deposit_footer data-v-57280228"><view data-event-opts="{{[['tap',[['minute',['$event']]]]]}}" class="deposit_footer_item data-v-57280228" bindtap="__e">再等等</view><view data-event-opts="{{[['tap',[['settlement1',['$event']]]]]}}" class="deposit_footer_item c data-v-57280228" bindtap="__e">立即结算</view></view></view></u-popup><u-modal vue-id="8dd740cc-8" show="{{show4}}" title="{{title}}" content="{{content}}" confirmColor="#01B6AD" data-event-opts="{{[['^confirm',[['e7']]]]}}" bind:confirm="__e" class="data-v-57280228" bind:__l="__l"></u-modal><u-modal vue-id="8dd740cc-9" show="{{show7}}" title="提示" content="确认结算吗?" showCancelButton="{{true}}" cancelText="取消" data-event-opts="{{[['^confirm',[['settlement1']]],['^cancel',[['e8']]]]}}" bind:confirm="__e" bind:cancel="__e" class="data-v-57280228" bind:__l="__l"></u-modal><u-popup vue-id="8dd740cc-10" show="{{show}}" mode="center" overlayStyle="{{({zIndex:'99999'})}}" closeOnClickOverlay="{{false}}" zIndex="99999" bgColor="transparent" round="{{10}}" data-event-opts="{{[['^close',[['e9']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="popupbox data-v-57280228"><view class="advertisement data-v-57280228"><image src="{{info.adList[0].imgfullurl}}" mode="widthFix" class="data-v-57280228"></image></view><image class="close data-v-57280228" src="/static/images/ic_close@2x.png" mode="widthFix" data-event-opts="{{[['tap',[['e10',['$event']]]]]}}" bindtap="__e"></image></view></u-popup><tram bind:unlockDoor="__e" vue-id="8dd740cc-11" data-ref="d_tram" data-event-opts="{{[['^unlockDoor',[['refresh',['tram']]]]]}}" class="data-v-57280228 vue-ref" bind:__l="__l"></tram></view>
<view class="index data-v-57280228"><view class="index_nav data-v-57280228" style="{{'height:'+('calc('+(statusbarHeight+navHeight)+'px'+' + '+'224rpx'+')')+';'}}"><view class="index_nav_a data-v-57280228" style="{{'height:'+(statusbarHeight+'px')+';'}}"></view><view style="{{'height:'+(navHeight+'px')+';'}}" class="data-v-57280228"></view><view class="index_nav_box data-v-57280228" style="{{'background:'+(top>0?'#9AE2DF':'rgba(0,0,0,0)')+';'}}"><view class="index_nav_a data-v-57280228" style="{{'height:'+(statusbarHeight+'px')+';'}}"></view><view style="{{'height:'+(navHeight+'px')+';'}}" class="data-v-57280228"></view><view class="index_nav_b data-v-57280228" style="{{'height:'+(navHeight+'px')+';'+('line-height:'+(navHeight+'px')+';')+('top:'+(statusbarHeight+'px')+';')}}"><text class="data-v-57280228">印象滨湖趣味自行车</text></view></view><view class="index_box data-v-57280228"><view class="index_box_map data-v-57280228"><map class="map data-v-57280228" id="mapId" scale="15" show-location="{{true}}" polygons="{{eleBusinessArea}}" markers="{{markers}}" latitude="{{latitude}}" longitude="{{longitude}}"></map><view class="index_box_map_type data-v-57280228"><block wx:for="{{types}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view data-event-opts="{{[['tap',[['clickType',['$0'],[[['types','',index,'id']]]]]]]}}" class="{{['data-v-57280228',type===item.id?'index_box_map_type_row active':'index_box_map_type_row']}}" bindtap="__e">{{item.name}}</view></block></view><view data-event-opts="{{[['tap',[['jumpMap',['$event']]]]]}}" class="index_box_icon data-v-57280228" bindtap="__e"><image src="/static/icon/ic_fullscreen@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><view class="index_box_title data-v-57280228"><view class="index_box_title_left data-v-57280228"><text class="data-v-57280228">{{info.parkName}}</text><text class="data-v-57280228">{{"服务电话:"+info.serverPhone}}</text></view><image src="/static/icon/ic_call@2x.png" mode="widthFix" data-event-opts="{{[['tap',[['calling',['$0'],['info.serverPhone']]]]]}}" bindtap="__e" class="data-v-57280228"></image></view><view class="index_box_function data-v-57280228"><block wx:for="{{functionList}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view data-event-opts="{{[['tap',[['jump',['$0'],[[['functionList','',index]]]]]]]}}" class="cXYC data-v-57280228" style="{{'margin-top:'+(item.id===5?'30rpx':'')+';'}}" catchtap="__e"><block wx:if="{{!userInfo.mobile}}"><button open-type="getPhoneNumber" data-event-opts="{{[['getphonenumber',[['getPhone',['$event']]]]]}}" bindgetphonenumber="__e" class="data-v-57280228"></button></block><image class="img80 data-v-57280228" src="{{item.icon}}" mode="widthFix"></image><text class="f26 c3 mt10 data-v-57280228">{{item.name}}</text></view></block></view><view class="index_box_vip data-v-57280228"><view class="index_box_vip_head data-v-57280228"><text class="data-v-57280228">热销套餐</text><text data-event-opts="{{[['tap',[['jumpTC',['$event']]]]]}}" bindtap="__e" class="data-v-57280228">更多优惠 ></text></view><scroll-view class="scrollView data-v-57280228" scroll-x="{{true}}"><block wx:for="{{tcList}}" wx:for-item="item" wx:for-index="index" wx:key="index"><view class="index_box_vip_row data-v-57280228"><view class="vip1 data-v-57280228"><view class="vip1_left data-v-57280228">{{''+(item.name||'')+''}}</view><view class="vip1_right data-v-57280228">{{''+(item.price||'')+''}}</view></view><view class="vip2 data-v-57280228"><text class="data-v-57280228">{{item.descs||''}}</text><view class="_u data-v-57280228">{{"Â¥"+(item.linePrice||'')}}</view></view><view class="vip3 data-v-57280228"><view class="vip3_info data-v-57280228">{{"低至"+item.dayPrice+"元/天"}}</view><view data-event-opts="{{[['tap',[['purchase',['$0'],[[['tcList','',index,'id']]]]]]]}}" class="vip3_button data-v-57280228" bindtap="__e">è´­ä¹°</view></view></view></block></scroll-view></view><view data-event-opts="{{[['tap',[['jumpX',['$event']]]]]}}" class="index_box_poster data-v-57280228" bindtap="__e"><image class="imgfull data-v-57280228" src="{{info.leaseNoticeUrl}}" mode="widthFix"></image></view><block wx:if="{{info.leaseVideoUrl}}"><view class="index_box_video data-v-57280228"><video class="img100b data-v-57280228" src="{{info.leaseVideoUrl}}" enable-danmu="{{true}}" danmu-btn="{{true}}" controls="{{true}}"></video></view></block><block wx:if="{{info.memberRidesResponse&&info.memberRidesResponse.ridesType===0}}"><block wx:if="{{show5}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 600rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show6}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show2}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show1}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 580rpx);" class="data-v-57280228"></view></block><block wx:else><block wx:if="{{show3}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 500rpx);" class="data-v-57280228"></view></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block></block></block></block></block><block wx:else><block wx:if="{{info.memberRidesResponse&&info.memberRidesResponse.ridesType===1}}"><block wx:if="{{$refs.d_tram.d_show3||$refs.d_tram.d_show4}}"><view style="width:100%;height:calc(env(safe-area-inset-bottom) + 660rpx);" class="data-v-57280228"></view></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block><block wx:else><view class="index_zw1 data-v-57280228"></view></block></block></view></view><view class="index_scancode data-v-57280228"><view class="index_scancode_top data-v-57280228"><view class="index_scancode_top_left data-v-57280228"><text class="data-v-57280228">遵守交规,安全骑行</text><text class="data-v-57280228">骑行时请遵守交通规则,安全骑行</text></view><image src="/static/images/ic_safe@2x.png" mode="widthFix" class="data-v-57280228"></image></view><block wx:if="{{!userInfo.mobile}}"><button class="index_scancode_bottom data-v-57280228" open-type="getPhoneNumber" data-event-opts="{{[['getphonenumber',[['getPhone',['$event']]]]]}}" bindgetphonenumber="__e">扫码租车</button></block><block wx:else><view data-event-opts="{{[['tap',[['carRental',['$event']]]]]}}" class="index_scancode_bottom data-v-57280228" bindtap="__e">扫码租车</view></block><view class="index_scancode_zw data-v-57280228"></view></view><u-popup vue-id="8dd740cc-1" show="{{show1}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e0']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="deposit data-v-57280228"><view class="deposit_text data-v-57280228"><text class="data-v-57280228">温馨提示</text><text class="data-v-57280228">{{"骑行需要缴纳"+$root.g0+"元自行车押金"}}</text><text class="data-v-57280228">(押金随时可退)</text></view><view data-event-opts="{{[['tap',[['e1',['$event']]]]]}}" class="deposit_read data-v-57280228" bindtap="__e"><block wx:if="{{!active}}"><image src="/static/icon/ic_select@2x.png" mode="widthFix" class="data-v-57280228"></image></block><block wx:else><image src="/static/icon/ic_selected@2x.png" mode="widthFix" class="data-v-57280228"></image></block><view class="deposit_read_z data-v-57280228">我已阅读<text data-event-opts="{{[['tap',[['jumpX',['$event']]]]]}}" catchtap="__e" class="data-v-57280228">《租赁须知》</text>和<text data-event-opts="{{[['tap',[['jumpgz',['$event']]]]]}}" catchtap="__e" class="data-v-57280228">《计价规则》</text></view></view><view class="deposit_footer data-v-57280228"><view data-event-opts="{{[['tap',[['e2',['$event']]]]]}}" class="deposit_footer_item data-v-57280228" bindtap="__e">返回</view><view data-event-opts="{{[['tap',[['depositPayment',['$event']]]]]}}" class="deposit_footer_item c data-v-57280228" bindtap="__e">充值</view></view></view></u-popup><u-popup vue-id="8dd740cc-2" show="{{show5}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e3']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="loading data-v-57280228"><view class="loading_box data-v-57280228"><view class="loading_box_top data-v-57280228"><image src="/static/icon/ic_loading.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">开锁中</text></view><view class="loading_box_info data-v-57280228">请按照交规行驶</view></view></view></u-popup><u-popup vue-id="8dd740cc-3" show="{{show2}}" overlay="{{false}}" overlayOpacity="0" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e4']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="ride data-v-57280228"><view class="ride_head data-v-57280228"><view class="ride_head_item option data-v-57280228"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view><view class="ride_head_center data-v-57280228"><image src="/static/icon/ic_riding@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">骑行中</text></view><view data-event-opts="{{[['tap',[['toRidingDetails']]]]}}" class="ride_head_item data-v-57280228" bindtap="__e"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><block wx:if="{{info&&info.memberRidesResponse&&info.memberRidesResponse.discountMember}}"><view class="info_des_tc data-v-57280228"><u-icon vue-id="{{('8dd740cc-4')+','+('8dd740cc-3')}}" name="info-circle" color="#FF5A31" size="18" class="data-v-57280228" bind:__l="__l"></u-icon><block wx:if="{{info.memberRidesResponse.discountMember.limitType===0}}"><text class="data-v-57280228">您有骑行套餐,本次行程免费骑行</text></block><block wx:if="{{info.memberRidesResponse.discountMember.limitType===1}}"><text class="data-v-57280228">{{"您已购买骑行套餐,本次行程免费骑行"+$root.m0+"~"}}</text></block></view></block><block wx:if="{{info.memberRidesResponse}}"><view class="ride_content data-v-57280228"><view class="ride_content_a data-v-57280228"><text class="data-v-57280228">{{"开始时间:"+info.memberRidesResponse.rideStartTimeStr}}</text><text class="data-v-57280228">{{"本次已骑行:"+info.memberRidesResponse.rideTime+"分钟"}}</text></view><view class="ride_content_b data-v-57280228"><text class="data-v-57280228">{{"车型:"+info.memberRidesResponse.bikeType+"(编号:"+info.memberRidesResponse.bikeCode+")"}}</text><text class="data-v-57280228">{{info.memberRidesResponse.priceRole}}</text></view><view class="ride_content_info data-v-57280228"><image src="/static/icon/ic_tip@2x.png" mode="widthFix" class="data-v-57280228"></image><block wx:if="{{info.tips}}"><text class="data-v-57280228">{{info.tips}}</text></block></view></view></block><view data-event-opts="{{[['tap',[['navigationReturn',['$event']]]]]}}" class="ride_btn data-v-57280228" bindtap="__e">导航至园区站还车点</view><view data-event-opts="{{[['tap',[['toFaultReporting',['$event']]]]]}}" class="ride_err data-v-57280228" bindtap="__e"><image src="/static/icon/ic_guzhang@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">车辆故障上报</text></view></view></u-popup><u-popup vue-id="8dd740cc-5" show="{{show6}}" overlay="{{false}}" overlayOpacity="0" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e5']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="ride data-v-57280228"><view class="ride_head data-v-57280228"><view class="ride_head_item option data-v-57280228"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view><view class="ride_head_center data-v-57280228"><image src="/static/icon/ic_riding@2x.png" mode="widthFix" class="data-v-57280228"></image><text class="data-v-57280228">已还车</text></view><view data-event-opts="{{[['tap',[['toRidingDetails']]]]}}" class="ride_head_item data-v-57280228" bindtap="__e"><text class="data-v-57280228">骑行明细</text><image src="/static/icon/ar_detail@2x.png" mode="widthFix" class="data-v-57280228"></image></view></view><block wx:if="{{info&&info.memberRidesResponse&&info.memberRidesResponse.discountMember}}"><view class="info_des_tc data-v-57280228"><u-icon vue-id="{{('8dd740cc-6')+','+('8dd740cc-5')}}" name="info-circle" color="#FF5A31" size="18" class="data-v-57280228" bind:__l="__l"></u-icon><block wx:if="{{info.memberRidesResponse.discountMember.limitType===0}}"><text class="data-v-57280228">您有骑行套餐,本次行程免费骑行</text></block><block wx:if="{{info.memberRidesResponse.discountMember.limitType===1}}"><text class="data-v-57280228">{{"您已购买骑行套餐,本次行程免费骑行"+$root.m1+"~"}}</text></block></view></block><block wx:if="{{info.memberRidesResponse}}"><view class="ride_content data-v-57280228"><view class="ride_content_a data-v-57280228"><text class="data-v-57280228">{{"最后骑行:"+info.memberRidesResponse.rideStartTimeStr+"~"+info.memberRidesResponse.rideEndTimeStr+"("+info.memberRidesResponse.rideTime+"分钟)"}}</text></view><view class="ride_content_b data-v-57280228"><text class="data-v-57280228">{{"车型:"+info.memberRidesResponse.bikeType+"(编号:"+info.memberRidesResponse.bikeCode+")"}}</text><text class="data-v-57280228">{{info.memberRidesResponse.priceRole}}</text></view><view class="ride_content_info data-v-57280228"><image src="/static/icon/ic_tip@2x.png" mode="widthFix" class="data-v-57280228"></image><block wx:if="{{info.tips}}"><text class="data-v-57280228">{{info.tips}}</text></block></view></view></block><view data-event-opts="{{[['tap',[['carRental',['$event']]]]]}}" class="ride_btn data-v-57280228" bindtap="__e">扫码继续骑行</view><view data-event-opts="{{[['tap',[['settlement',['$event']]]]]}}" class="ride_settlement data-v-57280228" bindtap="__e">结束骑行,结算退押金</view></view></u-popup><u-popup vue-id="8dd740cc-7" show="{{show3}}" overlay="{{false}}" closeOnClickOverlay="{{false}}" mode="bottom" bgColor="#fff" round="{{10}}" data-event-opts="{{[['^close',[['e6']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="deposit1 data-v-57280228"><view class="deposit_text data-v-57280228"><text class="data-v-57280228">温馨提示</text><text class="red data-v-57280228">结算后,如果继续骑行会重新开始计费</text><text class="red data-v-57280228">确认结算么?</text></view><view class="deposit_footer data-v-57280228"><view data-event-opts="{{[['tap',[['minute',['$event']]]]]}}" class="deposit_footer_item data-v-57280228" bindtap="__e">再等等</view><view data-event-opts="{{[['tap',[['settlement1',['$event']]]]]}}" class="deposit_footer_item c data-v-57280228" bindtap="__e">立即结算</view></view></view></u-popup><u-modal vue-id="8dd740cc-8" show="{{show4}}" title="{{title}}" content="{{content}}" confirmColor="#01B6AD" data-event-opts="{{[['^confirm',[['e7']]]]}}" bind:confirm="__e" class="data-v-57280228" bind:__l="__l"></u-modal><u-modal vue-id="8dd740cc-9" show="{{show7}}" title="提示" content="确认结算吗?" showCancelButton="{{true}}" cancelText="取消" data-event-opts="{{[['^confirm',[['settlement1']]],['^cancel',[['e8']]]]}}" bind:confirm="__e" bind:cancel="__e" class="data-v-57280228" bind:__l="__l"></u-modal><u-popup vue-id="8dd740cc-10" show="{{show}}" mode="center" overlayStyle="{{({zIndex:'99999'})}}" closeOnClickOverlay="{{false}}" zIndex="99999" bgColor="transparent" round="{{10}}" data-event-opts="{{[['^close',[['e9']]]]}}" bind:close="__e" class="data-v-57280228" bind:__l="__l" vue-slots="{{['default']}}"><view class="popupbox data-v-57280228"><view class="advertisement data-v-57280228"><image src="{{info.adList[0].imgfullurl}}" mode="widthFix" class="data-v-57280228"></image></view><image class="close data-v-57280228" src="/static/images/ic_close@2x.png" mode="widthFix" data-event-opts="{{[['tap',[['e10',['$event']]]]]}}" bindtap="__e"></image></view></u-popup><tram bind:unlockDoor="__e" vue-id="8dd740cc-11" data-ref="d_tram" data-event-opts="{{[['^unlockDoor',[['refresh',['tram']]]]]}}" class="data-v-57280228 vue-ref" bind:__l="__l"></tram></view>
bicycle/unpackage/dist/dev/mp-weixin/pages/index/index.wxss
@@ -169,6 +169,7 @@
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  position: relative;
  top: -24rpx;
}
@@ -176,6 +177,7 @@
  font-weight: 400;
}
.index .index_nav .index_box .index_box_function .cXYC.data-v-57280228 {
  width: 23%;
  position: relative;
}
.index .index_nav .index_box .index_box_function .cXYC button.data-v-57280228 {
bicycle/unpackage/dist/dev/mp-weixin/project.private.config.json
@@ -3,5 +3,32 @@
  "projectname": "bicycle",
  "setting": {
    "compileHotReLoad": true
  },
  "condition": {
    "miniprogram": {
      "list": [
        {
          "name": "运营中心列表",
          "pathName": "pages/operationList/operationList",
          "query": "",
          "scene": null,
          "launchMode": "default"
        },
        {
          "name": "运营中心",
          "pathName": "pages/operationsCenter/operationsCenter",
          "query": "",
          "launchMode": "default",
          "scene": null
        },
        {
          "name": "运营中心登录",
          "pathName": "pages/operationLogin/operationLogin",
          "query": "",
          "launchMode": "default",
          "scene": null
        }
      ]
    }
  }
}
bicycle/utils/http.api.js
@@ -34,6 +34,11 @@
    let backElecBike = (data = {}) => uni.$u.http.post('web/business/backElecBike', data)    // ç”µè½¦ç«™ç‚¹è¿˜è½¦
    let pauseElecBike = (data = {}) => uni.$u.http.post('web/business/pauseElecBike', data)    // ç”µè½¦ä¸´æ—¶åœè½¦
    let pauseOpenElecBike = (data = {}) => uni.$u.http.post('web/business/pauseOpenElecBike', data)    // ç”µè½¦ä¸´åœå¼€é”
    let login = (data = {}) => uni.$u.http.post('web/manger/login', data)    // ç™»å½•管理员账号
    let logout = (data = {}) => uni.$u.http.post('web/manger/logout', data)    // é€€å‡ºç®¡ç†å‘˜è´¦å·
    let pageBikes = (data = {}) => uni.$u.http.post('web/manger/pageBikes', data)    // åˆ†é¡µæŸ¥è¯¢ç”µè½¦åˆ—表
    let updateBikeStatus = (params = {}) => uni.$u.http.get('web/manger/updateBikeStatus/batch', { params })    // ç”µè½¦æ‰¹é‡ä¸Šä¸‹æž¶
    let updateLockStatus = (params = {}) => uni.$u.http.get('web/manger/updateLockStatus/batch', { params })    // ç”µè½¦æ‰¹é‡å¼€å…³é”
    vm.$u.api = {
@@ -63,7 +68,12 @@
        openElecBike,
        backElecBike,
        pauseElecBike,
        pauseOpenElecBike
        pauseOpenElecBike,
        login,
        logout,
        pageBikes,
        updateBikeStatus,
        updateLockStatus
    };
}
server/platform/src/main/java/com/doumee/api/business/GoodsorderController.java
@@ -10,6 +10,7 @@
import com.doumee.core.utils.DateUtil;
import com.doumee.dao.business.model.Goodsorder;
import com.doumee.dao.business.model.WxBillDetail;
import com.doumee.dao.business.vo.BikeIncomeReportVO;
import com.doumee.dao.business.vo.DiscountGoodsorderExportVO;
import com.doumee.dao.business.vo.GoodsorderExportVO;
import com.doumee.dao.business.vo.GoodsorderTotalDataVO;
@@ -31,6 +32,7 @@
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@@ -94,6 +96,7 @@
        return ApiResponse.success(goodsorderService.findPage(pageWrap));
    }
    @ApiOperation("线上交易汇总数据接口")
    @PostMapping("/getTotalData")
    @RequiresPermissions("business:goodsorder:query")
@@ -102,6 +105,8 @@
        pageWrap.setEndDate(pageWrap.getEndDate() != null ? pageWrap.getEndDate():pageWrap.getStartDate());
        return ApiResponse.success(goodsorderService.getTotalData(pageWrap));
    }
    @ApiOperation("订单列表-导出Excel")
    @PostMapping("/exportExcel")
@@ -135,6 +140,7 @@
    public ApiResponse<PageData<GoodsorderExportVO>> findPageAccountDetail(@RequestBody PageWrap<Goodsorder> pageWrap) {
            return ApiResponse.success(goodsorderService.findAccountDetailPage(pageWrap));
    }
    @ApiOperation("收款明细(微信对账明细)_导出Excel")
    @PostMapping("/exportAccountDetailExcel")
    @RequiresPermissions("business:goodsorder:exportExcel")
@@ -186,4 +192,19 @@
    public ApiResponse<GoodsorderCanBanlanceDTO> getGoodsorderCanBanlanceDTO(@RequestParam String orderId){
        return ApiResponse.success(goodsorderService.getGoodsorderCanBanlanceDTO(orderId));
    }
    @ApiOperation("车型收入分析")
    @PostMapping("/getBikeIncomeReportVOList")
    public ApiResponse<List<List<String>>> getBikeIncomeReportVOList (@RequestBody Goodsorder goodsorder) {
        return ApiResponse.success(goodsorderService.getBikeIncomeReportVOList(goodsorder.getStartDate(),goodsorder.getEndDate()));
    }
    @ApiOperation("车型收入分析-导出Excel")
    @PostMapping("/bikeIncomeExportExcel")
    public void exportExcel (@RequestBody Goodsorder goodsorder, HttpServletResponse response) {
        goodsorderService.excel(goodsorder.getStartDate(),goodsorder.getEndDate(),response);
    }
}
server/services/src/main/java/com/doumee/core/annotation/excel/ExcelExporter.java
@@ -1,5 +1,6 @@
package com.doumee.core.annotation.excel;
import com.doumee.core.constants.Constants;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.dao.business.model.Goodsorder;
@@ -168,6 +169,21 @@
            }
        }
    }
//    public void exportList (List<List<String>> data, String fileName, String sheetName, HttpServletResponse response) {
//        try {
//            String encodeFileName = URLEncoder.encode(fileName, Charset.forName("UTF-8").toString()) + ".xlsx";
//            response.setHeader("Content-Disposition","attachment;filename=" + encodeFileName);
//            response.setContentType("application/octet-stream");
//            response.setHeader("eva-opera-type", "download");
//            response.setHeader("eva-download-filename", encodeFileName);
//            this.exportList(data, sheetName, response.getOutputStream());
//        } catch (IOException e) {
//            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
//        }
//    }
    /**
     * å¯¼å‡ºåˆ°æŒ‡å®šè¾“出流
     * @param os è¾“出流
@@ -181,27 +197,47 @@
            sheet.createFreezePane(0, 1);
            Row header = sheet.createRow(0);
            CellStyle hstyle = configHeaderCellStatic(sxssfWorkbook);
            CellStyle cstyle = configCellStatic(sxssfWorkbook);
            List<String> headerList =dataList.get(0);
            for (int i = 0; i < headerList.size(); i++) {
            for (int i = 0; i < dataList.size(); i++) {
                Cell cell = header.createCell(i);
                cell.setCellValue(headerList.get(i));
                cell.setCellValue(dataList.get(i).get(Constants.ZERO));
                // åˆ—宽设置
                sheet.setColumnWidth(i, headerList.get(i).length() * 2 * 256);
                sheet.setColumnWidth(i, dataList.get(i).get(Constants.ZERO).length() * 2 * 256);
                // è®¾ç½®åˆ—头单元格
                cell.setCellStyle(hstyle);
            }
            // åˆ›å»ºæ•°æ®è®°å½•
            for (int rowIndex = 1; rowIndex < dataList.size(); rowIndex++) {
                Row row = sheet.createRow(rowIndex );
                List<String> rowList = dataList.get(rowIndex);
                for (int i = 0; i < rowList.size(); i++) {
                    Cell cell = row.createCell(i);
                    cell.setCellValue(rowList.get(i));
                    // åˆ—宽设置
                    cell.setCellStyle(cstyle);
            //总行数
            Integer rowSize = dataList.get(Constants.ZERO).size();
            //总列数
            Integer columnSize = dataList.size();
            for (int i = 1; i < rowSize; i++) {
                Row row = sheet.createRow(i);
                for (int j = 0; j < columnSize; j++) {
                    Cell cell = row.createCell(j);
                    cell.setCellValue(dataList.get(j).get(i));
                }
            }
//
//            List<String> headerList =dataList.get(0);
//            for (int i = 0; i < headerList.size(); i++) {
//                Cell cell = header.createCell(i);
//                cell.setCellValue(headerList.get(i));
//                // åˆ—宽设置
//                sheet.setColumnWidth(i, headerList.get(i).length() * 2 * 256);
//                // è®¾ç½®åˆ—头单元格
//                cell.setCellStyle(hstyle);
//            }
//            // åˆ›å»ºæ•°æ®è®°å½•
//            for (int rowIndex = 1; rowIndex < dataList.size(); rowIndex++) {
//                Row row = sheet.createRow(rowIndex );
//                List<String> rowList = dataList.get(rowIndex);
//                for (int i = 0; i < rowList.size(); i++) {
//                    Cell cell = row.createCell(i);
//                    cell.setCellValue(rowList.get(i));
//                    // åˆ—宽设置
//                    cell.setCellStyle(cstyle);
//                }
//            }
            sxssfWorkbook.write(os);
            os.close();
        } catch (Exception e) {
server/services/src/main/java/com/doumee/core/utils/DateUtil.java
@@ -69,6 +69,30 @@
    }
    public static List<Date> getDateList(Date dBegin, Date dEnd) {
        int i = 1;
        //日期工具类准备
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //设置开始时间
        Calendar calBegin = Calendar.getInstance();
        calBegin.setTime(dBegin);
        int weekNumber = calBegin.get(Calendar.DAY_OF_WEEK) - 1;
        //设置结束时间
        Calendar calEnd = Calendar.getInstance();
        calEnd.setTime(dEnd);
        //装返回的日期集合容器
        List<Date> dateList = new ArrayList<Date>();
        dateList.add(dBegin);
        //将第一个月添加里面去
        while (dEnd.after(calBegin.getTime())) {
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            Date date =  calBegin.getTime();
            dateList.add(date);
        }
        return dateList;
    }
    public static Date StringToDateFormat(String DATE,String format) {
        if(StringUtils.isBlank(DATE)){
server/services/src/main/java/com/doumee/dao/business/model/DiscountMember.java
@@ -28,6 +28,7 @@
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ExcelColumn(name="创建时间",index = 8,width = 16,dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date createDate;
    @ApiModelProperty(value = "创建人")
@@ -55,7 +56,7 @@
    private String name;
    @ApiModelProperty(value = "类型 0期限卡 1次卡", example = "1")
    @ExcelColumn(name="套餐类型",index = 1,valueMapping = "0=期限卡;1=次卡;",width = 10)
    @ExcelColumn(name="套餐类型",index = 1,valueMapping = "0=期限卡;1=次卡;",width = 10)
    private Integer type;
    @ApiModelProperty(value = "每日骑行限制类型 0不限制 1限制", example = "1")
@@ -162,4 +163,14 @@
    @ApiModelProperty(value = "操作记录")
    @TableField(exist = false)
    private List<DiscountLog> optLogList;
    @ApiModelProperty(value = "查询开始日期(包含)", example = "2023-10-01 15:12:01")
    @TableField(exist = false)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date startCreateDate;
    @ApiModelProperty(value = "查询截止日期(包含)", example = "2023-10-09 15:12:05")
    @TableField(exist = false)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endCreateDate;
}
server/services/src/main/java/com/doumee/dao/business/model/Goodsorder.java
@@ -103,6 +103,8 @@
    private String closeUserId;
    @ApiModelProperty(value = "结算类型 0用户自行结算 1平台人工强制结算 2系统自动结算")
    private Integer closeType;
    @ApiModelProperty(value = "结算车型编码")
    private String paramId;
    @ApiModelProperty(value = "用户openid" )
    @TableField(exist = false)
    @ExcelColumn(name="用户",index = 1 ,width = 10,align = HorizontalAlignment.CENTER)
@@ -123,11 +125,12 @@
    @ExcelColumn(name="退押金(元)",index = 6,width = 10,align = HorizontalAlignment.CENTER)
    private BigDecimal refundMoney;
    @ApiModelProperty(value = "骑行卡抵扣(分)")
    @ExcelColumn(name="优惠金额",index = 10,width = 10,align = HorizontalAlignment.CENTER)
    @TableField(exist = false)
    private BigDecimal discountMoney;
    @ApiModelProperty(value = "最后退款时间")
    @TableField(exist = false)
    @ExcelColumn(name="退款结算时间",index = 9,width = 10,align = HorizontalAlignment.CENTER,dateFormat = "yyyy-MM-dd HH:mm:ss")
    @ExcelColumn(name="退款时间",index = 9,width = 10,align = HorizontalAlignment.CENTER,dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date refundDate;
    @ApiModelProperty(value = "最近骑行状态")
    @TableField(exist = false)
@@ -137,7 +140,6 @@
    private Integer closeStatus;
    @ApiModelProperty(value = "操作人")
    @ExcelColumn(name="操作人",index = 9,width = 10,align = HorizontalAlignment.CENTER)
    @TableField(exist = false)
    private String refundUserName;
@@ -145,4 +147,9 @@
    @TableField(exist = false)
    private String discountName;
    @ApiModelProperty(value = "骑行类型")
    @ExcelColumn(name="订单类型",index = 11,width = 10,valueMapping = "3=单车类型;4=电车类型;",align = HorizontalAlignment.CENTER)
    @TableField(exist = false)
    private Integer bikeType;
}
server/services/src/main/java/com/doumee/dao/business/vo/BikeIncomeDetailReportVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.doumee.dao.business.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * è®¢å•信息表
 * @author æ±Ÿè¹„蹄
 * @date 2023/09/27 18:06
 */
@Data
@ApiModel("车型收入分析")
public class BikeIncomeDetailReportVO {
    @ApiModelProperty(value = "收入金额")
    private String totalAmount;
    @ApiModelProperty(value = "日期值")
    private String dateStr;
}
server/services/src/main/java/com/doumee/dao/business/vo/BikeIncomeReportVO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.doumee.dao.business.vo;
import com.doumee.core.annotation.excel.ExcelColumn;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
 * è®¢å•信息表
 * @author æ±Ÿè¹„蹄
 * @date 2023/09/27 18:06
 */
@Data
@ApiModel("车型收入分析")
public class BikeIncomeReportVO {
    @ApiModelProperty(value = "车型名称")
    private String paramName;
    @ApiModelProperty(value = "车型主键")
    private String paramId;
//    @ApiModelProperty(value = "行数据收入列表")
//    private List<BikeIncomeDetailReportVO> bikeIncomeDetailReportVOList;
    @ApiModelProperty(value = "行数据收入列表")
    private List<String> dataList;
}
server/services/src/main/java/com/doumee/dao/business/vo/GoodsorderExportVO.java
@@ -57,4 +57,11 @@
    @ExcelColumn(name="退款时间",width = 10,index = 5,align = HorizontalAlignment.CENTER,dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date refundDate;
    @ApiModelProperty(value = "骑行类型")
    @ExcelColumn(name="订单类型",index = 8,width = 10,valueMapping = "1=套餐订单;3=自行车订单;4=电动车订单;",align = HorizontalAlignment.CENTER)
    private Integer bikeType;
    @ApiModelProperty(value = "交易类型 0租车押金 1套餐卡购买")
    private Integer type;
}
server/services/src/main/java/com/doumee/dao/business/web/response/RidesDetailResponse.java
@@ -35,6 +35,9 @@
    @ApiModelProperty(value = "抵扣金额")
    private BigDecimal disCountMoney;
    @ApiModelProperty(value = "车辆类型编码")
    private String paramId;
    @ApiModelProperty(value = "骑行记录")
    private List<MemberRidesResponse> memberRidesResponseList;
server/services/src/main/java/com/doumee/service/business/GoodsorderService.java
@@ -8,6 +8,7 @@
import com.doumee.dao.business.model.DiscountMember;
import com.doumee.dao.business.model.Goodsorder;
import com.doumee.dao.business.model.MemberRides;
import com.doumee.dao.business.vo.BikeIncomeReportVO;
import com.doumee.dao.business.vo.GoodsorderExportVO;
import com.doumee.dao.business.vo.GoodsorderTotalDataVO;
import com.doumee.dao.business.web.request.BackElecBikeRequest;
@@ -20,7 +21,9 @@
import com.wechat.pay.java.service.refund.model.RefundNotification;
import io.swagger.models.auth.In;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
@@ -212,4 +215,8 @@
    DiscountMember getUseDiscount(String memberId, Integer driveTime,Integer type);
    void autCancel();
    List<List<String>> getBikeIncomeReportVOList(Date startDate , Date endDate);
    void excel(Date startDate , Date endDate, HttpServletResponse response);
}
server/services/src/main/java/com/doumee/service/business/impl/DiscountMemberServiceImpl.java
@@ -11,10 +11,7 @@
import com.doumee.dao.business.DiscountLogMapper;
import com.doumee.dao.business.DiscountMemberMapper;
import com.doumee.dao.business.join.DiscountMemberJoinMapper;
import com.doumee.dao.business.model.Discount;
import com.doumee.dao.business.model.DiscountLog;
import com.doumee.dao.business.model.DiscountMember;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.business.model.*;
import com.doumee.dao.business.web.request.DiscountMemberDTO;
import com.doumee.dao.system.model.SystemUser;
import com.doumee.service.business.DiscountMemberService;
@@ -147,6 +144,8 @@
                .like(StringUtils.isNotBlank(model.getName()),DiscountMember::getName,model.getName())
                .like(StringUtils.isNotBlank(model.getOpenid()),Member::getOpenid,model.getOpenid())
                .eq(Objects.nonNull(model.getStatus()),DiscountMember::getStatus,model.getStatus())
                .ge(Objects.nonNull(model.getStartCreateDate()),DiscountMember::getCreateDate, model.getStartCreateDate())
                .le(Objects.nonNull(model.getEndCreateDate()),DiscountMember::getCreateDate, model.getEndCreateDate())
                .ne(DiscountMember::getStatus,Constants.TWO)
                .orderByDesc(DiscountMember::getCode);
        return PageData.from(discountMemberJoinMapper.selectJoinPage(page, DiscountMember.class,queryWrapper));
@@ -249,4 +248,8 @@
        QueryWrapper<DiscountMember> wrapper = new QueryWrapper<>(discountMember);
        return discountMemberMapper.selectCount(wrapper);
    }
}
server/services/src/main/java/com/doumee/service/business/impl/GoodsorderServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.doumee.core.annotation.excel.ExcelExporter;
import com.doumee.core.constants.Constants;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.Constants;
@@ -28,6 +29,8 @@
import com.doumee.dao.business.model.Goodsorder;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.business.model.MemberRides;
import com.doumee.dao.business.vo.BikeIncomeDetailReportVO;
import com.doumee.dao.business.vo.BikeIncomeReportVO;
import com.doumee.dao.business.vo.GoodsorderExportVO;
import com.doumee.dao.business.vo.GoodsorderTotalDataVO;
import com.doumee.dao.business.web.request.*;
@@ -58,10 +61,14 @@
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.sql.Ref;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@@ -199,7 +206,9 @@
            MPJLambdaWrapper<Goodsorder> queryWrapper = new MPJLambdaWrapper<>();
            queryWrapper.selectAll(Goodsorder.class);
            queryWrapper.selectAs(Member::getOpenid, Goodsorder::getOpenid);
            queryWrapper.selectAs(BaseParam::getType, Goodsorder::getBikeType);
            queryWrapper.leftJoin(Member.class, Member::getId  ,Goodsorder::getMemberId);
            queryWrapper.leftJoin(BaseParam.class, BaseParam::getId  ,Goodsorder::getParamId);
            queryWrapper.select("(select max(r.done_date) from refund r where r.obj_id=t.id  and r.status=2 ) as refund_date");
            queryWrapper.select("(select sum(r.money) from refund r where r.obj_id=t.id and r.status=2) as refund_money");
            //时间段筛选
@@ -213,6 +222,9 @@
            queryWrapper.eq(Goodsorder::getPayStatus,Constants.ONE);
            queryWrapper.orderByAsc(Goodsorder::getPayDate);
            goodsorderExportVOIPage = goodsorderJoinMapper.selectJoinPage(page, GoodsorderExportVO.class, queryWrapper);
        }else{
            MPJLambdaWrapper<Refund> queryWrapper = new MPJLambdaWrapper<>();
            queryWrapper.selectAs(Refund::getMoney,GoodsorderExportVO::getRefundMoney);
@@ -240,6 +252,7 @@
        if (!CollectionUtils.isEmpty(goodsorderExportVOIPage.getRecords())){
            goodsorderExportVOIPage.getRecords().forEach(s->{
                s.setBikeType(s.getType()==Constants.ZERO?s.getBikeType():Constants.ONE);
                s.setMoney(Constants.translateMoney(s.getMoney()));
                s.setRefundMoney(Constants.translateMoney(s.getRefundMoney()));
                s.setCloseMoney(Constants.translateMoney(s.getCloseMoney()).compareTo(s.getMoney()) > 0 ? s.getMoney() : Constants.translateMoney(s.getCloseMoney()));
@@ -283,6 +296,7 @@
        }
        if (!CollectionUtils.isEmpty(goodsorderList)){
            goodsorderList.forEach(s->{
                s.setBikeType(s.getType()==Constants.ZERO?s.getBikeType():Constants.ONE);
                s.setMoney(Constants.translateMoney(s.getMoney()));
                s.setCloseMoney(Constants.translateMoney(s.getCloseMoney()).compareTo(s.getMoney()) > 0 ? s.getMoney() : Constants.translateMoney(s.getCloseMoney()));
                s.setRefundMoney(Constants.translateMoney(s.getRefundMoney()));
@@ -296,11 +310,13 @@
        queryWrapper.selectAll(Goodsorder.class);
        queryWrapper.selectAs(Member::getOpenid, Goodsorder::getOpenid);
        queryWrapper.selectAs(DiscountMember::getName, Goodsorder::getDiscountName);
        queryWrapper.selectAs(BaseParam::getType, Goodsorder::getBikeType);
        queryWrapper.leftJoin(Member.class, Member::getId  ,Goodsorder::getMemberId);
        queryWrapper.leftJoin(DiscountMember.class, DiscountMember::getGoodsorderId  ,Goodsorder::getId);
//        queryWrapper.select("(select r.name from discount_member r where r.isdeleted=0  and r.goodsorder_id=t.id limit 1) as discountName");
        queryWrapper.leftJoin(BaseParam.class, BaseParam::getId  ,Goodsorder::getParamId);
        queryWrapper.select("(select max(r.done_date) from refund r where r.obj_id=t.id  and  r.status in(0,2)) as refund_date");
        queryWrapper.select("(select sum(r.money) from refund r where r.obj_id=t.id and r.status in(0,2)) as refund_money");
        queryWrapper.select("(select  sum(d.ride_price)  from discount_log d where d.goodsorder_id=t.id and d.type = 0) as discountMoney");
        //时间段筛选
        if (Objects.nonNull(model.getStartDate())){
            queryWrapper.ge(Goodsorder::getPayDate, Utils.Date.getStart(model.getStartDate()));
@@ -308,6 +324,7 @@
        if (Objects.nonNull(model.getEndDate())){
            queryWrapper.le( Goodsorder::getPayDate, Utils.Date.getEnd(model.getEndDate()));
        }
        queryWrapper.eq(Objects.nonNull(model.getBikeType()),BaseParam::getType,model.getBikeType());
        queryWrapper.eq(Constants.equalsInteger(model.getType(),Constants.ONE)&&model.getPayStatus() !=null,Goodsorder::getPayStatus,model.getPayStatus());
        queryWrapper.like(model.getCode() !=null,Goodsorder::getCode,model.getCode());
        queryWrapper.like(model.getId() !=null,Goodsorder::getId,model.getId());
@@ -333,6 +350,8 @@
        queryWrapper.select("(select  sum(er.discount_price) from member_rides  er  where er.ordre_id=t.id and er.isdeleted=0) as discountMoney," +
                "(select  er.status from member_rides  er  where er.ordre_id=t.id order by er.create_date desc limit 1) as memberRidesStatus");
        queryWrapper.select("( select s.realname from refund r left join system_user s on r.creator = s.id where r.obj_id = t.id order by r.id desc  limit 1  ) ",Goodsorder::getRefundUserName);
        if(Objects.nonNull(pageWrap.getModel().getCloseStatus()) && pageWrap.getModel().getCloseStatus().equals(Constants.ZERO)){
            queryWrapper.ne(Goodsorder::getStatus,Constants.GOODSORDER_STATUS.CLOSE.getKey());
@@ -627,6 +646,7 @@
                freeTime = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME, Constants.FREE_RENT_TIME).getCode());
            }catch (Exception e){
            }
            closeMoney = getCloseMoneyByRides(memberRides,freeTime,true,goodsorder.getMoney(),goodsorder.getMemberId(),true).getAmount();
            //实际结算价格,记录在最高车型记录上
//            memberRides.get(0).setActualPrice(closeMoney);
@@ -674,6 +694,31 @@
                memberRidesJoinMapper.updateById(up);
            }
        }
        int durationSum = 0;
        int freeTime = 0;
        try {
            freeTime = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME, Constants.FREE_RENT_TIME).getCode());
        }catch (Exception e){
        }
        //最高价格车型的骑行记录
        //MemberRides topRides = this.getMaxRides(memberRides,durationSum,freeTime,true);
        MemberRides topRides =null;
        for(MemberRides rides : memberRides){
            if ( true && Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey()!=(Constants.formatIntegerNum(rides.getStatus()))){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"当前订单有未完成的骑行,无法强制结算");
            }
            durationSum += Constants.formatIntegerNum(rides.getDuration());//累计骑行(计费)时长
            if(durationSum-freeTime > 0 ){//只算超出免费时长的数据
                if(topRides == null ||( Constants.formatIntegerNum(topRides.getSortnum())<Constants.formatIntegerNum(rides.getSortnum())
                        && Constants.formatIntegerNum(rides.getDuration())>0)){
                    topRides = rides;
                }
            }
        }
        //无超过免费时长的骑行记录 æŸ¥è¯¢æœ€åŽä¸€æ¡è®°å½•
        if(Objects.isNull(topRides)){
             topRides = memberRidesJoinMapper.selectOne(new QueryWrapper<MemberRides>().lambda().eq(MemberRides::getOrdreId,goodsorder.getId()).orderByDesc(MemberRides::getCreateDate).last("limit 1"));
        }
//        BigDecimal closeMoney =( Constants.formatDecimalNum(goodsorder.getMoney()).subtract(refund.getMoney()));
        //退款乐行
//       int type =Constants.formatIntegerNum(refund.getType());
@@ -681,6 +726,7 @@
        update.setId(goodsorder.getId());
        update.setStatus(Constants.GOODSORDER_STATUS.CLOSE.getKey());
        update.setCloseMoney(closeMoney);
        update.setParamId(Objects.nonNull(topRides)?topRides.getParamId():null);
        update.setCloseStatus(Constants.ONE);
        update.setCloseDate(new Date());
        update.setCloseInfo(Constants.REFUND_TYPE.get(type).getInfo());
@@ -717,6 +763,23 @@
        transactionsMapper.insert(transactions);
        //修改订单信息
        goodsorderMapper.updateById(update);
    }
    public MemberRides getMaxRides(List<MemberRides> memberRides,Integer durationSum,Integer freeTime,boolean isClose){
        MemberRides topRides =null;
        for(MemberRides rides : memberRides){
            if ( isClose && Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey()!=(Constants.formatIntegerNum(rides.getStatus()))){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"当前订单有未完成的骑行,无法强制结算");
            }
            durationSum += Constants.formatIntegerNum(rides.getDuration());//累计骑行(计费)时长
            if(durationSum-freeTime > 0 ){//只算超出免费时长的数据
                if(topRides == null ||( Constants.formatIntegerNum(topRides.getSortnum())<Constants.formatIntegerNum(rides.getSortnum())
                        && Constants.formatIntegerNum(rides.getDuration())>0)){
                    topRides = rides;
                }
            }
        }
        return topRides;
    }
    /**
     * é€€æ¬¾æˆåŠŸå›žè°ƒ
@@ -792,14 +855,30 @@
        transactionsMapper.insert(transactions);
    }
    @Override
    public List<MemberRides> getMemberRidesForClose(String id) {
        MPJLambdaWrapper<MemberRides> wrapper = new MPJLambdaWrapper<>();
        wrapper.eq(MemberRides::getOrdreId,id);
        wrapper.ne(MemberRides::getStatus,Constants.MEMBER_RIDES_STATUS.LOCKING_DEFEAT.getKey());
        wrapper.selectAll(MemberRides.class)
                .selectAs(BaseParam::getSortnum, MemberRides::getSortnum)
                .selectAs(BaseParam::getName, MemberRides::getParamName);
        wrapper.leftJoin(BaseParam.class, BaseParam::getId, MemberRides::getParamId);
        wrapper.orderByDesc(BaseParam::getSortnum);
        //取最高车型作为计价方案
        //查询所有骑行记录
        List<MemberRides> memberRides = memberRidesJoinMapper.selectJoinList(MemberRides.class,wrapper);
        return memberRides;
    }
    private RidesDetailResponse  getCloseMoneyByRides(List<MemberRides> memberRides,int freeTime,boolean isClose,BigDecimal yjMoney,String memberId,Boolean unOver) {
        RidesDetailResponse ridesDetailResponse = new RidesDetailResponse();
        ridesDetailResponse.setHaveDisCount(Constants.ZERO);
        BigDecimal closeMoney = new BigDecimal(0.00);
        int durationSum = 0;
        //最高价格车型的骑行记录
        //MemberRides topRides = this.getMaxRides(memberRides,durationSum,freeTime,isClose);
        MemberRides topRides =null;
        //取最高车型计算方案结算订单
        for(MemberRides rides : memberRides){
            if ( isClose && Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey()!=(Constants.formatIntegerNum(rides.getStatus()))){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"当前订单有未完成的骑行,无法强制结算");
@@ -812,7 +891,6 @@
                }
            }
        }
        //计算应付金额
        if( topRides != null){
            int baseTime =Constants.formatIntegerNum(topRides.getBaseTime());
@@ -827,7 +905,9 @@
                }
            }
            topRides.setActualPrice(closeMoney);
        }
            //2025å¹´3月18日11:28:38 è¿”回骑行价格最高的车型
            ridesDetailResponse.setParamId(topRides.getParamId());
        }
        //查询是否存在套餐信息
        DiscountMember discountMember = this.getUseDiscount(memberId,durationSum,Objects.nonNull(topRides)?topRides.getType():null);
        //计算抵扣金额
@@ -891,22 +971,6 @@
        ridesDetailResponse.setAmount(closeMoney);
        ridesDetailResponse.setBikeType(topRides!=null?topRides.getParamName():"-");
        return ridesDetailResponse;
    }
    @Override
    public List<MemberRides> getMemberRidesForClose(String id) {
        MPJLambdaWrapper<MemberRides> wrapper = new MPJLambdaWrapper<>();
        wrapper.eq(MemberRides::getOrdreId,id);
        wrapper.ne(MemberRides::getStatus,Constants.MEMBER_RIDES_STATUS.LOCKING_DEFEAT.getKey());
        wrapper.selectAll(MemberRides.class)
                .selectAs(BaseParam::getSortnum, MemberRides::getSortnum)
                .selectAs(BaseParam::getName, MemberRides::getParamName);
        wrapper.leftJoin(BaseParam.class, BaseParam::getId, MemberRides::getParamId);
        wrapper.orderByDesc(BaseParam::getSortnum);
        //取最高车型作为计价方案
        //查询所有骑行记录
        List<MemberRides> memberRides = memberRidesJoinMapper.selectJoinList(MemberRides.class,wrapper);
        return memberRides;
    }
    @Override
@@ -1078,7 +1142,7 @@
            model.setRefundNum(Constants.formatIntegerNum(refund.getCountNum()));
            model.setRefundMoney(Constants.translateMoney(Constants.formatDecimalNum(refund.getMoney())));
        }
        model.setClosedMoney(model.getPayMoney().subtract(model.getRefundMoney()).subtract(model.getUnClosedMoney()));
        model.setClosedMoney(model.getPayMoney().add(model.getDiscountMoney()).subtract(model.getRefundMoney()).subtract(model.getUnClosedMoney()));
        return  model;
    }
    @Override
@@ -1385,6 +1449,7 @@
    public void autoCloseOrder( ) {
        Goodsorder goodsorder = new Goodsorder();
        goodsorder.setIsdeleted(Constants.ZERO);
        goodsorder.setType(Constants.ZERO);
        goodsorder.setStatus(Constants.goodsorderStatus.pay);
        List<Goodsorder> list = findList(goodsorder);
        if (!CollectionUtils.isEmpty(list)){
@@ -1401,8 +1466,8 @@
                }
            });
        }
    }
    @Override
    public void goodsOrderSettlement(String memberId) {
        Goodsorder goodsorder = this.goodsorderMapper.selectOne(new QueryWrapper<Goodsorder>()
@@ -1641,4 +1706,85 @@
        );
    }
    @Override
    public List<List<String>> getBikeIncomeReportVOList(Date startDate ,Date endDate){
        if( (Objects.isNull(startDate)||Objects.isNull(endDate))
        || startDate.getTime()>endDate.getTime()
        || DateUtil.daysBetweenDates(endDate,startDate) > 30
        )
        {
            throw new BusinessException(ResponseStatus.BAD_REQUEST);
        }
        System.out.println( DateUtil.daysBetweenDates(endDate,startDate));
        //获取所有车型信息
        List<BaseParam> baseParamList = baseParamMapper.selectList(new QueryWrapper<BaseParam>().lambda().eq(BaseParam::getIsdeleted,Constants.ZERO)
                .in(BaseParam::getType,Constants.THREE,Constants.FOUR)
                .orderByAsc(BaseParam::getType,BaseParam::getSortnum)
        );
        //获取2个日期下所有天数
        List<Date> dateList = DateUtil.getDateList(startDate,endDate);
        //查询日期内的所有数据
        List<Goodsorder> goodsorderList = goodsorderMapper.selectList(new QueryWrapper<Goodsorder>().lambda().eq(Goodsorder::getType,Constants.ZERO)
                .eq(Goodsorder::getIsdeleted,Constants.ZERO)
                .eq(Goodsorder::getStatus,Constants.FOUR)
                .isNotNull(Goodsorder::getParamId)
                .ge(Goodsorder::getPayDate, Utils.Date.getStart(startDate))
                .le( Goodsorder::getPayDate, Utils.Date.getEnd(endDate))
        );
        List<List<String>> parentList = new ArrayList<>();
        for (BaseParam baseParam:baseParamList) {
            List<String> dataChildList = new ArrayList<>();
            dataChildList.add(baseParam.getName()+"(元)");
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (Date date:dateList) {
                BigDecimal amount = goodsorderList.stream()
                        .filter(i->StringUtils.isNotBlank(i.getParamId())&&DateUtil.getShortDateStr(date).equals(DateUtil.getShortDateStr(i.getCreateDate()))&&baseParam.getId().equals(i.getParamId()))
                        .map(i->i.getCloseMoney()).reduce(BigDecimal.ZERO,BigDecimal::add);
                amount = amount.divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP);
                dataChildList.add(amount.toString());
                totalAmount  = amount.add(totalAmount);
            }
            dataChildList.add("ï¿¥"+totalAmount);
            parentList.add(dataChildList);
        }
        List<String> dataStrList = new ArrayList<>();
        dataStrList.add("日期");
        for (Date date:dateList) {
            dataStrList.add(DateUtil.getShortDateStr(date));
        }
        dataStrList.add("总计");
        parentList.add(0,dataStrList);
        return parentList;
    }
    @Override
    public void excel(Date startDate , Date endDate, HttpServletResponse response){
        List<List<String>> data = this.getBikeIncomeReportVOList(startDate,endDate);
        try {
            String fileName = "车型收入分析_"+System.currentTimeMillis();
            String encodeFileName = URLEncoder.encode(fileName, Charset.forName("UTF-8").toString()) + ".xlsx";
            response.setHeader("Content-Disposition","attachment;filename=" + encodeFileName);
            response.setContentType("application/octet-stream");
            response.setHeader("eva-opera-type", "download");
            response.setHeader("eva-download-filename", encodeFileName);
            ExcelExporter.exportList(data, fileName, response.getOutputStream());
        } catch (IOException e) {
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        }
    }
}
server/services/src/main/java/com/doumee/service/business/impl/WxBillServiceImpl.java
@@ -273,6 +273,7 @@
        bill.setDiscountRefundFee(new BigDecimal(0.00));
        bill.setDiscountRefundCmmsAmt(new BigDecimal(0.00));
        bill.setBikeRefundCmmsAmt(new BigDecimal(0.00));
        bill.setDiscountFee(new BigDecimal(0.00));
        return bill;
    }
    @Override
server/web/src/main/java/com/doumee/task/ScheduleTool.java
@@ -43,12 +43,12 @@
     * ç«™ç‚¹è½¦è¾†æ»¡æž¶çŽ‡é¢„è­¦
     * @throws Exception
     */
//    @Scheduled(fixedDelay = 1000L *20L )
//    public void reSubMqtt() throws Exception {
//        log.info("=====================检查是否需要重新订阅===========start============");
//        MqttClientInit.isSubClientValid();
//        log.info("=====================检查是否需要重新订阅===========end============");
//    }
    @Scheduled(fixedDelay = 1000L *20L )
    public void reSubMqtt() throws Exception {
        log.info("=====================检查是否需要重新订阅===========start============");
        MqttClientInit.isSubClientValid();
        log.info("=====================检查是否需要重新订阅===========end============");
    }
    @Scheduled(fixedDelay = 1000L * 100L )