Merge branch 'develop_wsy' into 'develop'
Develop wsy required merge See merge request StarlockTeam/starwork-uniapp!16
This commit is contained in:
commit
f8f65fdb77
@ -122,8 +122,6 @@
|
||||
"@uni-helper/vite-plugin-uni-pages": "0.2.20",
|
||||
"@uni-helper/vite-plugin-uni-platform": "^0.0.4",
|
||||
"@unocss/preset-legacy-compat": "^0.59.4",
|
||||
"@vue/cli-plugin-typescript": "^5.0.8",
|
||||
"@vue/cli-service": "^5.0.8",
|
||||
"@vue/runtime-core": "^3.5.13",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"autoprefixer": "^10.4.20",
|
||||
|
||||
3394
pnpm-lock.yaml
generated
3394
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
148
src/pages.json
148
src/pages.json
@ -279,8 +279,7 @@
|
||||
"path": "pages/mine/mine",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTitleText": "首页"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -362,6 +361,151 @@
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/access-permission-inquiry",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/access-right-detection",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/add-permission-group",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/delivery-status",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/permission-query",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/release-record",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/send-permission",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/viewing-delivery-records",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/access-authority/access-authority",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/one-click-open-door/one-click-open-door",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/password-open-door/password-open-door",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/traffic-record/traffic-record",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/visitor-invitation/visitor-invitation",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/visitor-manage/visitor-manage-tab",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/time-planning-allocation/add-daily-traffic-plan",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/time-planning-allocation/add-time-schedule",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-detail",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-list",
|
||||
"type": "page",
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": []
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
import CommonItem from '@/components/CommonItemItem/CommonItem.vue'
|
||||
|
||||
const times = ref([
|
||||
|
||||
@ -121,47 +121,52 @@
|
||||
name: '人员通行',
|
||||
list: [
|
||||
{
|
||||
id: 106,
|
||||
icon: 'https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png',
|
||||
name: '通行权限',
|
||||
id: 230,
|
||||
icon: 'https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png',
|
||||
name: '门禁管理',
|
||||
url: '/pages/personnel-passage/traffic-correlation'
|
||||
},
|
||||
{
|
||||
id: 230,
|
||||
icon: 'https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png',
|
||||
name: '门禁控制',
|
||||
url: '/pages/personnel-passage/traffic-correlation'
|
||||
id: 106,
|
||||
icon: 'https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png',
|
||||
name: '门禁授权',
|
||||
url: '/pages/personnel-passage/access-authority/access-authority'
|
||||
},
|
||||
{
|
||||
id: 302,
|
||||
icon: 'https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png',
|
||||
name: '一键开门'
|
||||
name: '一键开门',
|
||||
url: '/pages/personnel-passage/one-click-open-door/one-click-open-door'
|
||||
},
|
||||
{
|
||||
id: 400,
|
||||
icon: 'https://file.hikmall.com/prod/image/701d5a7031fa4b4290838c4562f99a0b.png',
|
||||
name: '密码开门'
|
||||
name: '密码开门',
|
||||
url: '/pages/personnel-passage/password-open-door/password-open-door'
|
||||
},
|
||||
{
|
||||
id: 299,
|
||||
icon: 'https://file.hikmall.com/prod/image/771a717eb8d74f5bba71db68c9605a0f.png',
|
||||
name: '通行记录',
|
||||
url: '/pages/personnel-passage/traffic-correlation'
|
||||
url: '/pages/personnel-passage/traffic-record/traffic-record'
|
||||
},
|
||||
{
|
||||
id: 387,
|
||||
icon: 'https://file.hikmall.com/prod/image/9752516f054342d3ac310a0fdb32b654.png',
|
||||
name: '访客管理'
|
||||
name: '访客管理',
|
||||
url: '/pages/personnel-passage/visitor-manage/visitor-manage-tab'
|
||||
},
|
||||
{
|
||||
id: 399,
|
||||
icon: 'https://file.hikmall.com/prod/image/4dbe971d6fac465cb4fed956defd678c.png',
|
||||
name: '我的访客'
|
||||
name: '我的访客',
|
||||
url: '/pages/personnel-passage/visitor-manage/visitor-manage-tab'
|
||||
},
|
||||
{
|
||||
id: 388,
|
||||
icon: 'https://file.hikmall.com/prod/image/624a69276df1480088661e20cbc0e189.png',
|
||||
name: '访客邀约'
|
||||
name: '访客邀约',
|
||||
url: '/pages/personnel-passage/visitor-invitation/visitor-invitation'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '首页'
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
type: 'page',
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
@ -10,7 +10,7 @@
|
||||
<template>
|
||||
<view class="control-container">
|
||||
<!-- 快捷功能区 -->
|
||||
<view class="quick-actions">
|
||||
<!-- <view class="quick-actions">
|
||||
<view class="quick-item" style="background-color: #fff7f2">
|
||||
<view class="quick-content">
|
||||
<text class="quick-title">门自动常开</text>
|
||||
@ -25,7 +25,7 @@
|
||||
<image class="quick-icon" src="/static/images/icon_phone_unlock.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-box">
|
||||
@ -73,31 +73,6 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部导航 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png"
|
||||
/>
|
||||
<text>通行权限</text>
|
||||
</view>
|
||||
<view class="tab-item active">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png"
|
||||
/>
|
||||
<text>门禁控制</text>
|
||||
</view>
|
||||
<view class="tab-item">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png"
|
||||
/>
|
||||
<text>通行记录</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -131,75 +106,74 @@
|
||||
}
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
margin: 12px 0;
|
||||
// .quick-actions {
|
||||
// display: grid;
|
||||
// grid-template-columns: 1fr 1fr;
|
||||
// gap: 12px;
|
||||
// margin: 12px 0;
|
||||
|
||||
.quick-item {
|
||||
position: relative;
|
||||
height: 50px;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
// .quick-item {
|
||||
// position: relative;
|
||||
// height: 50px;
|
||||
// padding: 12px;
|
||||
// border-radius: 8px;
|
||||
|
||||
&:first-child {
|
||||
background-color: #eef4ff;
|
||||
// background: red;
|
||||
.quick-icon {
|
||||
background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
}
|
||||
}
|
||||
// &:first-child {
|
||||
// background-color: #eef4ff;
|
||||
// // background: red;
|
||||
// .quick-icon {
|
||||
// background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
// }
|
||||
// }
|
||||
|
||||
&:last-child {
|
||||
background-color: #fff7f2;
|
||||
.quick-icon {
|
||||
background: linear-gradient(135deg, #ff9853 0%, #ff7b30 100%);
|
||||
}
|
||||
}
|
||||
// &:last-child {
|
||||
// background-color: #fff7f2;
|
||||
// .quick-icon {
|
||||
// background: linear-gradient(135deg, #ff9853 0%, #ff7b30 100%);
|
||||
// }
|
||||
// }
|
||||
|
||||
.quick-content {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
// .quick-content {
|
||||
// position: relative;
|
||||
// height: 100%;
|
||||
|
||||
.quick-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
// .quick-title {
|
||||
// font-size: 15px;
|
||||
// font-weight: 500;
|
||||
// color: #333;
|
||||
// }
|
||||
|
||||
.quick-desc {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
// .quick-desc {
|
||||
// display: block;
|
||||
// margin-top: 8px;
|
||||
// font-size: 11px;
|
||||
// color: #666;
|
||||
// }
|
||||
|
||||
.quick-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
// padding: 8px;
|
||||
border-radius: 50%;
|
||||
transform: translateY(-50%);
|
||||
// .quick-icon {
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// right: 0;
|
||||
// width: 45px;
|
||||
// height: 45px;
|
||||
// // padding: 8px;
|
||||
// border-radius: 50%;
|
||||
// transform: translateY(-50%);
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: brightness(0) invert(1); // 将图标改为白色
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// image {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// filter: brightness(0) invert(1); // 将图标改为白色
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
margin: 16px 0;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
@ -263,6 +237,7 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 80px;
|
||||
padding: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
@ -281,7 +256,7 @@
|
||||
|
||||
.unlock-btn {
|
||||
position: absolute;
|
||||
top: 50%; /* 改为50% */
|
||||
top: 50%;
|
||||
right: 8px;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
@ -291,11 +266,11 @@
|
||||
height: 35px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 50%;
|
||||
transform: translateY(-50%); /* 添加这行来实现精确居中 */
|
||||
transform: translateY(-50%);
|
||||
|
||||
.unlock-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,49 +282,16 @@
|
||||
padding-top: 16px;
|
||||
|
||||
.device-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
//background-color: red;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.device-name {
|
||||
margin-top: 4px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 8px 0;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.tab-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
301
src/pages/personnel-passage/AccessManage/AccessManage.vue
Normal file
301
src/pages/personnel-passage/AccessManage/AccessManage.vue
Normal file
@ -0,0 +1,301 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<!-- 门禁管理 -->
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 开局引导 -->
|
||||
<view class="guide-section">
|
||||
<view class="guide-title">门禁开局引导</view>
|
||||
<view class="guide-link">点击查看→</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<view class="stats-section" @click="handleStatsClick">
|
||||
<view class="stats-item">
|
||||
<text class="number">0</text>
|
||||
<text class="label">团队人员</text>
|
||||
</view>
|
||||
<view class="stats-item">
|
||||
<text class="number">0</text>
|
||||
<text class="label">陌生人</text>
|
||||
</view>
|
||||
<view class="stats-item">
|
||||
<text class="number">0</text>
|
||||
<text class="label">访客</text>
|
||||
<text class="sub-label">今日开门次数统计</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 同步提示 -->
|
||||
<view class="sync-tip" @click="handleSyncClick">
|
||||
<view class="dot"></view>
|
||||
<text class="text">您有6个人员、15条信息未同步到设备</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<!-- 功能列表 -->
|
||||
<view class="feature-grid">
|
||||
<view class="feature-item" v-for="item in features" :key="item.name">
|
||||
<image class="icon" :src="item.icon" mode="aspectFit" />
|
||||
<text class="name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 更多应用 -->
|
||||
<view class="more-section">
|
||||
<text class="section-title">更多应用</text>
|
||||
<view class="more-grid">
|
||||
<view class="more-item" v-for="item in moreApps" :key="item.name">
|
||||
<view class="content">
|
||||
<view class="name">
|
||||
<text>{{ item.name }}</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/e75144eac8984ee198ef533c2f9d3558.png',
|
||||
name: '人员管理'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/cf46656ec73b404891e2b46b57ff5fc2.png',
|
||||
name: '门禁授权'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/0526d084da4a49579f832dd4588dcb16.png',
|
||||
name: '通行记录'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/7ea5f88d404442eeb958fbe0904777d1.png',
|
||||
name: '消息订阅'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/2887bb1c453244a2a872ec98c0360478.png',
|
||||
name: '门自动常开'
|
||||
}
|
||||
]
|
||||
|
||||
const moreApps = [
|
||||
{
|
||||
name: '访客',
|
||||
desc: '访客人员,临时通行'
|
||||
},
|
||||
{
|
||||
name: '信息发布',
|
||||
desc: '广告、欢迎词发布到屏幕'
|
||||
}
|
||||
]
|
||||
|
||||
const handleStatsClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/traffic-record/traffic-record'
|
||||
})
|
||||
}
|
||||
|
||||
const handleSyncClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/permission-query'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.guide-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.guide-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.guide-link {
|
||||
font-size: 14px;
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.stats-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.number {
|
||||
margin-bottom: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.sub-label {
|
||||
position: absolute;
|
||||
right: -15px;
|
||||
bottom: -20px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sync-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
.dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 8px;
|
||||
background: #ff4d4f;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.feature-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-section {
|
||||
padding-bottom: 16px;
|
||||
margin-right: 32px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.section-title {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.more-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px;
|
||||
padding: 0 10px;
|
||||
|
||||
.more-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px 10px;
|
||||
background: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
|
||||
.arrow {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,168 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="权限查询" />
|
||||
<view class="inquiry-container">
|
||||
<!-- 查询表单 -->
|
||||
<view class="inquiry-form">
|
||||
<!-- 查询方式 -->
|
||||
<view class="form-item">
|
||||
<text class="label">人员查询方式</text>
|
||||
<view class="select" @click="handleSelectType">
|
||||
<text>按姓名</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 姓名输入 -->
|
||||
<view class="form-item">
|
||||
<text class="label">人员姓名</text>
|
||||
<input class="input" type="text" placeholder="请输入" placeholder-class="placeholder" />
|
||||
</view>
|
||||
|
||||
<!-- 门禁范围 -->
|
||||
<view class="form-item">
|
||||
<text class="label">门禁点范围</text>
|
||||
<view class="select" @click="handleSelectDoor">
|
||||
<text class="placeholder">全选</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 下发状态 -->
|
||||
<view class="form-item">
|
||||
<text class="label">下发状态</text>
|
||||
<view class="select" @click="handleSelectStatus">
|
||||
<text class="placeholder">全选</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-buttons">
|
||||
<button class="reset-btn">重置</button>
|
||||
<button class="query-btn">查询</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const handleSelectType = () => {
|
||||
// 处理选择查询方式
|
||||
}
|
||||
|
||||
const handleSelectDoor = () => {
|
||||
// 处理选择门禁点
|
||||
}
|
||||
|
||||
const handleSelectStatus = () => {
|
||||
// 处理选择状态
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.inquiry-container {
|
||||
min-height: 100vh;
|
||||
padding: 0 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.inquiry-form {
|
||||
margin-top: 12px;
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-bottom: 1px;
|
||||
background-color: #fff;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
height: 20px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
border-radius: 22px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.reset-btn {
|
||||
color: #666;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.query-btn {
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,180 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="通行权限检测" />
|
||||
<view class="detection-container">
|
||||
<!-- 检测说明 -->
|
||||
<view class="detection-banner">
|
||||
<image class="banner-img" src="/static/images/bg_no_device.webp" mode="aspectFit" />
|
||||
<view class="detection-info">
|
||||
<image class="info-icon" src="/static/images/icon_white_tip.png" mode="aspectFit" />
|
||||
<view class="info-content">
|
||||
<text class="info-title">可检测以下两类问题:</text>
|
||||
<text class="info-item">1. 人员无法通行?</text>
|
||||
<text class="info-item">2.通行记录识别为陌生人?抓拍图不是该人员?</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 检测表单 -->
|
||||
<view class="detection-form">
|
||||
<!-- 姓名输入 -->
|
||||
<view class="form-item">
|
||||
<text class="label">姓名</text>
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="请输入完整姓名"
|
||||
placeholder-class="placeholder"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 门禁选择 -->
|
||||
<view class="form-item">
|
||||
<text class="label">门禁</text>
|
||||
<view class="select" @click="handleSelectDoor">
|
||||
<text class="placeholder">请选择</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 开始检测按钮 -->
|
||||
<button class="start-btn" @click="handleStartDetection">开始检测</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const handleSelectDoor = () => {
|
||||
// 处理选择门禁
|
||||
}
|
||||
|
||||
const handleStartDetection = () => {
|
||||
// 处理开始检测
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detection-container {
|
||||
min-height: 100vh;
|
||||
padding: 0 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.detection-banner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
margin-top: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
aspect-ratio: 1/1;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.detection-info {
|
||||
display: flex;
|
||||
// width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.info-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.info-title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detection-form {
|
||||
margin-top: 12px;
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
min-width: 60px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
|
||||
.placeholder {
|
||||
margin-right: 8px;
|
||||
margin-left: auto;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
margin-top: 24px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background: #2b5cff;
|
||||
border-radius: 22px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,310 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="添加权限组" />
|
||||
<scroll-view
|
||||
class="group-container"
|
||||
:scroll-y="true"
|
||||
:style="{ height: 'calc(100vh - var(--status-bar-height) - 44px)' }"
|
||||
>
|
||||
<!-- 配置名称 -->
|
||||
<view class="form-item input-item">
|
||||
<view class="form-header">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>配置名称</text>
|
||||
</view>
|
||||
</view>
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="name"
|
||||
@input="nameLength = name.length"
|
||||
placeholder="必填"
|
||||
placeholder-class="placeholder"
|
||||
maxlength="20"
|
||||
/>
|
||||
<text class="count">{{ nameLength }}/20</text>
|
||||
</view>
|
||||
|
||||
<!-- 配置描述 -->
|
||||
<view class="form-item input-item">
|
||||
<view class="form-header">
|
||||
<text class="form-label">配置描述</text>
|
||||
</view>
|
||||
<textarea
|
||||
class="textarea"
|
||||
v-model="desc"
|
||||
@input="descLength = desc.length"
|
||||
placeholder="描述权限配置的范围,例如:1幢1单元门口机出入口"
|
||||
placeholder-class="placeholder"
|
||||
maxlength="50"
|
||||
/>
|
||||
<text class="count">{{ descLength }}/50</text>
|
||||
</view>
|
||||
|
||||
<!-- 人员配置方式 -->
|
||||
<view class="form-item select-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>人员配置方式</text>
|
||||
</view>
|
||||
<view class="form-value">
|
||||
<text>按人员/组织</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 人员范围 -->
|
||||
<view class="form-item select-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>人员范围</text>
|
||||
</view>
|
||||
<view class="form-value">
|
||||
<text class="placeholder">必选</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 门禁范围 -->
|
||||
<view class="form-item select-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>门禁范围</text>
|
||||
</view>
|
||||
<view class="form-value">
|
||||
<text class="placeholder">必选</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 门禁通行时间 -->
|
||||
<view class="form-item select-item" @click="handleTimePlanningAllocationClick">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>门禁通行时间</text>
|
||||
</view>
|
||||
<view class="form-value">
|
||||
<text>全天时段有效</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示说明 -->
|
||||
<view class="tips">
|
||||
<view class="tips-header">
|
||||
<image class="icon" src="/static/images/icon_gray_tip.png" mode="aspectFit" />
|
||||
<text class="title">提示</text>
|
||||
</view>
|
||||
<view class="tips-content">
|
||||
<view class="tips-list">
|
||||
<view class="tip-item">
|
||||
<text>1.</text>
|
||||
<text>
|
||||
通行时间仅型号为DS-K1T、D1或HST-AU开头的门禁设备有效,其余型号仅支持全天时段有效;
|
||||
</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<text>2.</text>
|
||||
<text>
|
||||
通过角色配置[一键开门]、[密码开门]菜单权限,可远程/蓝牙/密码打开此配置范围内的门禁;
|
||||
</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<text>3.</text>
|
||||
<text>一键开门不受通行时间、门禁状态的限制,可全天开门。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位,防止保存按钮遮挡内容 -->
|
||||
<view style="height: 76px"></view>
|
||||
</scroll-view>
|
||||
<!-- 底部按钮 -->
|
||||
<button class="save-btn">保存</button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const nameLength = ref(0)
|
||||
const descLength = ref(0)
|
||||
|
||||
// 门禁通行时间
|
||||
const handleTimePlanningAllocationClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-list'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.group-container {
|
||||
box-sizing: border-box;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
.form-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
margin-left: 4px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.input,
|
||||
.textarea {
|
||||
display: block; // 确保是块级元素
|
||||
width: auto; // 让宽度自动计算
|
||||
padding: 8px;
|
||||
// margin-right: 10px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.count {
|
||||
position: absolute;
|
||||
right: 26px;
|
||||
bottom: 26px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.select-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
|
||||
.form-value {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding: 16px;
|
||||
margin-top: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.tips-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
.tips-list {
|
||||
padding-left: 4px;
|
||||
clear: both;
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
text:last-child {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border-radius: 8px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
278
src/pages/personnel-passage/AccessManage/delivery-status.vue
Normal file
278
src/pages/personnel-passage/AccessManage/delivery-status.vue
Normal file
@ -0,0 +1,278 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="下发状态" />
|
||||
<view class="status-container">
|
||||
<!-- 人员信息 -->
|
||||
<view class="person-info">
|
||||
<text class="name">HikMall_30013234</text>
|
||||
<text class="company">19104656的互联</text>
|
||||
|
||||
<!-- 门禁信息 -->
|
||||
<view class="door-info">
|
||||
<text class="label">门禁</text>
|
||||
<text class="value">DS-K(L40959329)</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 下发状态列表 -->
|
||||
<view class="status-list">
|
||||
<!-- 人员信息 -->
|
||||
<view class="status-item">
|
||||
<checkbox class="checkbox" :checked="false" />
|
||||
<view class="item-content">
|
||||
<text class="title">人员信息</text>
|
||||
</view>
|
||||
<text class="status success">已下发</text>
|
||||
</view>
|
||||
|
||||
<!-- 人脸 -->
|
||||
<view class="status-item">
|
||||
<checkbox class="checkbox" :checked="false" />
|
||||
<view class="item-content">
|
||||
<text class="title">人脸</text>
|
||||
<image class="icon" src="/static/images/icon_face.png" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="status success">已下发</text>
|
||||
</view>
|
||||
|
||||
<!-- 指纹 -->
|
||||
<view class="status-item">
|
||||
<checkbox class="checkbox" :checked="false" />
|
||||
<view class="item-content">
|
||||
<text class="title">指纹1</text>
|
||||
<image class="icon" src="/static/images/icon_fingerprint.png" mode="aspectFit" />
|
||||
<text class="error-msg">设备离线,请稍后重试</text>
|
||||
</view>
|
||||
<text class="status error">下发失败</text>
|
||||
</view>
|
||||
|
||||
<!-- 密码 -->
|
||||
<view class="status-item">
|
||||
<checkbox class="checkbox" :checked="false" />
|
||||
<view class="item-content">
|
||||
<text class="title">密码</text>
|
||||
<image class="icon" src="/static/images/icon_password.png" mode="aspectFit" />
|
||||
<text class="password">7****9</text>
|
||||
</view>
|
||||
<text class="status success">已下发</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 状态说明 -->
|
||||
<view class="status-desc">
|
||||
<view class="desc-header">
|
||||
<image class="info-icon" src="/static/images/icon_info.png" mode="aspectFit" />
|
||||
<text class="title">状态说明</text>
|
||||
</view>
|
||||
<view class="desc-list">
|
||||
<text class="desc-item">1、下发中:已配置权限,正在同步到门禁点;</text>
|
||||
<text class="desc-item">2、删除中:已删除权限,正在同步到门禁点;</text>
|
||||
<text class="desc-item">3、待下发:已配置权限,未同步到门禁点,不可通行;</text>
|
||||
<text class="desc-item">4、已下发:已配置权限,并已同步到门禁点,可通行;</text>
|
||||
<text class="desc-item">5、下发失败:已配置权限,同步到门禁点失败,不可通行;</text>
|
||||
<text class="desc-item">6、待重新下发:更新信息,待将信息同步到门禁点,可通行;</text>
|
||||
<text class="desc-item">7、待删除:已删除权限,未同步到门禁点,可通行。</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-buttons">
|
||||
<button class="record-btn" @click="handleRecordBtnClick">查看记录</button>
|
||||
<button class="publish-btn">立即下发</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const handleRecordBtnClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/viewing-delivery-records'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.status-container {
|
||||
min-height: 100vh;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.person-info {
|
||||
padding: 16px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.company {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.door-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.status-list {
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f5f6fa;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-right: 8px;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.item-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.password {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 14px;
|
||||
|
||||
&.success {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.desc-header {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.info-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.desc-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.desc-item {
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
background-color: #fff;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.record-btn {
|
||||
color: #666;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.publish-btn {
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
364
src/pages/personnel-passage/AccessManage/permission-query.vue
Normal file
364
src/pages/personnel-passage/AccessManage/permission-query.vue
Normal file
@ -0,0 +1,364 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="权限查询" />
|
||||
<scroll-view
|
||||
class="query-container"
|
||||
:scroll-y="true"
|
||||
:style="{ height: 'calc(100vh - var(--status-bar-height) - 44px)' }"
|
||||
>
|
||||
<!-- 搜索提示卡片 -->
|
||||
<view class="search-tip">
|
||||
<text>人员无法通行?</text>
|
||||
<text class="check-btn" @click="handleCheckClick">去检测</text>
|
||||
</view>
|
||||
|
||||
<!-- 权限查询入口 -->
|
||||
<view class="query-entry" @click="handleQueryClick">
|
||||
<text class="entry-title">通行权限查询</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<!-- 人员列表 -->
|
||||
<view class="person-list">
|
||||
<view class="person-item" v-for="person in personList" :key="person.id">
|
||||
<view class="person-info">
|
||||
<text class="person-name">{{ person.name }}</text>
|
||||
<text class="person-id">{{ person.id }}</text>
|
||||
</view>
|
||||
<text class="company">{{ person.company }}</text>
|
||||
<view class="validity">
|
||||
<text class="label">有效时间:</text>
|
||||
<text class="value">{{ person.validityPeriod }}</text>
|
||||
</view>
|
||||
<view class="access-info">
|
||||
<view class="door-info">
|
||||
<image class="icon" src="/static/images/icon_door.png" mode="aspectFit" />
|
||||
<text>门禁点:{{ person.doorPoint }}</text>
|
||||
</view>
|
||||
<view class="time-info">
|
||||
<image class="icon" src="/static/images/icon_time.png" mode="aspectFit" />
|
||||
<text>通行时间:</text>
|
||||
<view class="time-tag">{{ person.accessTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="auth-types" @click="() => handlePersonItemClick(person)">
|
||||
<view class="type-item" v-for="type in person.authTypes" :key="type.name">
|
||||
<image class="type-icon" :src="type.icon" mode="aspectFit" />
|
||||
<text>{{ type.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="item-arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-buttons">
|
||||
<button class="btn add-btn" @click="handleAddBtnClick">添加权限组</button>
|
||||
<button class="btn publish-btn" @click="handlePublishBtnClick">下发权限</button>
|
||||
<button class="btn record-btn" @click="handleRecordBtnClick">下发记录</button>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
interface AuthType {
|
||||
name: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
interface Person {
|
||||
id: string
|
||||
name: string
|
||||
company: string
|
||||
validityPeriod: string
|
||||
doorPoint: string
|
||||
accessTime: string
|
||||
authTypes: AuthType[]
|
||||
}
|
||||
|
||||
const personList = ref<Person[]>([
|
||||
{
|
||||
id: 'CY01068968',
|
||||
name: 'HikMall_30013234',
|
||||
company: '19104656的互联',
|
||||
validityPeriod: '永久有效',
|
||||
doorPoint: 'DS-K(L40959329)',
|
||||
accessTime: '全天时段有效',
|
||||
authTypes: [
|
||||
{ name: '人员', icon: '/static/images/icon_person.png' },
|
||||
{ name: '人脸', icon: '/static/images/icon_face.png' },
|
||||
{ name: '指纹', icon: '/static/images/icon_fingerprint.png' },
|
||||
{ name: '密码', icon: '/static/images/icon_password.png' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'CY01069559',
|
||||
name: '4',
|
||||
company: '19104656的互联/test',
|
||||
validityPeriod: '2000-01-01至2037-12-31',
|
||||
doorPoint: 'DS-K(L40959329)',
|
||||
accessTime: '全天时段有效',
|
||||
authTypes: [
|
||||
{ name: '人员', icon: '/static/images/icon_person.png' },
|
||||
{ name: '指纹', icon: '/static/images/icon_fingerprint.png' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'CY01069559',
|
||||
name: '4',
|
||||
company: '19104656的互联/test',
|
||||
validityPeriod: '2000-01-01至2037-12-31',
|
||||
doorPoint: 'DS-K(L40959329)',
|
||||
accessTime: '全天时段有效',
|
||||
authTypes: [
|
||||
{ name: '人员', icon: '/static/images/icon_person.png' },
|
||||
{ name: '指纹', icon: '/static/images/icon_fingerprint.png' }
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
const handleCheckClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/access-right-detection'
|
||||
})
|
||||
}
|
||||
|
||||
const handleQueryClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/access-permission-inquiry'
|
||||
})
|
||||
}
|
||||
|
||||
const handlePersonItemClick = (person: Person) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/personnel-passage/AccessManage/delivery-status?id=${person.id}`
|
||||
})
|
||||
}
|
||||
|
||||
// 添加权限组
|
||||
const handleAddBtnClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/add-permission-group'
|
||||
})
|
||||
}
|
||||
|
||||
// 下发权限
|
||||
const handlePublishBtnClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/send-permission'
|
||||
})
|
||||
}
|
||||
|
||||
// 下发记录
|
||||
const handleRecordBtnClick = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/release-record'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.query-container {
|
||||
box-sizing: border-box;
|
||||
padding: 0 16px;
|
||||
padding-bottom: 63px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
margin-top: 12px;
|
||||
background-color: #fff7f2;
|
||||
border-radius: 8px;
|
||||
|
||||
.check-btn {
|
||||
padding: 2px 8px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.query-entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-top: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.entry-title {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.person-list {
|
||||
margin-top: 12px;
|
||||
|
||||
.person-item {
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.person-info {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
|
||||
.person-name {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.person-id {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.company {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.validity {
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.access-info {
|
||||
padding: 12px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.door-info,
|
||||
.time-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.time-tag {
|
||||
padding: 2px 8px;
|
||||
margin-left: 4px;
|
||||
font-size: 12px;
|
||||
color: #2b5cff;
|
||||
background-color: #eef4ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.auth-types {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
|
||||
.type-item {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
.type-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-arrow {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
padding-top: 12px;
|
||||
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #eee;
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
font-size: 14px;
|
||||
|
||||
// &::after {
|
||||
// border: 1px solid #eee;
|
||||
// border-radius: 0;
|
||||
// }
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
color: #2b5cff;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.publish-btn {
|
||||
color: #2b5cff;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.record-btn {
|
||||
color: #2b5cff;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
186
src/pages/personnel-passage/AccessManage/release-record.vue
Normal file
186
src/pages/personnel-passage/AccessManage/release-record.vue
Normal file
@ -0,0 +1,186 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="下发记录" />
|
||||
<scroll-view
|
||||
class="record-container"
|
||||
:scroll-y="true"
|
||||
:style="{ height: 'calc(100vh - var(--status-bar-height) - 44px)' }"
|
||||
>
|
||||
<view class="record-list">
|
||||
<view class="record-item" v-for="record in records" :key="record.time">
|
||||
<view class="record-header">
|
||||
<view class="title-wrap">
|
||||
<text class="title">{{ record.title }}</text>
|
||||
<text class="time">{{ record.time }}</text>
|
||||
</view>
|
||||
<view class="status-wrap" @click="handleRecordClick(record)">
|
||||
<text class="status">{{ record.status }}</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="record-stats">
|
||||
<view class="stat-item">
|
||||
<text class="value">{{ record.success }}</text>
|
||||
<text class="label">成功</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="value">{{ record.fail }}</text>
|
||||
<text class="label">失败</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="value">{{ record.total }}</text>
|
||||
<text class="label">总数</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
interface Record {
|
||||
title: string
|
||||
time: string
|
||||
status: string
|
||||
success: number
|
||||
fail: number
|
||||
total: number
|
||||
}
|
||||
|
||||
const records = ref<Record[]>([
|
||||
{
|
||||
title: '系统自动操作下发',
|
||||
time: '2025-01-16 14:01:41',
|
||||
status: '已完成',
|
||||
success: 0,
|
||||
fail: 4,
|
||||
total: 4
|
||||
},
|
||||
{
|
||||
title: '杨操作下发',
|
||||
time: '2025-01-16 09:47:06',
|
||||
status: '已完成',
|
||||
success: 0,
|
||||
fail: 4,
|
||||
total: 4
|
||||
},
|
||||
{
|
||||
title: '系统自动操作下发',
|
||||
time: '2025-01-16 06:01:13',
|
||||
status: '已完成',
|
||||
success: 0,
|
||||
fail: 8,
|
||||
total: 8
|
||||
},
|
||||
{
|
||||
title: '系统自动操作下发',
|
||||
time: '2025-01-15 06:01:12',
|
||||
status: '已完成',
|
||||
success: 0,
|
||||
fail: 8,
|
||||
total: 8
|
||||
},
|
||||
{
|
||||
title: '系统自动操作下发',
|
||||
time: '2025-01-14 15:42:37',
|
||||
status: '已完成',
|
||||
success: 0,
|
||||
fail: 4,
|
||||
total: 4
|
||||
}
|
||||
])
|
||||
|
||||
const handleRecordClick = (record: Record) => {
|
||||
// 处理记录点击
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.record-container {
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.record-list {
|
||||
.record-item {
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.record-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.title-wrap {
|
||||
.title {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.status-wrap {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.status {
|
||||
font-size: 14px;
|
||||
color: #2b5cff;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 12px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.value {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
214
src/pages/personnel-passage/AccessManage/send-permission.vue
Normal file
214
src/pages/personnel-passage/AccessManage/send-permission.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="下发权限">
|
||||
<template #right>
|
||||
<view class="timing-btn" @click="handleTimingClick">
|
||||
<image class="icon" src="/static/images/icon_timing.png" mode="aspectFit" />
|
||||
<text>定时下发</text>
|
||||
</view>
|
||||
</template>
|
||||
</TopNavigation>
|
||||
|
||||
<view class="send-container">
|
||||
<!-- 下发选项 -->
|
||||
<view class="form-item">
|
||||
<text class="label">下发方式</text>
|
||||
<view class="select">
|
||||
<text>普通下发</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">门禁范围</text>
|
||||
<view class="select">
|
||||
<text>全选</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示说明 -->
|
||||
<view class="tips">
|
||||
<view class="tips-header">
|
||||
<image class="icon" src="/static/images/icon_gray_tip.png" mode="aspectFit" />
|
||||
<text class="title">提示</text>
|
||||
</view>
|
||||
<view class="tips-content">
|
||||
<view class="tips-list">
|
||||
<view class="tip-item">
|
||||
<text>1.</text>
|
||||
<text>仅可选择已配置过通行权限的门禁进行下发;</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<text>2.</text>
|
||||
<text>下发信息过多,会影响人员通行体验,建议避开人流量较大时间,错峰下发;</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<text>3.</text>
|
||||
<text>
|
||||
设备数据与平台数据不一致时,可选择[全量下发],将删除设备本地数据后,重新下发平台数据;
|
||||
</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<text>4.</text>
|
||||
<text>
|
||||
通行时间仅型号为DS-K1T、D1或HST-AU开头的门禁设备有效,其余型号仅支持全天时段有效。
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="extra-tips">
|
||||
<text>
|
||||
新添加或修改权限组需点击[立即下发],将配置的通行凭证下发到对应门禁点成功后,可生效通行权限;
|
||||
</text>
|
||||
<text>
|
||||
若权限组已按照组织/分组/楼幢进行人员配置,则后续在对应的组织/分组/楼幢中加入人员,将自动下发新增的通行凭证,无需手动下发。
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<button class="send-btn">立即下发</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const handleTimingClick = () => {
|
||||
// 处理定时下发点击
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.send-container {
|
||||
min-height: 100vh;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.timing-btn {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.tips-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
.tips-list {
|
||||
padding-left: 4px;
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
text:last-child {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.extra-tips {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
background-color: #f5f6fa;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border-radius: 8px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,231 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="日常通行计划" />
|
||||
<view class="plan-container">
|
||||
<!-- 周时间选择 -->
|
||||
<view class="week-section">
|
||||
<text class="required">*</text>
|
||||
<text class="title">周时间选择</text>
|
||||
<view class="week-list">
|
||||
<view
|
||||
v-for="(day, index) in weekDays"
|
||||
:key="index"
|
||||
:class="['week-item', { active: day.active }]"
|
||||
>
|
||||
{{ day.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 通行时段 -->
|
||||
<view class="time-section">
|
||||
<view class="section-header">
|
||||
<text>通行时段</text>
|
||||
<text class="sub-text">未添加通行时段表示全天不可通行</text>
|
||||
</view>
|
||||
|
||||
<!-- 时段列表 -->
|
||||
<view class="time-list">
|
||||
<view class="time-item" v-for="(period, index) in timePeriods" :key="index">
|
||||
<view class="time-info">
|
||||
<text class="period-label">时段{{ index + 1 }}</text>
|
||||
<text class="time-value">{{ period.time }}</text>
|
||||
</view>
|
||||
<view class="action-icons">
|
||||
<image
|
||||
class="gray-delet-icon"
|
||||
src="/static/images/icon_gray_delet.png"
|
||||
mode="scaleToFill"
|
||||
@click="deletAction"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 添加时段按钮 -->
|
||||
<view class="add-time">
|
||||
<image class="add-icon" src="/static/images/icon_blue_add.png" mode="aspectFit" />
|
||||
<text>增加通行时段</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部保存按钮 -->
|
||||
<button class="save-btn">保存</button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const weekDays = ref([
|
||||
{ label: '一', active: true },
|
||||
{ label: '二', active: true },
|
||||
{ label: '三', active: true },
|
||||
{ label: '四', active: true },
|
||||
{ label: '五', active: true },
|
||||
{ label: '六', active: false },
|
||||
{ label: '日', active: false }
|
||||
])
|
||||
|
||||
const timePeriods = ref([{ time: '08:00:00-12:00:00' }, { time: '14:00:00-18:00:00' }])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.plan-container {
|
||||
padding: 12px 0;
|
||||
// margin-right: 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.week-section {
|
||||
padding: 12px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.week-list {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
|
||||
.week-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: calc((100% - 48px) / 7);
|
||||
aspect-ratio: 1;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
border: 1px dashed #ddd;
|
||||
border-radius: 50%;
|
||||
|
||||
&.active {
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time-section {
|
||||
padding: 12px 16px;
|
||||
background-color: #fff;
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.sub-text {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.time-list {
|
||||
.time-item {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.time-info {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
margin-bottom: 0;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.period-label {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.time-value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.action-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-left: 12px;
|
||||
|
||||
.gray-delet-icon {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-time {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.add-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border-radius: 8px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,313 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="增加时间计划" />
|
||||
<scroll-view scroll-y class="time-schedule">
|
||||
<view class="content">
|
||||
<!-- 计划名称 -->
|
||||
<view class="form-item">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>计划名称</text>
|
||||
</view>
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="请填写计划名称"
|
||||
placeholder-style="color: #999;"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 计划描述 -->
|
||||
<view class="form-item">
|
||||
<view class="label">计划描述</view>
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="非必填"
|
||||
placeholder-style="color: #999;"
|
||||
maxlength="50"
|
||||
/>
|
||||
<view class="word-count">0/50</view>
|
||||
</view>
|
||||
|
||||
<!-- 日常通行计划 -->
|
||||
<view class="form-item">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>日常通行计划</text>
|
||||
</view>
|
||||
<view class="time-block-main">
|
||||
<view class="time-block">
|
||||
<view class="week-select">
|
||||
<text>周一至周五</text>
|
||||
<!-- <uni-icons type="right" size="16" color="white"></uni-icons> -->
|
||||
<image
|
||||
class="right-icon"
|
||||
src="/static/images/icon_black_right.png"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="time-periods">
|
||||
<view class="time-item">
|
||||
<text>时段1</text>
|
||||
<text class="time">08:00:00-12:00:00</text>
|
||||
<view class="delete-icon">
|
||||
<uni-icons type="trash" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text>时段2</text>
|
||||
<text class="time">14:00:00-16:00:00</text>
|
||||
<view class="delete-icon">
|
||||
<uni-icons type="trash" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
class="gray_delet-icon"
|
||||
src="/static/images/icon_gray_delet.png"
|
||||
mode="scaleToFill"
|
||||
@click="deletAction"
|
||||
/>
|
||||
</view>
|
||||
<view class="add-time" @click="addTimeSlot">
|
||||
<!-- <uni-icons type="plusempty" size="16" color="#2979ff"></uni-icons> -->
|
||||
<image class="add-icon" src="/static/images/icon_blue_add.png" mode="scaleToFill" />
|
||||
<text>添加日常通行计划</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 节假日通行计划 -->
|
||||
<view class="form-item">
|
||||
<view class="holiday-header">
|
||||
<text>节假日通行计划</text>
|
||||
<text class="sub-text">遇节假日将按假日计划执行</text>
|
||||
</view>
|
||||
<view class="holiday-select" @click="selectHoliday">
|
||||
<text>法定节假日</text>
|
||||
<image
|
||||
class="holiday-select-right-icon"
|
||||
src="/static/images/icon_black_right.png"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位,为fixed按钮留出空间 -->
|
||||
<view class="footer-placeholder"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部保存按钮 -->
|
||||
<view class="footer">
|
||||
<button class="save-btn" type="primary">保存</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.time-schedule {
|
||||
box-sizing: border-box;
|
||||
height: calc(100vh - 44px); // 减去顶部导航栏的高度
|
||||
background-color: #f5f6fa;
|
||||
|
||||
.content {
|
||||
padding: 12px 16px;
|
||||
|
||||
.form-item {
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
// width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
box-sizing: border-box;
|
||||
height: 80px;
|
||||
padding: 8px 12px;
|
||||
margin-right: 32px;
|
||||
font-size: 14px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.time-block-main {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.time-block {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
background-color: #f5f6fa;
|
||||
border-radius: 8px;
|
||||
|
||||
.week-select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: fit-content;
|
||||
min-width: 120px;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
border-radius: 8px;
|
||||
|
||||
.right-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.time-periods {
|
||||
padding: 12px 0;
|
||||
|
||||
.time-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
color: #666;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.time {
|
||||
flex: 1;
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gray_delet-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.add-time {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
color: #2979ff;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 4px;
|
||||
|
||||
.add-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 16px;
|
||||
color: #2979ff;
|
||||
}
|
||||
}
|
||||
|
||||
.holiday-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.sub-text {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.holiday-select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 4px;
|
||||
|
||||
.holiday-select-right-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer-placeholder {
|
||||
height: 76px; // 为底部按钮占位
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
padding: 16px;
|
||||
background-color: #f5f6fa;
|
||||
|
||||
.save-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
line-height: 44px;
|
||||
color: #fff;
|
||||
background-color: #2979ff;
|
||||
border-radius: 22px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
const addTimeSlot = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/time-planning-allocation/add-daily-traffic-plan'
|
||||
})
|
||||
}
|
||||
|
||||
const deletAction = () => {
|
||||
console.log('删除')
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,136 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="计划1" />
|
||||
<scroll-view
|
||||
class="plan-container"
|
||||
:scroll-y="true"
|
||||
:style="{ height: 'calc(100vh - var(--status-bar-height) - 44px - 76px)' }"
|
||||
>
|
||||
<view class="tip-box">
|
||||
<text>如需修改,请在【通行权限】-【通行时间计划】功能内修改</text>
|
||||
</view>
|
||||
|
||||
<!-- 计划名称 -->
|
||||
<view class="form-item">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="planName"
|
||||
placeholder="我路走里呀我路走里哇路在"
|
||||
placeholder-class="placeholder"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 日常通行时间 -->
|
||||
<view class="time-section">
|
||||
<text class="section-title">日常通行时间</text>
|
||||
<view class="time-card">
|
||||
<text class="week-text">周一至周五</text>
|
||||
<view class="time-row">
|
||||
<text class="time-label">时段1</text>
|
||||
<text class="time-value">08:00:00-18:00:00</text>
|
||||
</view>
|
||||
<view class="time-row">
|
||||
<text class="time-label">时段2</text>
|
||||
<text class="time-value">20:00:00-23:59:00</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const planName = ref('')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.plan-container {
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.tip-box {
|
||||
padding: 12px 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
color: #ff6b00;
|
||||
background-color: #fff6f0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
.input {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.time-section {
|
||||
margin-right: 32px;
|
||||
|
||||
.section-title {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.time-card {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.week-text {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.time-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.time-label {
|
||||
width: 60px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.time-value {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,157 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="节假日计划配置" />
|
||||
<scroll-view
|
||||
class="plan-container"
|
||||
:scroll-y="true"
|
||||
:style="{ height: 'calc(100vh - var(--status-bar-height) - 44px - 76px)' }"
|
||||
>
|
||||
<!-- 添加计划 -->
|
||||
<view class="plan-item add-plan" @click="handleAddPlan">
|
||||
<text class="title">增加时间计划</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<!-- 计划列表 -->
|
||||
<view class="plan-list">
|
||||
<!-- 法定节假日 -->
|
||||
<view class="plan-item" @click="handlePlanClickDetail">
|
||||
<view class="checkbox-wrap">
|
||||
<checkbox class="checkbox" :checked="false" color="#2B5CFF" />
|
||||
</view>
|
||||
<view class="content" @click="handlePlanClick">
|
||||
<text class="title">法定节假日</text>
|
||||
<text class="desc">每年自动同步国家法定节假日,通行时段可自定义</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 浓的 -->
|
||||
<view class="plan-item" @click="handlePlanClickDetail">
|
||||
<view class="checkbox-wrap">
|
||||
<checkbox class="checkbox" :checked="false" color="#2B5CFF" />
|
||||
</view>
|
||||
<view class="content" @click="handlePlanClick">
|
||||
<text class="title">浓的</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<button class="save-btn">保存</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const handleAddPlan = () => {
|
||||
// 处理添加计划
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/time-planning-allocation/add-time-schedule'
|
||||
})
|
||||
}
|
||||
|
||||
const handlePlanClick = () => {
|
||||
// 处理计划点击
|
||||
}
|
||||
|
||||
// 处理计划点击
|
||||
const handlePlanClickDetail = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-detail'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.plan-container {
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.plan-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
margin-right: 32px;
|
||||
margin-bottom: 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
&.add-plan {
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-wrap {
|
||||
margin-right: 8px;
|
||||
|
||||
.checkbox {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
|
||||
.title {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: block;
|
||||
margin-right: 16px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border-radius: 8px;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,220 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: false
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="查看记录" />
|
||||
<view class="records-container">
|
||||
<!-- 人员信息 -->
|
||||
<view class="person-info">
|
||||
<text class="name">HikMall_30013234</text>
|
||||
<text class="company">19104656的互联</text>
|
||||
|
||||
<!-- 门禁信息 -->
|
||||
<view class="door-info">
|
||||
<text class="label">门禁</text>
|
||||
<text class="value">DS-K(L40959329)</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 记录列表 -->
|
||||
<view class="records-list">
|
||||
<!-- 记录项 -->
|
||||
<view class="record-item" v-for="(item, index) in records" :key="index">
|
||||
<text class="time">{{ item.time }}</text>
|
||||
<view class="record-content">
|
||||
<view class="content-header">
|
||||
<text class="title">{{ item.title }}</text>
|
||||
<text :class="['status', item.status === '下发失败' ? 'error' : 'success']">
|
||||
{{ item.status }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="operation-info">
|
||||
<image class="icon" src="/static/images/icon_operation.png" mode="aspectFit" />
|
||||
<text class="label">权限操作:</text>
|
||||
<text class="value">{{ item.operation }}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="item.error" class="error-info">
|
||||
<image class="icon" src="/static/images/icon_info.png" mode="aspectFit" />
|
||||
<text class="label">失败原因:</text>
|
||||
<text class="value">{{ item.error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
|
||||
const records = [
|
||||
{
|
||||
time: '2025-01-16 06:01:13',
|
||||
title: '指纹1',
|
||||
status: '下发失败',
|
||||
operation: '下发权限',
|
||||
error: '设备离线,请稍后重试'
|
||||
},
|
||||
{
|
||||
time: '2025-01-15 06:01:12',
|
||||
title: '指纹1',
|
||||
status: '下发失败',
|
||||
operation: '下发权限',
|
||||
error: '设备离线,请稍后重试'
|
||||
},
|
||||
{
|
||||
time: '2025-01-14 06:01:17',
|
||||
title: '指纹1',
|
||||
status: '下发失败',
|
||||
operation: '下发权限',
|
||||
error: '设备离线,请稍后重试'
|
||||
},
|
||||
{
|
||||
time: '2025-01-13 11:22:18',
|
||||
title: '人员信息',
|
||||
status: '下发成功',
|
||||
operation: '下发权限'
|
||||
},
|
||||
{
|
||||
time: '2025-01-15 06:01:12',
|
||||
title: '指纹1',
|
||||
status: '下发失败',
|
||||
operation: '下发权限',
|
||||
error: '设备离线,请稍后重试'
|
||||
},
|
||||
{
|
||||
time: '2025-01-15 06:01:12',
|
||||
title: '指纹1',
|
||||
status: '下发失败',
|
||||
operation: '下发权限',
|
||||
error: '设备离线,请稍后重试'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.records-container {
|
||||
min-height: 100vh;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.person-info {
|
||||
padding: 16px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.company {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.door-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
background-color: #f8f9fc;
|
||||
border-radius: 8px;
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.records-list {
|
||||
.record-item {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.time {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.record-content {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.content-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 14px;
|
||||
|
||||
&.success {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.operation-info,
|
||||
.error-info {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -9,8 +9,19 @@
|
||||
|
||||
<template>
|
||||
<view class="passage-container">
|
||||
<!-- 替换原来的 banner 部分为 AccessSwiper -->
|
||||
<AccessSwiper class="mt-4" />
|
||||
<TopNavigation title="门禁授权" />
|
||||
|
||||
<view class="visitor-card">
|
||||
<view class="card-content">
|
||||
<view class="card-left">
|
||||
<text class="card-title">访客人员,临时通行</text>
|
||||
<text class="card-desc">使用访客管理,来访轻松搞定</text>
|
||||
</view>
|
||||
<!-- <view class="card-right">
|
||||
<image src="/static/images/visitor-illustration.png" mode="aspectFit" />
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 权限组快捷入口 -->
|
||||
<view class="quick-actions">
|
||||
@ -30,6 +41,38 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="remind-card">
|
||||
<view class="card-header">
|
||||
<view class="header-left">
|
||||
<image class="user-icon" src="/static/images/icon_user.png" mode="aspectFit" />
|
||||
<text class="user-count">6</text>
|
||||
</view>
|
||||
<text class="check-text">查看未同步信息 ></text>
|
||||
</view>
|
||||
<view class="stats-container">
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">4</text>
|
||||
<text class="stat-label">人员/通行规则</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">0</text>
|
||||
<text class="stat-label">人脸</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">7</text>
|
||||
<text class="stat-label">指纹</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">0</text>
|
||||
<text class="stat-label">卡片</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-num">4</text>
|
||||
<text class="stat-label">密码</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 人员管理 -->
|
||||
<view class="feature-item">
|
||||
<view class="feature-left">
|
||||
@ -38,46 +81,26 @@
|
||||
src="https://file.hikmall.com/prod/image/e75144eac8984ee198ef533c2f9d3558.png"
|
||||
/>
|
||||
<view class="feature-text">
|
||||
<text class="feature-title">人员管理</text>
|
||||
<text class="feature-desc">团队管理内录入人员信息/人脸/指纹/卡</text>
|
||||
<text class="feature-title">人员信息录入</text>
|
||||
<text class="feature-desc">团队管理录入人员信息及通行凭证信息</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" />
|
||||
</view>
|
||||
|
||||
<!-- 通行权限组 -->
|
||||
<view class="access-authority-group">
|
||||
<view class="feature-item">
|
||||
<view class="feature-left">
|
||||
<image
|
||||
class="feature-icon"
|
||||
src="https://file.hikmall.com/prod/image/cf46656ec73b404891e2b46b57ff5fc2.png"
|
||||
/>
|
||||
<view class="feature-text">
|
||||
<text class="feature-title">通行权限组</text>
|
||||
<text class="feature-desc">配置人员在某段时间能开某个门</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" />
|
||||
</view>
|
||||
|
||||
<!-- 时间计划和门禁点分组 -->
|
||||
<view class="sub-features">
|
||||
<view class="sub-item">
|
||||
<image
|
||||
class="sub-icon"
|
||||
src="https://file.hikmall.com/prod/image/0526d084da4a49579f832dd4588dcb16.png"
|
||||
/>
|
||||
<text>通行时间计划</text>
|
||||
</view>
|
||||
<view class="sub-item">
|
||||
<image
|
||||
class="sub-icon"
|
||||
src="https://file.hikmall.com/prod/image/7ea5f88d404442eeb958fbe0904777d1.png"
|
||||
/>
|
||||
<text>门禁点分组</text>
|
||||
<view class="feature-item">
|
||||
<view class="feature-left">
|
||||
<image
|
||||
class="feature-icon"
|
||||
src="https://file.hikmall.com/prod/image/2887bb1c453244a2a872ec98c0360478.png"
|
||||
/>
|
||||
<view class="feature-text">
|
||||
<text class="feature-title">门禁权限组管理</text>
|
||||
<text class="feature-desc">配置人员通行的门与时间规则</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" />
|
||||
</view>
|
||||
|
||||
<!-- 权限查询 -->
|
||||
@ -111,31 +134,6 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部导航 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item active">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png"
|
||||
/>
|
||||
<text>通行权限</text>
|
||||
</view>
|
||||
<view class="tab-item" @click="navigateTo('access-control')">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png"
|
||||
/>
|
||||
<text>门禁控制</text>
|
||||
</view>
|
||||
<view class="tab-item" @click="navigateTo('traffic-record')">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png"
|
||||
/>
|
||||
<text>通行记录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 根据当前组件加载 -->
|
||||
<component :is="currentComponent" />
|
||||
</template>
|
||||
@ -170,40 +168,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
.visitor-card {
|
||||
height: 100%;
|
||||
padding: 16px 16px;
|
||||
margin-top: 12px;
|
||||
background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
border-radius: 12px;
|
||||
|
||||
.banner-content {
|
||||
.card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
|
||||
.banner-text {
|
||||
.card-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 4px;
|
||||
|
||||
.banner-title {
|
||||
.card-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.banner-desc {
|
||||
font-size: 14px;
|
||||
.card-desc {
|
||||
font-size: 10px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-btn {
|
||||
padding: 6px 12px;
|
||||
font-size: 14px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,6 +264,73 @@
|
||||
}
|
||||
}
|
||||
|
||||
.remind-card {
|
||||
height: 100%;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 12px;
|
||||
color: #fff;
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
background-color: #f5f6fa;
|
||||
border-radius: 5px;
|
||||
|
||||
.user-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.user-count {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.check-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.stats-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.stat-num {
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 11px;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.feature-list {
|
||||
// padding: 4px 0;
|
||||
// background-color: #fff;
|
||||
@ -352,36 +412,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 8px 0;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.tab-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,147 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="一键开门" />
|
||||
<view class="container">
|
||||
<view class="search-box">
|
||||
<image class="search-icon" src="/static/images/icon_search.png" mode="aspectFit" />
|
||||
<input type="text" placeholder="输入门禁点名称搜索" placeholder-class="placeholder" />
|
||||
</view>
|
||||
|
||||
<view class="device-list">
|
||||
<view class="device-item">
|
||||
<view class="device-left">
|
||||
<text class="device-name">DS-K(FU6004429)</text>
|
||||
<text class="favorite">☆ 收藏</text>
|
||||
</view>
|
||||
<view class="device-actions">
|
||||
<view class="action-btn">
|
||||
<image class="action-icon" src="/static/images/icon_table_menu.png" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="action-btn">
|
||||
<image class="action-icon" src="/static/images/icon_table_menu.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="device-item">
|
||||
<view class="device-left">
|
||||
<text class="device-name">DS-K(L40959329)</text>
|
||||
<text class="favorite">☆ 收藏</text>
|
||||
</view>
|
||||
<view class="device-actions">
|
||||
<view class="action-btn">
|
||||
<image class="action-icon" src="/static/images/icon_table_menu.png" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="action-btn">
|
||||
<image class="action-icon" src="/static/images/icon_table_menu.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-tip">
|
||||
<text>设备离线无法开门,可使用蓝牙开门</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
margin: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.search-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.device-list {
|
||||
padding: 0 12px;
|
||||
|
||||
.device-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px;
|
||||
margin: 0 4px 12px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.device-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.device-name {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.favorite {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.device-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-right: -4px;
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 50%;
|
||||
|
||||
.action-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-tip {
|
||||
padding: 16px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,146 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="密码开门" />
|
||||
<view class="container">
|
||||
<view class="password-list">
|
||||
<view class="password-card">
|
||||
<view class="help-icon">
|
||||
<text>通行帮助</text>
|
||||
<image src="/static/images/icon_white_tip.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<view class="password-display">
|
||||
<text class="password">742523</text>
|
||||
<image class="eye-icon" src="/static/images/icon_eye.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<view class="password-tip">*请妥善保管密码,勿泄露给他人</view>
|
||||
|
||||
<view class="door-range">
|
||||
<text>门禁范围</text>
|
||||
<image src="/static/images/icon_white_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-button">
|
||||
<button class="refresh-btn" @click="refreshPassword">重新生成密码</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.password-list {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.password-card {
|
||||
position: relative;
|
||||
margin-right: 0;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
border-radius: 12px;
|
||||
|
||||
.help-icon {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 15px 15px 15px 0;
|
||||
font-size: 14px;
|
||||
|
||||
text {
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.password-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.password {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
|
||||
.eye-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.password-tip {
|
||||
margin-bottom: 32px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.door-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 16px;
|
||||
font-size: 14px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
|
||||
text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-button {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
|
||||
.refresh-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
line-height: 44px;
|
||||
color: #fff;
|
||||
background-color: #2b5cff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -12,14 +12,11 @@
|
||||
<TopNavigation :title="titleTab[curIndex]"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view v-if="curIndex == 0">
|
||||
<AccessAuthority />
|
||||
<AccessManage />
|
||||
</view>
|
||||
<view v-else-if="curIndex == 1">
|
||||
<AccessControl />
|
||||
</view>
|
||||
<view v-else-if="curIndex == 2">
|
||||
<TrafficRecord />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<CustomTabBar :list="list" :default-index="0" @change="change"></CustomTabBar>
|
||||
@ -27,24 +24,20 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
// import { onLoad } from '@dcloudio/uni-app'
|
||||
import AccessAuthority from './AccessAuthority/AccessAuthority.vue'
|
||||
// import AccessAuthority from './AccessAuthority/AccessAuthority.vue'
|
||||
import AccessManage from './AccessManage/AccessManage.vue'
|
||||
import AccessControl from './AccessControl/AccessControl.vue'
|
||||
import TrafficRecord from './TrafficRecord/TrafficRecord.vue'
|
||||
import { TabBarItem } from '@/typings'
|
||||
const pages = [AccessAuthority, AccessControl, TrafficRecord]
|
||||
const titleTab = ['通行权限', '门禁控制', '通行记录']
|
||||
// const pages = [AccessAuthority, AccessControl]
|
||||
const titleTab = ['门禁管理', '门禁控制']
|
||||
const list = ref<Array<TabBarItem>>([
|
||||
{
|
||||
title: '通行权限',
|
||||
title: '门禁管理',
|
||||
icon: 'home'
|
||||
},
|
||||
{
|
||||
title: '门禁控制',
|
||||
icon: 'notification'
|
||||
},
|
||||
{
|
||||
title: '通行记录',
|
||||
icon: 'setting'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
type: 'page',
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
@ -8,9 +8,10 @@
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="通行记录"></TopNavigation>
|
||||
<view class="record-container">
|
||||
<!-- 快捷功能区 -->
|
||||
<view class="quick-actions">
|
||||
<!-- <view class="quick-actions">
|
||||
<view class="quick-item" style="background-color: #fff7f2">
|
||||
<view class="quick-content">
|
||||
<text class="quick-title">通行消息提醒</text>
|
||||
@ -25,7 +26,7 @@
|
||||
<image class="quick-icon" src="/static/images/icon_phone_unlock.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 时间筛选 -->
|
||||
<view class="time-filter">
|
||||
@ -80,32 +81,6 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部导航 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png"
|
||||
/>
|
||||
<text>通行权限</text>
|
||||
</view>
|
||||
<view class="tab-item">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png"
|
||||
/>
|
||||
<text>门禁控制</text>
|
||||
</view>
|
||||
<view class="tab-item active">
|
||||
<image
|
||||
class="tab-icon"
|
||||
src="https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png"
|
||||
/>
|
||||
<text>通行记录</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -143,74 +118,74 @@
|
||||
}
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
margin: 12px 0;
|
||||
// .quick-actions {
|
||||
// display: grid;
|
||||
// grid-template-columns: 1fr 1fr;
|
||||
// gap: 12px;
|
||||
// margin: 12px 0;
|
||||
|
||||
.quick-item {
|
||||
position: relative;
|
||||
height: 60px;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
// .quick-item {
|
||||
// position: relative;
|
||||
// height: 60px;
|
||||
// padding: 12px;
|
||||
// border-radius: 8px;
|
||||
|
||||
&:first-child {
|
||||
background-color: #eef4ff;
|
||||
// background: red;
|
||||
.quick-icon {
|
||||
background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
}
|
||||
}
|
||||
// &:first-child {
|
||||
// background-color: #eef4ff;
|
||||
// // background: red;
|
||||
// .quick-icon {
|
||||
// background: linear-gradient(135deg, #4080ff 0%, #2b5cff 100%);
|
||||
// }
|
||||
// }
|
||||
|
||||
&:last-child {
|
||||
background-color: #fff7f2;
|
||||
.quick-icon {
|
||||
background: linear-gradient(135deg, #ff9853 0%, #ff7b30 100%);
|
||||
}
|
||||
}
|
||||
// &:last-child {
|
||||
// background-color: #fff7f2;
|
||||
// .quick-icon {
|
||||
// background: linear-gradient(135deg, #ff9853 0%, #ff7b30 100%);
|
||||
// }
|
||||
// }
|
||||
|
||||
.quick-content {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
// .quick-content {
|
||||
// position: relative;
|
||||
// height: 100%;
|
||||
|
||||
.quick-title {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
// .quick-title {
|
||||
// position: relative;
|
||||
// z-index: 2;
|
||||
// font-size: 15px;
|
||||
// font-weight: 500;
|
||||
// color: #333;
|
||||
// }
|
||||
|
||||
.quick-desc {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
margin-right: 20px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
// .quick-desc {
|
||||
// position: relative;
|
||||
// z-index: 2;
|
||||
// display: block;
|
||||
// margin-top: 8px;
|
||||
// margin-right: 20px;
|
||||
// font-size: 11px;
|
||||
// color: #666;
|
||||
// }
|
||||
|
||||
.quick-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 50%;
|
||||
transform: translateY(-50%);
|
||||
// .quick-icon {
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// right: 0;
|
||||
// z-index: 1;
|
||||
// width: 45px;
|
||||
// height: 45px;
|
||||
// border-radius: 50%;
|
||||
// transform: translateY(-50%);
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// image {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// filter: brightness(0) invert(1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
.time-filter {
|
||||
display: flex;
|
||||
@ -318,36 +293,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 8px 0;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
.tab-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,259 @@
|
||||
<route lang="json5">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="访客邀约">
|
||||
<text class="nav-right-text">生成记录</text>
|
||||
</TopNavigation>
|
||||
<view class="container">
|
||||
<!-- 功能区域 -->
|
||||
<view class="function-area">
|
||||
<view class="function-item">
|
||||
<text class="title">访客码</text>
|
||||
<text class="desc">一键生成,分享权限,扫码通行</text>
|
||||
</view>
|
||||
<view class="function-item">
|
||||
<text class="title">新建邀约</text>
|
||||
<text class="desc">填写表单,短信邀约,灵活通行</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 访客通行凭证 -->
|
||||
<view class="visitor-pass">
|
||||
<view class="pass-header">
|
||||
<image class="pass-icon" src="/static/images/visitor/icon_pass.png" mode="aspectFit" />
|
||||
<text class="title">访客通行凭证</text>
|
||||
<text class="help" @click="showHelp">如何生成访客密码?</text>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<text class="label">到访地址</text>
|
||||
<view class="value">
|
||||
<text>19104656的互联</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">通行方式</text>
|
||||
<view class="value">
|
||||
<text>二维码</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item required">
|
||||
<text class="label">通行有效时段</text>
|
||||
<view class="value">
|
||||
<text>24小时内</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item required">
|
||||
<text class="label">通行次数</text>
|
||||
<view class="value">
|
||||
<text>不限制</text>
|
||||
<image class="arrow" src="/static/images/icon_black_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="tip-text">限制访客在每个门禁点的通行次数</text>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">访客姓名</text>
|
||||
<input class="input" type="text" placeholder="请输入" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">访客手机号</text>
|
||||
<input class="input" type="number" placeholder="请输入" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-bar">
|
||||
<button class="submit-btn" @click="handleSubmit">新建邀约</button>
|
||||
<button class="submit-btn" @click="handleSubmit">立即生成</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const showHelp = () => {
|
||||
// 显示帮助信息
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
// 处理提交
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 12px 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.function-area {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin: 0 32px 12px 0;
|
||||
|
||||
.function-item {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.title {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-pass {
|
||||
margin: 0 32px 0 0;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
|
||||
.pass-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
.pass-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.help {
|
||||
font-size: 14px;
|
||||
color: #2b5cff;
|
||||
}
|
||||
}
|
||||
|
||||
.form-content {
|
||||
padding: 0 16px;
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
&.required .label::before {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
content: '*';
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
padding: 0 12px;
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
display: block;
|
||||
padding: 8px 0;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
padding-bottom: calc(8px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(8px + env(safe-area-inset-bottom));
|
||||
background: #fff;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
|
||||
.submit-btn {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
line-height: 44px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background: #2b5cff;
|
||||
border-radius: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-right-text {
|
||||
padding: 4px 16px 4px 0;
|
||||
margin-right: 16px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,239 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 功能区域 -->
|
||||
<view class="function-area">
|
||||
<view class="function-item">
|
||||
<image
|
||||
class="icon"
|
||||
src="https://file.hikmall.com/prod/image/635392a7f5e04e75bb657b6cc6e2abc8.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<view class="text-wrapper">
|
||||
<text class="title">访客码</text>
|
||||
<text class="desc">分享刷码通行</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="function-item">
|
||||
<image
|
||||
class="icon"
|
||||
src="https://file.hikmall.com/prod/image/d1d07b3125f841848c3c3eb94509b2ae.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<view class="text-wrapper">
|
||||
<text class="title">新建邀约</text>
|
||||
<text class="desc">短信邀约访客</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 访客列表筛选 -->
|
||||
<view class="visitor-filter">
|
||||
<text
|
||||
v-for="(filter, index) in filters"
|
||||
:key="index"
|
||||
:class="['filter-item', { active: currentFilter === index }]"
|
||||
@click="switchFilter(index)"
|
||||
>
|
||||
{{ filter }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 记录列表 -->
|
||||
<view class="record-list">
|
||||
<view v-for="(record, index) in currentRecords" :key="index" class="record-item">
|
||||
<view class="record-number-wrapper">
|
||||
<text class="record-number">{{ record.number }}</text>
|
||||
<text class="visit-time">预约到访时间:{{ record.time }}</text>
|
||||
</view>
|
||||
<text class="status">{{ record.status }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="data-tip">仅展示近6个月数据</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const filters = ref(['全部', '已到访', '待来访', '更多筛选'])
|
||||
const currentFilter = ref(0)
|
||||
|
||||
// 访客记录数据
|
||||
const records = ref([
|
||||
{
|
||||
number: '3',
|
||||
time: '今天 10:57',
|
||||
status: '已失效',
|
||||
type: 'all'
|
||||
},
|
||||
{
|
||||
number: '12',
|
||||
time: '昨天 18:07',
|
||||
status: '已失效',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
number: '123',
|
||||
time: '2024/12/17 10:17',
|
||||
status: '已失效',
|
||||
type: 'all'
|
||||
}
|
||||
])
|
||||
|
||||
// 修改筛选逻辑
|
||||
const currentRecords = computed(() => {
|
||||
switch (currentFilter.value) {
|
||||
case 0: // 全部
|
||||
return records.value
|
||||
case 1: // 已到访
|
||||
return records.value.filter(record => record.type === 'visited')
|
||||
case 2: // 待来访
|
||||
return records.value.filter(record => record.type === 'pending')
|
||||
case 3: // 更多筛选
|
||||
return records.value
|
||||
default:
|
||||
return records.value
|
||||
}
|
||||
})
|
||||
|
||||
const switchFilter = index => {
|
||||
currentFilter.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
// padding: 0 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.function-area {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
margin: 12px 0;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.function-item {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
margin-right: 16px;
|
||||
margin-left: 16px;
|
||||
// padding: 8px 12px;
|
||||
// background: #f8f9fc;
|
||||
// border-radius: 8px;
|
||||
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-filter {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 12px 16px;
|
||||
margin-right: 16px;
|
||||
margin-left: 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px 12px 0 0;
|
||||
|
||||
.filter-item {
|
||||
padding-bottom: 4px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
&.active {
|
||||
color: #2b5cff;
|
||||
border-bottom: 2px solid #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-list {
|
||||
margin-right: 16px;
|
||||
margin-left: 16px;
|
||||
background: #fff;
|
||||
border-radius: 0 0 12px 12px;
|
||||
|
||||
.record-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
.record-number-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.record-number {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.visit-time {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.data-tip {
|
||||
display: block;
|
||||
padding-bottom: 16px;
|
||||
margin-top: 16px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,348 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部标签页 -->
|
||||
<view class="tab-header">
|
||||
<text
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="['tab-item', { active: currentTab === index }]"
|
||||
@click="switchTab(index)"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<view class="content">
|
||||
<image class="illustration" :src="tabs[currentTab].image" mode="aspectFit" />
|
||||
<text class="tip-text">{{ tabs[currentTab].tipText }}</text>
|
||||
<button class="invite-btn">
|
||||
<image src="/static/images/icon_arrow_right_white.png" mode="aspectFit" />
|
||||
{{ tabs[currentTab].buttonText }}
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 访客记录 -->
|
||||
<view class="visitor-record">
|
||||
<view class="record-header">
|
||||
<view class="header-left">
|
||||
<image src="/static/images/icon_record.png" mode="aspectFit" />
|
||||
<text>访客记录</text>
|
||||
</view>
|
||||
<view class="header-right">
|
||||
<text>一键下发</text>
|
||||
<image src="/static/images/icon_send.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 记录筛选 -->
|
||||
<view class="record-filter">
|
||||
<text
|
||||
v-for="(filter, index) in filters"
|
||||
:key="index"
|
||||
:class="['filter-item', { active: currentFilter === index }]"
|
||||
@click="switchFilter(index)"
|
||||
>
|
||||
{{ filter.name }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 记录列表 -->
|
||||
<view class="record-list">
|
||||
<view v-for="(record, index) in currentRecords" :key="index" class="record-item">
|
||||
<view class="record-number-wrapper">
|
||||
<text class="record-number">{{ record.number }}</text>
|
||||
<text class="visit-time">预约到访时间:{{ record.time }}</text>
|
||||
</view>
|
||||
<text class="status">{{ record.status }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text class="data-tip">仅展示近6个月数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const currentTab = ref(0)
|
||||
|
||||
const tabs = ref([
|
||||
{
|
||||
name: '访客自助预约',
|
||||
image: '/static/images/bg_no_device.webp',
|
||||
tipText: '邀请访客自助填写预约信息',
|
||||
buttonText: '去邀请'
|
||||
},
|
||||
{
|
||||
name: '我要邀约访客',
|
||||
image: '/static/images/bg_no_device.webp',
|
||||
tipText: '填写访客信息,短信邀请访客来访',
|
||||
buttonText: '去填写'
|
||||
},
|
||||
{
|
||||
name: '访客签到',
|
||||
image: '/static/images/bg_no_device.webp',
|
||||
tipText: '扫描访客二维码,人工核验签到',
|
||||
buttonText: '扫码核验'
|
||||
}
|
||||
])
|
||||
|
||||
const switchTab = index => {
|
||||
currentTab.value = index
|
||||
}
|
||||
|
||||
// 筛选选项
|
||||
const filters = ref([
|
||||
{ name: '全部', type: 'all' },
|
||||
{ name: '下发异常', type: 'error' },
|
||||
{ name: '更多筛选', type: 'more' }
|
||||
])
|
||||
|
||||
const currentFilter = ref(0)
|
||||
|
||||
// 访客记录数据
|
||||
const records = ref([
|
||||
{
|
||||
number: '3',
|
||||
time: '今天 10:57',
|
||||
status: '已失效',
|
||||
type: 'all'
|
||||
},
|
||||
{
|
||||
number: '12',
|
||||
time: '昨天 18:07',
|
||||
status: '已失效',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
number: '123',
|
||||
time: '2024/12/17 10:17',
|
||||
status: '已失效',
|
||||
type: 'all'
|
||||
}
|
||||
])
|
||||
|
||||
// 根据筛选条件计算显示的记录
|
||||
const currentRecords = computed(() => {
|
||||
const filterType = filters.value[currentFilter.value].type
|
||||
if (filterType === 'all') {
|
||||
return records.value
|
||||
}
|
||||
return records.value.filter(record => record.type === filterType)
|
||||
})
|
||||
|
||||
// 切换筛选
|
||||
const switchFilter = index => {
|
||||
currentFilter.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
// padding: 0 16px;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
display: flex;
|
||||
padding: 12px 0px;
|
||||
margin-right: 16px;
|
||||
margin-left: 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px 12px 0 0;
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
|
||||
&.active {
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
content: '';
|
||||
background-color: #2b5cff;
|
||||
border-radius: 1px;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
margin-right: 16px;
|
||||
margin-left: 16px;
|
||||
background: #fff;
|
||||
border-radius: 0 0 12px 12px;
|
||||
|
||||
.illustration {
|
||||
width: 240px;
|
||||
height: 160px;
|
||||
margin-bottom: 16px;
|
||||
// background-color: red;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
margin-bottom: 24px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.invite-btn {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: calc(100% - 32px);
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background: linear-gradient(90deg, #4080ff, #2b5cff);
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-record {
|
||||
// padding: 0 0 16px;
|
||||
margin: 12px 16px 16px 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.record-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 16px;
|
||||
background-color: #efeefe;
|
||||
border-radius: 12px 12px 0 0;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-filter {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.filter-item {
|
||||
padding-bottom: 4px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
&.active {
|
||||
color: #2b5cff;
|
||||
border-bottom: 2px solid #2b5cff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-list {
|
||||
.record-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
.record-number-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.record-number {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.visit-time {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.data-tip {
|
||||
display: block;
|
||||
padding-bottom: 16px;
|
||||
margin-top: 16px;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,246 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部标签页 -->
|
||||
<view class="tab-header">
|
||||
<text
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="['tab-item', { active: currentTab === index }]"
|
||||
@click="switchTab(index)"
|
||||
>
|
||||
{{ tab }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 设置列表 -->
|
||||
<view class="settings-list">
|
||||
<!-- 访客自助预约设置 -->
|
||||
<view class="setting-group">
|
||||
<view class="setting-item">
|
||||
<text class="label">访客自助预约</text>
|
||||
<switch
|
||||
:checked="settings.selfBooking"
|
||||
@change="e => updateSetting('selfBooking', e.detail.value)"
|
||||
color="#2b5cff"
|
||||
/>
|
||||
</view>
|
||||
<view class="setting-item with-arrow">
|
||||
<text class="label">预约设置</text>
|
||||
<image class="arrow" src="/static/images/icon_arrow_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="setting-item with-arrow">
|
||||
<text class="label">被访人</text>
|
||||
<view class="value">
|
||||
<text>全部成员</text>
|
||||
<image class="arrow" src="/static/images/icon_arrow_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="tip-text">开启后,您可提供预约码给访客,访客微信扫码自助预约</text>
|
||||
</view>
|
||||
|
||||
<!-- 其他设置项 -->
|
||||
<view class="setting-group">
|
||||
<view class="setting-item">
|
||||
<text class="label">成员邀约访客</text>
|
||||
<switch
|
||||
:checked="settings.memberInvite"
|
||||
@change="e => updateSetting('memberInvite', e.detail.value)"
|
||||
color="#2b5cff"
|
||||
/>
|
||||
</view>
|
||||
<view class="setting-item">
|
||||
<text class="label">访客补录信息</text>
|
||||
<switch
|
||||
:checked="settings.infoSupply"
|
||||
@change="e => updateSetting('infoSupply', e.detail.value)"
|
||||
color="#2b5cff"
|
||||
/>
|
||||
</view>
|
||||
<view class="setting-item with-arrow">
|
||||
<text class="label">访问时长</text>
|
||||
<view class="value">
|
||||
<text>最大30天/默认2小时</text>
|
||||
<image class="arrow" src="/static/images/icon_arrow_right.png" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="bottom-tip">
|
||||
开启后,允许成员预约访客,生效后,系统将发送短信。 自定义表单模板,登录PC端:
|
||||
<text class="link">hikiot.com</text>
|
||||
<text class="copy-icon">复制</text>
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="setting-group">
|
||||
<view class="setting-item">
|
||||
<text class="label">访客码</text>
|
||||
<view class="label-with-icon">
|
||||
<image class="info-icon" src="/static/images/icon_info.png" mode="aspectFit" />
|
||||
<switch
|
||||
:checked="settings.visitorCode"
|
||||
@change="e => updateSetting('visitorCode', e.detail.value)"
|
||||
color="#2b5cff"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<text class="tip-text">开启后,允许团队成员快速生成访客码,提供访客通行</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavigation from '@/components/TopNavigation/TopNavigation.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const tabs = ref(['预约方式', '到访通行', '审批设置'])
|
||||
const currentTab = ref(0)
|
||||
|
||||
const settings = ref({
|
||||
selfBooking: false,
|
||||
memberInvite: false,
|
||||
infoSupply: false,
|
||||
visitorCode: false
|
||||
})
|
||||
|
||||
const switchTab = index => {
|
||||
currentTab.value = index
|
||||
}
|
||||
|
||||
const updateSetting = (key, value) => {
|
||||
settings.value[key] = value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
display: flex;
|
||||
padding: 12px 0;
|
||||
margin: 12px 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
|
||||
&.active {
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
content: '';
|
||||
background-color: #2b5cff;
|
||||
border-radius: 1px;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-list {
|
||||
margin: 0 16px;
|
||||
|
||||
.setting-group {
|
||||
padding: 0 16px 12px 12px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.value {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.label-with-icon {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
.info-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&.with-arrow {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-tip {
|
||||
display: block;
|
||||
padding: 12px 0;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
|
||||
.link {
|
||||
color: #2b5cff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
display: inline-block;
|
||||
padding: 2px 4px;
|
||||
margin-left: 4px;
|
||||
color: #2b5cff;
|
||||
background: rgba(43, 92, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
padding: 12px 0;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,65 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-50px)] flex flex-col">
|
||||
<TopNavigation :title="titleTab[curIndex]"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view v-if="curIndex == 0">
|
||||
<VisitorManage />
|
||||
</view>
|
||||
<view v-else-if="curIndex == 1">
|
||||
<MyVisitor />
|
||||
</view>
|
||||
<view v-else-if="curIndex == 2">
|
||||
<VisitorSet />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<CustomTabBar :list="list" :default-index="0" @change="change"></CustomTabBar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// import { onLoad } from '@dcloudio/uni-app'
|
||||
import VisitorManage from './VisitorManage/VisitorManage.vue'
|
||||
import MyVisitor from './MyVisitor/MyVisitor.vue'
|
||||
import VisitorSet from './VisitorSet/VisitorSet.vue'
|
||||
|
||||
import { TabBarItem } from '@/typings'
|
||||
const titleTab = ['访客管理', '我的访客', '访客设置']
|
||||
const list = ref<Array<TabBarItem>>([
|
||||
{
|
||||
title: '首页',
|
||||
icon: 'home'
|
||||
},
|
||||
{
|
||||
title: '我的访客',
|
||||
icon: 'notification'
|
||||
},
|
||||
{
|
||||
title: '访客设置',
|
||||
icon: 'setting'
|
||||
}
|
||||
])
|
||||
|
||||
const curIndex = ref(0)
|
||||
// onLoad(options => {
|
||||
// console.log(`11111:${Number(options.curIndex)}`)
|
||||
// curIndex.value = Number(options.curIndex)
|
||||
// })
|
||||
const change = (data: { value: number }) => {
|
||||
curIndex.value = data.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f6f8fc;
|
||||
}
|
||||
</style>
|
||||
BIN
src/static/images/icon_blue_add.png
Normal file
BIN
src/static/images/icon_blue_add.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/static/images/icon_gray_delet.png
Normal file
BIN
src/static/images/icon_gray_delet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/static/images/icon_gray_tip.png
Normal file
BIN
src/static/images/icon_gray_tip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/static/images/icon_white_tip.png
Normal file
BIN
src/static/images/icon_white_tip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
20
src/types/uni-pages.d.ts
vendored
20
src/types/uni-pages.d.ts
vendored
@ -43,7 +43,25 @@ interface NavigateToOptions {
|
||||
"/pages/attendance/attendance-add-group/attendance-staff" |
|
||||
"/pages/attendance/attendance-add-group/attendance-time" |
|
||||
"/pages/attendance/attendance-add-group/outside-rules" |
|
||||
"/pages/attendance/attendance-add-group/special-date-set";
|
||||
"/pages/attendance/attendance-add-group/special-date-set" |
|
||||
"/pages/personnel-passage/AccessManage/access-permission-inquiry" |
|
||||
"/pages/personnel-passage/AccessManage/access-right-detection" |
|
||||
"/pages/personnel-passage/AccessManage/add-permission-group" |
|
||||
"/pages/personnel-passage/AccessManage/delivery-status" |
|
||||
"/pages/personnel-passage/AccessManage/permission-query" |
|
||||
"/pages/personnel-passage/AccessManage/release-record" |
|
||||
"/pages/personnel-passage/AccessManage/send-permission" |
|
||||
"/pages/personnel-passage/AccessManage/viewing-delivery-records" |
|
||||
"/pages/personnel-passage/access-authority/access-authority" |
|
||||
"/pages/personnel-passage/one-click-open-door/one-click-open-door" |
|
||||
"/pages/personnel-passage/password-open-door/password-open-door" |
|
||||
"/pages/personnel-passage/traffic-record/traffic-record" |
|
||||
"/pages/personnel-passage/visitor-invitation/visitor-invitation" |
|
||||
"/pages/personnel-passage/visitor-manage/visitor-manage-tab" |
|
||||
"/pages/personnel-passage/AccessManage/time-planning-allocation/add-daily-traffic-plan" |
|
||||
"/pages/personnel-passage/AccessManage/time-planning-allocation/add-time-schedule" |
|
||||
"/pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-detail" |
|
||||
"/pages/personnel-passage/AccessManage/time-planning-allocation/time-planning-allocation-list";
|
||||
}
|
||||
interface RedirectToOptions extends NavigateToOptions {}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user