jiangping
2024-02-28 df09f83479cd9860c90632b7db365ffc749df980
Merge remote-tracking branch 'origin/master'
已添加1个文件
已修改12个文件
743 ■■■■ 文件已修改
admin/package-lock.json 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/memberCard.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/retention.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/strandedPersonnel.vue 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/userAction.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/visitEvent.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/vue.config.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
h5/package-lock.json 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
h5/package.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
h5/pages.json 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
h5/pages/appointmentDetails/appointmentDetails.vue 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
h5/pages/cropping/cropping.vue 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/package-lock.json
@@ -1819,63 +1819,6 @@
          "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
          "dev": true
        },
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "ssri": {
          "version": "8.0.1",
          "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-8.0.1.tgz?cache=0&sync_timestamp=1617826515595&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
@@ -1883,28 +1826,6 @@
          "dev": true,
          "requires": {
            "minipass": "^3.1.1"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        },
        "vue-loader-v16": {
          "version": "npm:vue-loader@16.8.3",
          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
          "dev": true,
          "optional": true,
          "requires": {
            "chalk": "^4.1.0",
            "hash-sum": "^2.0.0",
            "loader-utils": "^2.0.0"
          }
        }
      }
@@ -13568,6 +13489,87 @@
        }
      }
    },
    "vue-loader-v16": {
      "version": "npm:vue-loader@16.8.3",
      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
      "dev": true,
      "optional": true,
      "requires": {
        "chalk": "^4.1.0",
        "hash-sum": "^2.0.0",
        "loader-utils": "^2.0.0"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        }
      }
    },
    "vue-property-decorator": {
      "version": "8.5.1",
      "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz",
admin/src/views/business/memberCard.vue
@@ -8,8 +8,8 @@
            <el-form-item label="姓名/手机号" prop="keyword">
                <el-input v-model="searchForm.keyword" placeholder="请输入员工姓名/手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="用户类型" prop="type">
                <el-select v-model="searchForm.type" placeholder="请选择">
            <el-form-item label="用户类型" prop="memberType">
                <el-select v-model="searchForm.memberType" placeholder="请选择">
                    <el-option label="劳务人员" :value="0"></el-option>
                    <el-option label="内部员工" :value="2"></el-option>
                </el-select>
@@ -53,8 +53,8 @@
                </el-table-column>
                <el-table-column label="用户类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 0">劳务访客</span>
                        <span v-if="row.type === 2">内部人员</span>
                        <span v-if="row.memberType === 0">劳务访客</span>
                        <span v-if="row.memberType === 2">内部人员</span>
                    </template>
                </el-table-column>
                <el-table-column prop="memberName" label="员工姓名" min-width="100px"></el-table-column>
@@ -102,7 +102,8 @@
        searchForm: {
          code: '',
          keyword: '',
          status: ''
          status: '',
          memberType: ''
        }
      }
    },
admin/src/views/business/retention.vue
@@ -44,7 +44,12 @@
                @selection-change="handleSelectionChange"
            >
                <el-table-column type="selection" width="55"></el-table-column>
                <el-table-column prop="companyName" label="公司/组织" min-width="100px"></el-table-column>
                <el-table-column prop="companyName" label="公司/组织" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 2 || row.type === 0">{{row.companyName}}</span>
                        <span v-else>{{row.visitCompanyName}}</span>
                    </template>
                </el-table-column>
                <el-table-column prop="type" label="人员类型" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 0">劳务访客</span>
@@ -54,8 +59,13 @@
                </el-table-column>
                <el-table-column prop="name" label="姓名" min-width="100px"></el-table-column>
                <el-table-column prop="phone" label="手机号" min-width="100px"></el-table-column>
                <el-table-column prop="idcardNo" label="身份证号" min-width="130px"></el-table-column>
                <el-table-column prop="deviceName" label="进场门禁" min-width="100px"></el-table-column>
                <el-table-column prop="idcardDecode" label="身份证号" min-width="130px"></el-table-column>
                <el-table-column label="进场门禁" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 1">-</span>
                        <span v-else>{{row.deviceName}}</span>
                    </template>
                </el-table-column>
                <el-table-column prop="eventDate" label="进场时间" min-width="100px"></el-table-column>
                <el-table-column label="人脸照片" min-width="100px">
                  <template slot-scope="{row}">
admin/src/views/business/strandedPersonnel.vue
@@ -42,25 +42,29 @@
                    </template>
                </el-table-column>
                <el-table-column prop="inDate" label="入场时间" min-width="100px"></el-table-column>
                <el-table-column prop="endtime" label="授权到期时间" min-width="100px"></el-table-column>
                <el-table-column prop="timeOut" label="超时时长" min-width="100px"></el-table-column>
                <el-table-column prop="outDate" label="授权到期时间" min-width="100px"></el-table-column>
                <el-table-column label="超时时长" min-width="100px">
                    <template slot-scope="{row}">
                        <span>{{row.timeOut.toString().replace('-', '')}}</span>
                    </template>
                </el-table-column>
                <el-table-column label="状态" min-width="100px">
                    <template slot-scope="{row}">
                        <span v-if="row.outStatus === 0">未超时</span>
                        <span v-else-if="row.timeOut === 1">已超时</span>
                        <span v-else-if="row.timeOut === 2">即将超时</span>
                        <span style="color: red;" v-else-if="row.outStatus === 1">已超时</span>
                        <span v-else-if="row.outStatus === 2">即将超时</span>
                    </template>
                </el-table-column>
<!--                <el-table-column-->
<!--                    v-if="containPermissions(['business:member:update', 'business:member:delete'])"-->
<!--                    label="操作"-->
<!--                    min-width="120"-->
<!--                    fixed="right"-->
<!--                >-->
<!--                    <template slot-scope="{row}">-->
<!--                        <el-button type="text" icon="el-icon-edit" v-permissions="['business:member:update']" @click="thaw(row.id)">离厂</el-button>-->
<!--                    </template>-->
<!--                </el-table-column>-->
                <el-table-column
                    v-if="containPermissions(['business:member:update', 'business:member:delete'])"
                    label="操作"
                    min-width="120"
                    fixed="right"
                >
                    <template slot-scope="{row}">
                        <el-button type="text" icon="el-icon-edit" v-permissions="['business:member:update']" @click="departure(scope.row.id)">离厂</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <pagination
                @size-change="handleSizeChange"
@@ -77,6 +81,7 @@
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import { findAllList } from '@/api/system/common'
import { level } from '@/api/business/staging'
export default {
  name: 'strandedPersonnel',
  extends: BaseTable,
@@ -104,6 +109,20 @@
    this.getUser()
  },
  methods: {
    departure(id) {
      this.$confirm('确定离场吗, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        level(id)
          .then(res => {
            this.search()
          })
      }).catch(() => {
      });
    },
    // thaws () {
    //   if (this.tableData.selectedRows.length === 0) return this.$message.warning('至少选择一项内容')
    //   const ids = this.tableData.selectedRows.map(item => {
admin/src/views/business/userAction.vue
@@ -2,11 +2,52 @@
    <TableLayout :permissions="['business:useraction:query']">
        <!-- æœç´¢è¡¨å• -->
        <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item label="类型" prop="type">
                <el-input v-model="searchForm.type" placeholder="请输入类型" @keypress.enter.native="search"></el-input>
            <el-form-item label="操作人名称" prop="createName">
                <el-input v-model="searchForm.createName" placeholder="请输入操作人名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="操作前状态" prop="beforeStatus">
                <el-input v-model="searchForm.beforeStatus" placeholder="请输入操作前状态" @keypress.enter.native="search"></el-input>
            <el-form-item label="操作对象" prop="memberName">
                <el-input v-model="searchForm.memberName" placeholder="请输入操作对象" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="所属公司" prop="companyName">
                <el-input v-model="searchForm.companyName" placeholder="请输入所属公司" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="人员类型" prop="memberType">
                <el-select v-model="searchForm.memberType" placeholder="请选择">
                    <el-option label="劳务访客" :value="0"></el-option>
                    <el-option label="普通访客" :value="1"></el-option>
                    <el-option label="内部人员" :value="2"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="手机号" prop="mobile">
                <el-input v-model="searchForm.mobile" placeholder="请输入手机号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item label="历史账号状态" prop="beforeStatus">
                <el-select v-model="searchForm.beforeStatus" placeholder="请选择">
                    <el-option label="解冻" :value="0"></el-option>
                    <el-option label="冻结" :value="1"></el-option>
                    <el-option label="拉黑" :value="2"></el-option>
                    <el-option label="恢复" :value="3"></el-option>
                    <el-option label="设为拜访人" :value="4"></el-option>
                    <el-option label="取消拜访人" :value="5"></el-option>
                    <el-option label="设为高级审批人" :value="6"></el-option>
                    <el-option label="取消高级审批人" :value="7"></el-option>
                    <el-option label="手动离场" :value="8"></el-option>
                    <el-option label="删除" :value="9"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="操作类型" prop="type">
                <el-select v-model="searchForm.type" placeholder="请选择">
                    <el-option label="解冻" :value="0"></el-option>
                    <el-option label="冻结" :value="1"></el-option>
                    <el-option label="拉黑" :value="2"></el-option>
                    <el-option label="恢复" :value="3"></el-option>
                    <el-option label="设为拜访人" :value="4"></el-option>
                    <el-option label="取消拜访人" :value="5"></el-option>
                    <el-option label="设为高级审批人" :value="6"></el-option>
                    <el-option label="取消高级审批人" :value="7"></el-option>
                    <el-option label="手动离场" :value="8"></el-option>
                    <el-option label="删除" :value="9"></el-option>
                </el-select>
            </el-form-item>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
@@ -20,9 +61,51 @@
                    :data="tableData.list"
                    stripe
            >
                <el-table-column prop="editDate" label="更新时间" min-width="100px"></el-table-column>
                <el-table-column prop="type" label="类型 0解冻 1冻结 2拉黑 3恢复 4设为拜访人 5取消拜访人 6设为高级审批人 7取消高级审批人 8手动离场 9删除" min-width="100px"></el-table-column>
                <el-table-column prop="beforeStatus" label="操作前状态 0解冻 1冻结 2拉黑 3恢复 4设为拜访人 5取消拜访人 6设为高级审批人 7取消高级审批人 8手动离场 9删除" min-width="100px"></el-table-column>
                <el-table-column prop="createName" label="操作人员"></el-table-column>
                <el-table-column prop="memberName" label="操作对象"></el-table-column>
                <el-table-column prop="companyName" label="所属公司">
                    <template slot-scope="{row}">
                        <span v-if="row.memberType === '1'">{{row.visitCompanyName}}</span>
                        <span v-else>{{row.companyName}}</span>
                    </template>
                </el-table-column>
                <el-table-column label="人员类型">
                    <template slot-scope="{row}">
                        <span v-if="row.memberType === '0'">劳务访客</span>
                        <span v-if="row.memberType === '1'">普通访客</span>
                        <span v-if="row.memberType === '2'">内部人员</span>
                    </template>
                </el-table-column>
                <el-table-column prop="mobile" label="手机号"></el-table-column>
                <el-table-column label="历史状态">
                    <template slot-scope="{row}">
                        <span v-if="row.beforeStatus === 0">解冻</span>
                        <span v-if="row.beforeStatus === 1">冻结</span>
                        <span v-if="row.beforeStatus === 2">拉黑</span>
                        <span v-if="row.beforeStatus === 3">恢复</span>
                        <span v-if="row.beforeStatus === 4">设为拜访人</span>
                        <span v-if="row.beforeStatus === 5">取消拜访人</span>
                        <span v-if="row.beforeStatus === 6">设为高级审批人</span>
                        <span v-if="row.beforeStatus === 7">取消高级审批人</span>
                        <span v-if="row.beforeStatus === 8">手动离场</span>
                        <span v-if="row.beforeStatus === 8">删除</span>
                    </template>
                </el-table-column>
                <el-table-column label="操作">
                    <template slot-scope="{row}">
                        <span v-if="row.type === 0">解冻</span>
                        <span v-if="row.type === 1">冻结</span>
                        <span v-if="row.type === 2">拉黑</span>
                        <span v-if="row.type === 3">恢复</span>
                        <span v-if="row.type === 4">设为拜访人</span>
                        <span v-if="row.type === 5">取消拜访人</span>
                        <span v-if="row.type === 6">设为高级审批人</span>
                        <span v-if="row.type === 7">取消高级审批人</span>
                        <span v-if="row.type === 8">手动离场</span>
                        <span v-if="row.type === 8">删除</span>
                    </template>
                </el-table-column>
                <el-table-column prop="createDate" label="操作时间"></el-table-column>
            </el-table>
            <pagination
                    @size-change="handleSizeChange"
@@ -46,8 +129,13 @@
      return {
        // æœç´¢
        searchForm: {
          type: '',
          beforeStatus: ''
          createName: '',
          memberName: '',
          companyName: '',
          memberType: '',
          mobile: '',
          beforeStatus: '',
          type: ''
        }
      }
    },
admin/src/views/business/visitEvent.vue
@@ -57,7 +57,7 @@
                <el-table-column prop="beVisitedPersonName" label="被访人" min-width="100px"></el-table-column>
                <el-table-column prop="beVisitedPersonOrg" label="被访人组织" min-width="100px"></el-table-column>
                <el-table-column prop="eventTypeName" label="事件类型" min-width="100px"></el-table-column>
                <el-table-column label="抓拍图uri" min-width="100px">
                <el-table-column label="抓拍图片" min-width="100px">
                    <template slot-scope="{row}">
                        <el-image v-if="row.captureUrlFull!=null"
                            style="width: 80px; height: 80px"
admin/src/views/index.vue
@@ -64,16 +64,15 @@
            label="访客公司">
          </el-table-column>
          <el-table-column
            prop="address"
            label="人员类型">
            <template slot-scope="{row}">
              <span v-if="row.memberType === 0">劳务访客</span>
              <span v-if="row.memberType === 1">普通访客</span>
              <span v-if="row.memberType === 2">内部人员</span>
              <span v-if="row.type === 0">劳务访客</span>
              <span v-if="row.type === 1">普通访客</span>
              <span v-if="row.type === 2">内部人员</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="endtime"
            prop="outDate"
            label="授权到期时间">
          </el-table-column>
          <el-table-column
admin/vue.config.js
@@ -13,9 +13,9 @@
        // http://192.168.0.134:10028   ä»»åº·
        // http://192.168.0.110:10013   ç£Šç£Š
        // http://192.168.0.132:10013   å¸…å“¥
        // http://192.168.0.129:10013   èå§
        // http://192.168.0.126:10033   èå§
        // https://dmtest.ahapp.net/admin_api   æµ‹è¯•服
        target: 'http://192.168.0.126:10033',
        target: 'http://192.168.0.129:10028',
        changeOrigin: true,
        pathRewrite: {
          [`^${[process.env.VUE_APP_API_PREFIX]}`]: ''
h5/package-lock.json
@@ -1,7 +1,19 @@
{
  "requires": true,
  "name": "支持分页Picker",
  "version": "1.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "qrcodejs2": {
      "version": "0.0.2",
      "resolved": "https://registry.npmmirror.com/qrcodejs2/-/qrcodejs2-0.0.2.tgz",
      "integrity": "sha512-+Y4HA+cb6qUzdgvI3KML8GYpMFwB24dFwzMkS/yXq6hwtUGNUnZQdUnksrV1XGMc2mid5ROw5SAuY9XhI3ValA=="
    },
    "uniapp-qrcode": {
      "version": "1.0.2",
      "resolved": "https://registry.npmmirror.com/uniapp-qrcode/-/uniapp-qrcode-1.0.2.tgz",
      "integrity": "sha512-jcWwWz4yXsO7if/+78MMXj5VUdZTLu2D6L/IKb4mJkIw87oF11pO3WS/jS27SUcPCrX/BKcir5a2R1uvkaoR9g=="
    },
    "uview-ui": {
      "version": "2.0.36",
      "resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.36.tgz",
h5/package.json
@@ -16,5 +16,9 @@
            "前端组件",
            "通用组件"
        ]
    },
    "dependencies": {
        "qrcodejs2": "0.0.2",
        "uniapp-qrcode": "^1.0.2"
    }
}
h5/pages.json
@@ -111,6 +111,14 @@
                "navigationBarTitleText" : "预约详情",
                "enablePullDownRefresh" : false
            }
        },
        {
            "path" : "pages/cropping/cropping",
            "style" :
            {
                "navigationBarTitleText" : "图片裁剪",
                "enablePullDownRefresh" : false
            }
        }
    ],
    "subPackages": [ 
h5/pages/appointmentDetails/appointmentDetails.vue
@@ -1,7 +1,7 @@
<template>
    <view class="box">
        <view class="box_head">
            <image src="@/static/logo@2x.png" mode="widthFix"></image>
            <canvas class="box_head_qrcode" canvas-id="img"></canvas>
            <text class="box_head_a" v-if="info.status === 0">访客预约待审核</text>
            <text class="box_head_a" style="color: ;" v-if="info.status === 2">访客预约审核通过</text>
            <text class="box_head_a" v-if="info.status === 3">访客预约审核不通过</text>
@@ -11,14 +11,15 @@
        </view>
        <view class="box_list">
            <view class="box_list_label">拜访信息</view>
            <view class="box_list_tips">请注意查看出入门禁下发情况,如若下发失败需重新申请</view>
            <view class="box_list_item">
                <view class="box_list_item_label">拜访员工:</view>
                <view class="box_list_item_label">被访人员:</view>
                <view class="box_list_item_val">{{info.visitUserName}}</view>
            </view>
            <view class="box_list_item">
            <!-- <view class="box_list_item">
                <view class="box_list_item_label">车牌号:</view>
                <view class="box_list_item_val">{{info.carNos}}</view>
            </view>
            </view> -->
            <view class="box_list_item">
                <view class="box_list_item_label">拜访事由:</view>
                <view class="box_list_item_val">{{info.visitReason}}</view>
@@ -31,19 +32,38 @@
                <view class="box_list_item_label">访问门禁:</view>
                <view class="box_list_item_val" v-if="info.doorGroupName && info.doorGroupName.length > 0">{{info.doorGroupName.join('、')}}</view>
            </view>
            <view class="box_list_item">
                <view class="box_list_item_label">主访客:</view>
                <view class="box_list_item_val">
                    {{info.name}} {{info.phone}}
                </view>
            </view>
            <view class="box_list_item" v-for="(item, index) in info.withVisitsList" :key="index">
                <view class="box_list_item_label">随访人员{{index + 1}}:</view>
                <view class="box_list_item_val">{{item.name}} {{item.phone}}</view>
                <view class="box_list_item_val">
                    {{item.name}} {{item.phone}}
                    <view class="box_list_item_val_btn" v-if="[2,5,7,8,9].includes(item.status)">
                        <u-button text="查看二维码" size="mini" @click="seeQrCode(item)" type="primary"></u-button>
            </view>
        </view>
            </view>
        </view>
        <u-popup :show="show" mode="center" @close="close">
            <view class="qrocde">
                <canvas class="qrcode_img" canvas-id="img1"></canvas>
            </view>
        </u-popup>
    </view>
</template>
<script>
    import wxcode from 'uniapp-qrcode'
    export default {
        data() {
            return {
                info: {}
                info: {},
                show: false
            };
        },
        onLoad(option) {
@@ -51,8 +71,26 @@
                .then(res => {
                    if (res.code === 200) {
                        this.info = res.data
                        if (res.data.qrcode) {
                            wxcode.qrcode('img', res.data.qrcode, 320, 320)
                        }
                    }
                })
        },
        methods: {
            close() {
                this.show = false
            },
            seeQrCode(code) {
                if (code.qrcode) {
                    this.show = true
                    this.$nextTick(() => {
                        wxcode.qrcode('img1', code.qrcode, 300, 300)
                    })
                } else {
                    uni.showToast({ title: '暂无二维码', icon: 'none' })
                }
            }
        }
    }
</script>
@@ -64,6 +102,17 @@
<style lang="scss" scoped>
    .box {
        width: 100%;
        .qrocde {
            width: 300rpx;
            height: 300rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            .qrcode_img {
                width: 100%;
                height: 100%;
            }
        }
        .box_head {
            width: 100%;
            padding: 40rpx 0;
@@ -73,7 +122,7 @@
            align-items: center;
            justify-content: center;
            flex-direction: column;
            image {
            .box_head_qrcode {
                width: 320rpx;
                height: 320rpx;
            }
@@ -96,6 +145,19 @@
            background-color: #ffffff;
            padding: 40rpx 30rpx;
            box-sizing: border-box;
            .box_list_tips {
                width: 100%;
                height: 52rpx;
                padding: 0 20rpx;
                box-sizing: border-box;
                line-height: 52rpx;
                background-color: rgba(224, 49, 42, 0.06);
                font-weight: 400;
                font-size: 24rpx;
                color: #E0312A;
                border-radius: 4rpx;
                margin: 30rpx 0;
            }
            .box_list_label {
                font-size: 32rpx;
                font-weight: 500;
@@ -117,6 +179,12 @@
                    font-family: PingFangSC, PingFang SC;
                    font-weight: 400;
                    color: #333333;
                    display: flex;
                    align-items: center;
                    .box_list_item_val_btn {
                        width: 140rpx;
                        margin-left: 15rpx;
                    }
                }
            }
        }
h5/pages/cropping/cropping.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,280 @@
<template>
    <view class="settingHeadImage" @touchstart="onTouchstart" @touchmove.stop.prevent="onTouchmove" @touchend="touchE">
        <!-- è’™å±‚ -->
        <canvas class="pre-canvas" canvas-id="firstCanvas" :style="{ width: 100 + 'vw', height: 100 + 'vh' }"></canvas>
        <!-- img预览 -->
        <view class="preImage" :style="{ width: preImgW + 'px' }">
            <canvas canvas-id="mycanvas" class="pre-i"
                :style="{ width: preImgW + 'px', height: preImgH + 'px', transform: `translate(${x}px,${y}px)` }"></canvas>
        </view>
        <!-- å·¥å…· -->
        <view class="setting-btns"><text @click="onCrop">确定</text></view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                maxW: 250, // æœ€å¤§å®½åº¦
                maxH: 250,
                screenWidth: '', // å±å¹•宽
                screenHeight: '',
                xToTop: 0, // x方向距离顶部距离
                scale: 1, // ç¼©æ”¾
                preSrc: '',
                preImgW: '',
                preImgH: '',
                x: 0,
                y: 0,
                oldx: 0,
                oldy: 0,
                isMove: false,
                start: {
                    left: 0,
                    top: 0
                }
            };
        },
        computed: {},
        onLoad(option) {
            // é€‰æ‹©ç…§ç‰‡ä¿¡æ¯
            let data = JSON.parse(decodeURIComponent(option.item));
            const query = uni.createSelectorQuery();
            query.select('.settingHeadImage').boundingClientRect();
            query.exec(res => {
                // è®¾ç½®å±å¹•大小
                this.screenWidth = res[0].width;
                this.screenHeight = res[0].height;
                // è®¾ç½®å›¾åƒåŸºå‡†å€¼ï¼Œå›¾åƒåŸºå‡†å€¼æŒ‰å±å¹•宽度设置,两边留白各40
                this.maxH = res[0].width - 80;
                this.maxW = res[0].width - 80;
                // è®¾ç½®X轴值,算式:屏幕高度的一半减去基准框高度的一半
                this.xToTop = this.screenHeight / 2 - this.maxH / 2;
                this.setImageSize(data);
            });
        },
        methods: {
            // å®½é«˜å¤„理
            setImageSize(data) {
                const {
                    tempFilePath
                } = data;
                const {
                    maxH,
                    maxW
                } = this;
                uni.getImageInfo({
                    src: tempFilePath,
                    success: res => {
                        const {
                            errMsg,
                            path,
                            width,
                            height
                        } = res;
                        let w = '';
                        let h = '';
                        if (errMsg === 'getImageInfo:ok') {
                            w = width;
                            h = height;
                            // å®½å¤§ä¸Žé«˜å¤§äºŽæœ€å¤§å®½åº¦
                            if (width > height && width > maxW) {
                                w = Math.floor((width / height) * maxW);
                                h = maxH;
                            }
                            // é«˜å¤§äºŽå®½å¤§äºŽæœ€å¤§é«˜åº¦
                            if (height > width && height > maxH) {
                                h = Math.floor((height / width) * maxH);
                                w = maxW;
                            }
                            // å®½é«˜ç›¸ç­‰æˆ–者宽高小于最大值
                            if (width === height || (width < maxW && height < maxH)) {
                                h = maxH;
                                w = maxW;
                            }
                            this.preSrc = path;
                            this.preImgH = h;
                            this.preImgW = w;
                            // è®¾ç½®è’™å±‚
                            this.setBgBox();
                            // å›¾åƒé¢„览
                            this.previewCanvas({
                                w,
                                h,
                                path
                            });
                        }
                    }
                });
            },
            // è®¾ç½®è’™å±‚
            setBgBox() {
                const {
                    maxW,
                    maxH,
                    screenHeight,
                    screenWidth,
                    xToTop
                } = this;
                const ctx = uni.createCanvasContext('firstCanvas');
                // å…ˆæ¸…除矩形
                ctx.clearRect(0, 0, screenWidth, screenHeight);
                // è®¾ç½®canvas透明度
                ctx.setGlobalAlpha(0.7);
                // è®¾ç½®è’™å±‚颜色
                ctx.setFillStyle('#000000');
                // ç»˜åˆ¶è’™å±‚
                ctx.fillRect(0, 0, screenWidth, screenHeight);
                // åŸºå‡†æ¡†ç•™ç™½
                ctx.clearRect(40, xToTop, maxW, maxH);
                // ç»˜åˆ¶åŸºå‡†æ¡†
                ctx.beginPath();
                ctx.setStrokeStyle('#FFFFFF');
                ctx.strokeRect(40, xToTop, maxW, maxH);
                ctx.closePath();
                ctx.draw();
            },
            // é¢„览
            previewCanvas({
                w,
                h,
                path
            }) {
                const ctx = uni.createCanvasContext('mycanvas');
                ctx.drawImage(path, 0, 0, w, h);
                ctx.draw();
            },
            onTouchstart(ev) {
                if (ev.changedTouches.length === 1) {
                    this.isMove = true;
                    this.start.left = ev.changedTouches[0].clientX;
                    this.start.top = ev.changedTouches[0].clientY;
                }
            },
            onTouchmove(ev) {
                const {
                    maxW,
                    maxH,
                    preImgH,
                    preImgW,
                    xToTop
                } = this;
                if (this.isMove && ev.changedTouches.length === 1) {
                    let clientX = ev.changedTouches[0].clientX,
                        clientY = ev.changedTouches[0].clientY;
                    this.x = preImgW <= maxW ? 0 : this.oldx + clientX - this.start.left;
                    this.y = preImgH <= maxH ? 0 : this.oldy + clientY - this.start.top;
                }
            },
            touchE(val) {
                const {
                    preImgH,
                    preImgW,
                    maxH,
                    maxW
                } = this;
                const query = uni.createSelectorQuery();
                const fx = this.x;
                query.select('.pre-i').boundingClientRect();
                query.exec(res => {
                    // x、y回弹计算
                    let y = (res[0].height - res[0].width) / 2;
                    /**
                     * åˆ¤æ–­ç…§ç‰‡å¯ç§»åŠ¨çš„è·ç¦»æ˜¯å¦å¤§äºŽç•™ç™½çš„å€¼ï¼Œå¦‚æžœå¤§äºŽå‘å³åˆ’æ—¶å›¾ç‰‡çš„å®½å‡åŽ»åŸºå‡†æ¡†çš„å®½å‡åŽ»ç•™ç™½å‘å·¦æ—¶ç•™ç™½ï¼Œå°äºŽæ—¶æŒ‰å›¾ç‰‡çš„å¯ç§»åŠ¨å€¼
                     * */
                    let x = (preImgW - maxW) / 2 > 40 ? (fx < 0 ? preImgW - maxW - 40 : 40) : (preImgW - maxW) / 2;
                    if (preImgH > maxH) {
                        this.y = this.y > y ? y : this.y < -y ? -y : this.y;
                    }
                    if (preImgW > maxW) {
                        this.x = this.x > x ? x : this.x < -x ? -x : this.x;
                    }
                    this.oldx = this.x;
                    this.oldy = this.y;
                    this.isMove = false;
                });
            },
            // è£å‰ª
            onCrop() {
                let y = 0;
                let x = 0;
                const query = uni.createSelectorQuery();
                query.select('.pre-i').boundingClientRect();
                query.exec(res => {
                    // èŽ·å–é¢„è§ˆimg距离左上的距离
                    y = Math.abs(res[0].top);
                    x = Math.abs(res[0].left);
                    const {
                        maxW,
                        maxH,
                        preImgH,
                        preImgW,
                        xToTop
                    } = this;
                    uni.canvasToTempFilePath({
                        x: Math.abs(res[0].left < 0 ? x + 40 : x - 40),
                        y: Math.abs(res[0].top < 0 ? xToTop + y : xToTop - y),
                        width: maxW,
                        height: maxH,
                        destWidth: maxW,
                        destHeight: maxH,
                        canvasId: 'mycanvas',
                        success: fileRes => {
                            console.log(fileRes);
                            uni.previewImage({
                                count: 1,
                                urls: [fileRes.tempFilePath]
                            });
                        },
                        fail: function(err) {
                            console.log(err);
                            uni.showToast({
                                title: '上传失败:图片生成过程中遇到错误',
                                icon: 'none'
                            });
                        }
                    });
                });
            }
        }
    };
</script>
<style lang="scss" scoped>
    .settingHeadImage {
        background-color: #000000;
        overflow: hidden;
        .pre-canvas {
            position: fixed;
            top: 0;
            left: 0;
            z-index: 20;
        }
        .preImage {
            min-width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            z-index: 1;
            .pre-i {
                // transition: all 0.1s;
            }
        }
        .setting-btns {
            position: fixed;
            bottom: 0;
            left: 0;
            z-index: 20;
            font-size: 14px;
            color: #ffffff;
        }
    }
</style>