考勤机设置页面搭建
This commit is contained in:
parent
a7f9997a36
commit
b75fbc37cd
|
|
@ -1,4 +1,4 @@
|
|||
# VITE_API_BASE_URL = http://112.29.103.165:1616
|
||||
# VITE_API_BASE_URL = /api
|
||||
VITE_API_BASE_URL = /api
|
||||
# VITE_API_BASE_URL = http://192.168.0.14:1999/hd-realname/prod-api
|
||||
VITE_API_BASE_URL = http://192.168.0.234:38080
|
||||
# VITE_API_BASE_URL = http://192.168.0.234:38080
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
VITE_API_BASE_URL = http://192.168.0.14:1999/hd-realname/prod-api
|
||||
VITE_API_BASE_URL = https://sh.cygrxt.com:19999/hd-realname/prod-api
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "auto"
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ const afterRead = (e) => {
|
|||
// keyInfoForm.value.photoIds = data.data
|
||||
photoIds.value = data.data
|
||||
} else {
|
||||
uni.$u.toast('上传失败:' + data.msg)
|
||||
uni.$u.toast('上传失败')
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
|
|
@ -376,7 +376,7 @@ const afterRead = (e) => {
|
|||
},
|
||||
})
|
||||
} else {
|
||||
uni.$u.toast('人脸识别失败:' + data?.msg)
|
||||
uni.$u.toast('人脸识别失败')
|
||||
keyInfoForm.value.faceImg = []
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ import { ref, watch } from 'vue'
|
|||
import { pathToBase64 } from 'image-tools'
|
||||
import { useMemberStore } from '@/stores'
|
||||
import dayjs from 'dayjs'
|
||||
import { getShanghaiProByIdNumberAPI } from '@/services/person-entry'
|
||||
|
||||
const memberStore = useMemberStore()
|
||||
const idCardFormRef = ref(null) // 身份证表单ref
|
||||
|
|
@ -278,6 +279,35 @@ const onBlurIdNumber = (val) => {
|
|||
idCardModel.value.birthday =
|
||||
birthday?.slice(0, 4) + '-' + birthday.slice(4, 6) + '-' + birthday.slice(6, 8)
|
||||
idCardModel.value.sex = sex % 2 === 0 ? '女' : '男'
|
||||
|
||||
console.log(props.formType, 'props.formType')
|
||||
|
||||
if (props.formType == 1) {
|
||||
checkShanghaiPro()
|
||||
}
|
||||
}
|
||||
|
||||
// 校验身份证号
|
||||
const checkShanghaiPro = async () => {
|
||||
const { data: res } = await getShanghaiProByIdNumberAPI({
|
||||
idNumber: idCardModel.value.idNumber,
|
||||
})
|
||||
// return res
|
||||
|
||||
if (res && Object.keys(res).length > 0 && res.isShanghai == 1) {
|
||||
uni.$u.toast('当前人员已经入场上海工程,可通过后台进行多工程设置...')
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
if (res && Object.keys(res).length > 0 && (res.isShanghai == 0 || res.isShanghai == null)) {
|
||||
uni.$u.toast('当前人员已经存在,可直接编辑')
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: 'pages/person-entry/child-pages/editPerson',
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
// 日期格式化
|
||||
|
|
@ -474,6 +504,10 @@ const props = defineProps({
|
|||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
formType: {
|
||||
type: [Number, String],
|
||||
default: 1,
|
||||
},
|
||||
})
|
||||
|
||||
// 增加监听
|
||||
|
|
|
|||
|
|
@ -169,6 +169,20 @@
|
|||
"navigationBarTitleText": "custom",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
// 考勤机设置
|
||||
{
|
||||
"path": "pages/machine-setting/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "考勤机设置"
|
||||
}
|
||||
},
|
||||
// 考勤机设置 ---- 绑定设置
|
||||
{
|
||||
"path": "pages/machine-setting/components/bindSetting",
|
||||
"style": {
|
||||
"navigationBarTitleText": "考勤机设置"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
|
|
|||
|
|
@ -147,11 +147,11 @@ const onAttendanceHandle = () => {
|
|||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.$u.toast('打卡失败:' + err.msg)
|
||||
uni.$u.toast('打卡失败:' + (err?.msg || ''))
|
||||
},
|
||||
})
|
||||
} else {
|
||||
uni.$u.toast('人脸识别失败,请重新识别' + data?.msg)
|
||||
uni.$u.toast('人脸识别失败,请重新识别' + data.msg === null ? '' : data.msg)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ const onHandleCodeImg = async () => {
|
|||
|
||||
// 登录按钮
|
||||
const onSubmitLogin = debounce(() => {
|
||||
// uni.navigateTo({ url: '/pages/select-project/index' })
|
||||
sendLoading.value = true
|
||||
loginModelRef.value
|
||||
.validate()
|
||||
|
|
@ -182,7 +183,6 @@ const onSubmitLogin = debounce(() => {
|
|||
if (valid) {
|
||||
try {
|
||||
const res = await loginApi(opinionModel.value)
|
||||
|
||||
sendLoading.value = false
|
||||
if (res.code === 200) {
|
||||
memberStore.setToken(res.data.access_token)
|
||||
|
|
@ -199,7 +199,6 @@ const onSubmitLogin = debounce(() => {
|
|||
uni.removeStorageSync('userInfo')
|
||||
}
|
||||
}
|
||||
|
||||
getUserInfo()
|
||||
} else {
|
||||
sendLoading.value = false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,295 @@
|
|||
<template>
|
||||
<view>
|
||||
<!-- 绑定设置 -->
|
||||
<view class="bind-setting-container">
|
||||
<!-- 通讯编码 -->
|
||||
<view class="form-item">
|
||||
<text class="label-text">考勤机编码</text>
|
||||
<text class="value-text">{{ machineInfo.deviceCode }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 考勤机名称 -->
|
||||
<view class="form-item">
|
||||
<text class="label-text">考勤机名称</text>
|
||||
<text class="value-text">{{ machineInfo.deviceName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 点击选择绑定数据提示 -->
|
||||
<view class="select-tip">
|
||||
<text class="tip-text">点击选择绑定数据</text>
|
||||
</view>
|
||||
|
||||
<!-- 工程名称 -->
|
||||
<view class="form-item">
|
||||
<text class="label-text">工程名称</text>
|
||||
<text class="value-text">{{ machineInfo.proName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 分包商名称 -->
|
||||
<view class="form-item select-item" @tap="onSelectSubcontractor">
|
||||
<text class="label-text">分包商名称</text>
|
||||
<view class="select-content">
|
||||
<text class="select-text" :class="{ placeholder: !machineInfo.subName }">
|
||||
{{ machineInfo.subName || '点击选择' }}
|
||||
</text>
|
||||
<up-icon name="arrow-right" size="16" color="#C0C4CC" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 班组名称 -->
|
||||
<view class="form-item select-item" @tap="onSelectTeam">
|
||||
<text class="label-text">班组名称</text>
|
||||
<view class="select-content">
|
||||
<text class="select-text" :class="{ placeholder: !machineInfo.teamName }">
|
||||
{{ machineInfo.teamName || '点击选择' }}
|
||||
</text>
|
||||
<up-icon name="arrow-right" size="16" color="#C0C4CC" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 固定底部按钮 -->
|
||||
<view class="bottom-buttons">
|
||||
<up-button type="warning" text="解除绑定" class="unbind-btn" @tap="onUnbind" />
|
||||
<up-button type="primary" text="确认绑定" class="confirm-btn" @tap="onConfirmBind" />
|
||||
</view>
|
||||
|
||||
<!-- 分包 -->
|
||||
<up-picker
|
||||
:show="subPickerShow"
|
||||
@cancel="onCancelSub"
|
||||
closeOnClickOverlay
|
||||
@confirm="onConfirmSub"
|
||||
:columns="subPickerColumns"
|
||||
@close="subPickerShow = false"
|
||||
/>
|
||||
<!-- 班组 -->
|
||||
<up-picker
|
||||
:show="teamPickerShow"
|
||||
@cancel="onCancelTeam"
|
||||
closeOnClickOverlay
|
||||
@confirm="onConfirmTeam"
|
||||
:columns="teamPickerColumns"
|
||||
@close="teamPickerShow = false"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup name="bindSetting">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getSubcontractorListAPI, getSubTeamContractListAPI } from '@/services/machine-setting'
|
||||
const subPickerShow = ref(false)
|
||||
const teamPickerShow = ref(false)
|
||||
const subPickerColumns = ref([[]])
|
||||
const teamPickerColumns = ref([[]])
|
||||
|
||||
// 考勤机信息
|
||||
const machineInfo = ref({
|
||||
deviceCode: '',
|
||||
deviceName: '',
|
||||
proId: '',
|
||||
proName: '',
|
||||
subId: '',
|
||||
subName: '',
|
||||
teamId: '',
|
||||
teamName: '',
|
||||
})
|
||||
|
||||
// 选择分包商
|
||||
const onSelectSubcontractor = () => {
|
||||
// TODO: 实现分包商选择逻辑
|
||||
subPickerShow.value = true
|
||||
}
|
||||
|
||||
// 选择班组
|
||||
const onSelectTeam = () => {
|
||||
// TODO: 实现班组选择逻辑
|
||||
teamPickerShow.value = true
|
||||
}
|
||||
|
||||
// 获取分包商列表
|
||||
const getSubcontractorListFun = async () => {
|
||||
const res = await getSubcontractorListAPI({ proId: machineInfo.value.proId })
|
||||
subPickerColumns.value[0] = res?.rows?.map((item) => {
|
||||
return {
|
||||
text: item.subName,
|
||||
value: item.id,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取班组列表
|
||||
const getSubTeamContractListFun = async () => {
|
||||
const res = await getSubTeamContractListAPI({
|
||||
proId: machineInfo.value.proId,
|
||||
subId: machineInfo.value.subId,
|
||||
})
|
||||
teamPickerColumns.value[0] = res?.data?.map((item) => {
|
||||
return {
|
||||
text: item.teamName,
|
||||
value: item.teamId,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 解除绑定
|
||||
const onUnbind = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要解除绑定吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// TODO: 实现解除绑定逻辑
|
||||
console.log('解除绑定')
|
||||
uni.showToast({
|
||||
title: '解除绑定成功',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 确认绑定
|
||||
const onConfirmBind = () => {
|
||||
if (!machineInfo.value.subcontractorName) {
|
||||
uni.showToast({
|
||||
title: '请选择分包商',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!machineInfo.value.teamName) {
|
||||
uni.showToast({
|
||||
title: '请选择班组',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 实现确认绑定逻辑
|
||||
console.log('确认绑定', machineInfo.value)
|
||||
uni.showToast({
|
||||
title: '绑定成功',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
const onCancelSub = () => {
|
||||
machineInfo.value.subId = ''
|
||||
machineInfo.value.subName = ''
|
||||
machineInfo.value.teamId = ''
|
||||
machineInfo.value.teamName = ''
|
||||
teamPickerColumns.value[0] = []
|
||||
subPickerShow.value = false
|
||||
}
|
||||
const onConfirmSub = (e) => {
|
||||
machineInfo.value.subId = e.value[0].value
|
||||
machineInfo.value.subName = e.value[0].text
|
||||
subPickerShow.value = false
|
||||
getSubTeamContractListFun()
|
||||
}
|
||||
const onCancelTeam = () => {
|
||||
machineInfo.value.teamId = ''
|
||||
machineInfo.value.teamName = ''
|
||||
teamPickerShow.value = false
|
||||
}
|
||||
const onConfirmTeam = (e) => {
|
||||
machineInfo.value.teamId = e.value[0].value
|
||||
machineInfo.value.teamName = e.value[0].text
|
||||
teamPickerShow.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 获取页面参数
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1]
|
||||
const options = currentPage.options
|
||||
|
||||
if (options.params) {
|
||||
// TODO: 根据ID获取考勤机详细信息
|
||||
console.log('考勤机ID:', JSON.parse(options.params))
|
||||
machineInfo.value = JSON.parse(options.params)
|
||||
getSubcontractorListFun()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.bind-setting-container {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
min-height: calc(100vh - 200rpx);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 0;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
.label-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
max-width: 60%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.select-item {
|
||||
.select-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.select-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&.placeholder {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-tip {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.tip-text {
|
||||
font-size: 24rpx;
|
||||
color: #ff6b6b;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-buttons {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
.unbind-btn {
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
<template>
|
||||
<!-- 考勤机设置 -->
|
||||
<view class="machine-setting">
|
||||
<view class="search-content">
|
||||
<up-input
|
||||
clearable
|
||||
ref="inputRef"
|
||||
class="search-name"
|
||||
v-model="queryParams.deviceName"
|
||||
placeholder="输入考勤机名称"
|
||||
>
|
||||
<template #suffix>
|
||||
<up-icon name="search" size="24" color="#909399" @tap="onSearchName" />
|
||||
</template>
|
||||
</up-input>
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="machine-setting-content"
|
||||
@scrolltolower="onHandleScrollToLower"
|
||||
>
|
||||
<view
|
||||
:key="item.id"
|
||||
class="machine-setting-item"
|
||||
@tap="onMachineSettingItem(item)"
|
||||
v-for="(item, index) in machineList"
|
||||
>
|
||||
<view class="machine-setting-item-header">
|
||||
<text class="index-text"> {{ index + 1 }} </text>
|
||||
<text> {{ item.deviceCode }} </text>
|
||||
</view>
|
||||
|
||||
<view class="common-info common-info-1">
|
||||
<view>
|
||||
<text class="label-text">名称</text>
|
||||
<text> {{ item.deviceName }} </text>
|
||||
</view>
|
||||
<view>
|
||||
<u-tag
|
||||
size="small"
|
||||
:text="item.proId ? '已绑定' : '未绑定'"
|
||||
:type="item.proId ? 'success' : 'error'"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-if="item.proId">
|
||||
<view class="common-info">
|
||||
<text class="label-text">所在工程</text>
|
||||
<text class="value-text">{{ item.proName }}</text>
|
||||
</view>
|
||||
<view class="common-info">
|
||||
<text class="label-text">所属分包</text>
|
||||
<text class="value-text">{{ item.subName }}</text>
|
||||
</view>
|
||||
<view class="common-info">
|
||||
<text class="label-text">所在班组</text>
|
||||
<text class="value-text">{{ item.teamName }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="loading-text">
|
||||
{{ !hasMore ? '没有更多数据了~' : '正在加载...' }}
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view v-if="total === 10" class="empty-content">
|
||||
<up-empty :icon="Empty" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup name="machineSetting">
|
||||
import { debounce } from 'lodash-es'
|
||||
import { ref, computed, onMounted, nextTick } from 'vue'
|
||||
import { getMachineListAPI } from '@/services/machine-setting.js'
|
||||
import { useCommonStore } from '@/stores'
|
||||
|
||||
import Empty from '@/static/image/Empty.png'
|
||||
|
||||
const inputRef = ref(null) // 输入框
|
||||
const machineList = ref([]) // 考勤机列表
|
||||
const total = ref(0) // 总条数
|
||||
|
||||
const commonStore = useCommonStore() // 工程信息
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
deviceName: '',
|
||||
})
|
||||
|
||||
// 搜索姓名
|
||||
const onSearchName = () => {
|
||||
queryParams.value.pageNum = 1
|
||||
machineList.value = []
|
||||
|
||||
getMachineListFun()
|
||||
}
|
||||
|
||||
// 获取考勤机列表数据
|
||||
const getMachineListFun = async () => {
|
||||
const res = await getMachineListAPI(queryParams.value)
|
||||
total.value = res?.total
|
||||
machineList.value = [...machineList.value, ...res?.rows]
|
||||
}
|
||||
|
||||
// 滚动到底部
|
||||
const onHandleScrollToLower = debounce(() => {
|
||||
if (hasMore.value) {
|
||||
queryParams.value.pageNum++
|
||||
getMachineListFun()
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
// 计算一下是否还有更多数据
|
||||
const hasMore = computed(() => {
|
||||
return machineList.value.length < total.value
|
||||
})
|
||||
|
||||
// 点击考勤机设置
|
||||
const onMachineSettingItem = (item) => {
|
||||
const { deviceCode, deviceName, proId, proName, subId, subName, teamId, teamName } = item
|
||||
const params = {
|
||||
deviceCode,
|
||||
deviceName,
|
||||
proId,
|
||||
proName,
|
||||
subId,
|
||||
subName,
|
||||
teamId,
|
||||
teamName,
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/machine-setting/components/bindSetting?params=${JSON.stringify(params)}`,
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
queryParams.value.proName = commonStore?.activeProjectName
|
||||
getMachineListFun()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.machine-setting {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.search-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.status-select {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e5e5e5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .u-select__content .u-select__options__wrap {
|
||||
top: 30px !important;
|
||||
right: -30px !important;
|
||||
}
|
||||
|
||||
.machine-setting-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
||||
.machine-setting-item {
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border: 1px solid #e5e5e5;
|
||||
box-shadow: 0 0 10rpx 2rpx rgba(0, 0, 0, 0.1);
|
||||
font-size: 14px;
|
||||
|
||||
.machine-setting-item-header {
|
||||
padding: 16rpx 0;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.index-text {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: 60rpx;
|
||||
width: 50rpx;
|
||||
margin-right: 60rpx;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 60rpx;
|
||||
border-top-left-radius: 10rpx;
|
||||
border-bottom-left-radius: 10rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.index-text::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -24rpx; /* 三角形宽度的一半 */
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 30rpx solid transparent; /* 高度的一半 */
|
||||
border-bottom: 30rpx solid transparent; /* 高度的一半 */
|
||||
border-left: 30rpx solid #409eff; /* 三角形宽度 */
|
||||
}
|
||||
|
||||
& text:last-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.common-info {
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.common-info-1 view {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.value-text {
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -79,7 +79,7 @@ const queryParams = ref({
|
|||
pageNum: 1,
|
||||
pageSize: 12,
|
||||
workerName: '',
|
||||
proName: commonStore?.activeProjectName,
|
||||
// proName: commonStore?.activeProjectName,
|
||||
})
|
||||
|
||||
// 获取人员列表
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ const onFaceRecognition = () => {
|
|||
})
|
||||
}, 500)
|
||||
} else {
|
||||
uni.$u.toast('人脸识别失败,请重新识别' + data?.msg)
|
||||
uni.$u.toast('人脸识别失败,请重新识别' + data.msg === null ? '' : data.msg)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
|
|
|
|||
|
|
@ -1,73 +1,81 @@
|
|||
<template>
|
||||
<!-- 新增和修改人员信息 -->
|
||||
|
||||
<NavBarModal :navBarTitle="navBarTitle" />
|
||||
<view
|
||||
class="add-person-container"
|
||||
:style="{
|
||||
paddingBottom: nextBtnHeight + 'px',
|
||||
paddingTop: safeAreaInsets?.top + paddingTop + 'px',
|
||||
}"
|
||||
>
|
||||
<!-- 步骤条 -->
|
||||
<view>
|
||||
<up-steps :current="currentStep">
|
||||
<up-steps-item
|
||||
:key="item.title"
|
||||
:title="item.title"
|
||||
:error="item.isError"
|
||||
v-for="item in stepList"
|
||||
<view>
|
||||
<NavBarModal :navBarTitle="navBarTitle" />
|
||||
<view
|
||||
class="add-person-container"
|
||||
:style="{
|
||||
paddingBottom: nextBtnHeight + 'px',
|
||||
paddingTop: safeAreaInsets?.top + paddingTop + 'px',
|
||||
}"
|
||||
>
|
||||
<!-- 步骤条 -->
|
||||
<view>
|
||||
<up-steps :current="currentStep">
|
||||
<up-steps-item
|
||||
:key="item.title"
|
||||
:title="item.title"
|
||||
:error="item.isError"
|
||||
v-for="item in stepList"
|
||||
/>
|
||||
</up-steps>
|
||||
</view>
|
||||
|
||||
<view class="person-info-container">
|
||||
<PersonIdCardForm
|
||||
ref="personIdCardFormRef"
|
||||
:idCardInfo="idCardInfo"
|
||||
:formType="formType"
|
||||
v-if="currentStep === 0"
|
||||
/>
|
||||
</up-steps>
|
||||
</view>
|
||||
<KeyInfoForm
|
||||
:keyInfo="keyInfo"
|
||||
:formType="formType"
|
||||
v-if="currentStep === 1"
|
||||
ref="personKeyInfoFormRef"
|
||||
/>
|
||||
<ContractForm
|
||||
v-if="currentStep === 2"
|
||||
ref="personContractFormRef"
|
||||
:contractInfo="contractInfo"
|
||||
:contractImageList="contractImageList"
|
||||
:isEditContractStatus="isEditContractStatus"
|
||||
/>
|
||||
<WageCardForm
|
||||
:formType="formType"
|
||||
ref="personWageCardFormRef"
|
||||
:wageCardInfo="wageCardInfo"
|
||||
:wageCardImageList="wageCardImageList"
|
||||
v-if="currentStep === 3"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="person-info-container">
|
||||
<PersonIdCardForm
|
||||
ref="personIdCardFormRef"
|
||||
:idCardInfo="idCardInfo"
|
||||
v-if="currentStep === 0"
|
||||
/>
|
||||
<KeyInfoForm ref="personKeyInfoFormRef" :keyInfo="keyInfo" v-if="currentStep === 1" />
|
||||
<ContractForm
|
||||
v-if="currentStep === 2"
|
||||
ref="personContractFormRef"
|
||||
:contractInfo="contractInfo"
|
||||
:contractImageList="contractImageList"
|
||||
:isEditContractStatus="isEditContractStatus"
|
||||
/>
|
||||
<WageCardForm
|
||||
:formType="formType"
|
||||
ref="personWageCardFormRef"
|
||||
:wageCardInfo="wageCardInfo"
|
||||
:wageCardImageList="wageCardImageList"
|
||||
v-if="currentStep === 3"
|
||||
<view class="next-btn" ref="nextBtnRef">
|
||||
<up-button
|
||||
color="#0ab99c"
|
||||
text="上一步"
|
||||
@tap="onHandlePrev"
|
||||
v-if="currentStep > 0"
|
||||
style="margin-right: 10px"
|
||||
/>
|
||||
<up-button
|
||||
type="primary"
|
||||
@tap="onHandleNext"
|
||||
:text="currentStep === 3 ? '提交' : '下一步'"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<up-loading-icon
|
||||
:vertical="true"
|
||||
duration="2000"
|
||||
color="#3c9cff"
|
||||
:show="showLoading"
|
||||
textColor="#3c9cff"
|
||||
text="数据正在提交,请稍后..."
|
||||
style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="next-btn" ref="nextBtnRef">
|
||||
<up-button
|
||||
color="#0ab99c"
|
||||
text="上一步"
|
||||
@tap="onHandlePrev"
|
||||
v-if="currentStep > 0"
|
||||
style="margin-right: 10px"
|
||||
/>
|
||||
<up-button
|
||||
type="primary"
|
||||
@tap="onHandleNext"
|
||||
:text="currentStep === 3 ? '提交' : '下一步'"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<up-loading-icon
|
||||
:vertical="true"
|
||||
duration="2000"
|
||||
color="#3c9cff"
|
||||
:show="showLoading"
|
||||
textColor="#3c9cff"
|
||||
text="数据正在提交,请稍后..."
|
||||
style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -76,9 +84,12 @@ import { useCommonStore } from '@/stores'
|
|||
import { pathToBase64 } from 'image-tools'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref, onMounted, nextTick } from 'vue'
|
||||
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from '@/utils/sm'
|
||||
import { getPersonInfoByIdAPI, updatePersonLightStatusApi } from '@/services/person-entry'
|
||||
import { addPersonEntryApi, editPersonEntryApi } from '@/services/person-entry'
|
||||
import {
|
||||
getPersonInfoByIdAPI,
|
||||
updatePersonLightStatusApi,
|
||||
addPersonEntryApi,
|
||||
editPersonEntryApi,
|
||||
} from '@/services/person-entry'
|
||||
|
||||
import PersonIdCardForm from '@/components/PersonIdCardForm/index.vue'
|
||||
import KeyInfoForm from '@/components/KeyInfoForm/index.vue'
|
||||
|
|
@ -341,7 +352,7 @@ const getButtonHeight = () => {
|
|||
|
||||
// 获取人员信息
|
||||
const getPersonInfoByIdFun = async (id) => {
|
||||
const res = await getPersonInfoByIdAPI({ id })
|
||||
const res = await getPersonInfoByIdAPI({ id, proId: commonStore?.activeProjectId })
|
||||
|
||||
if (res.code === 200) {
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ const handleTapPersonEntry = (item) => {
|
|||
})
|
||||
}, 500)
|
||||
} else {
|
||||
uni.$u.toast('人脸识别失败,请重新识别' + data?.msg)
|
||||
uni.$u.toast(
|
||||
'人脸识别失败,请重新识别' + data.msg === null ? '' : data.msg,
|
||||
)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
</up-input>
|
||||
</view>
|
||||
|
||||
<view class="my-project-list">
|
||||
<view class="my-project-list" v-if="projectList.length > 0">
|
||||
<view
|
||||
class="project-item"
|
||||
:key="item.id"
|
||||
|
|
@ -21,6 +21,11 @@
|
|||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="empty-container">
|
||||
<up-empty text="暂无工程,可登录后台管理平台创建" />
|
||||
<up-button type="primary" text="跳转首页..." @tap="onJumpHome" />
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</template>
|
||||
|
|
@ -70,6 +75,11 @@ const getProjectList = async () => {
|
|||
})
|
||||
}
|
||||
|
||||
// 跳转首页
|
||||
const onJumpHome = () => {
|
||||
uni.switchTab({ url: '/pages/home/index' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getProjectList()
|
||||
})
|
||||
|
|
@ -110,5 +120,22 @@ onMounted(() => {
|
|||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20rpx;
|
||||
.up-empty {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.up-button {
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<!-- 工作台 -->
|
||||
<view>
|
||||
<up-grid :col="4" class="work-grid">
|
||||
<up-grid :col="4" class="work-grid" gap="20px">
|
||||
<up-grid-item v-for="(item, index) in workList" :key="index" @tap="handleTap(item)">
|
||||
<view class="icon-box" :style="{ backgroundColor: item.bgc_color }">
|
||||
<image :src="item.icon" mode="widthFix" class="icon-img" />
|
||||
|
|
@ -17,6 +17,7 @@ import EntryIcon from '@/static/image/work/entry.png'
|
|||
import ExitIcon from '@/static/image/work/exit.png'
|
||||
import CheckIcon from '@/static/image/work/check.png'
|
||||
import CountIcon from '@/static/image/work/count.png'
|
||||
import MachineSettingIcon from '@/static/image/work/machine-setting.png'
|
||||
|
||||
const workList = [
|
||||
{
|
||||
|
|
@ -51,6 +52,14 @@ const workList = [
|
|||
icon: CountIcon,
|
||||
url: '/pages/att-count/index',
|
||||
},
|
||||
{
|
||||
name: 'machineSetting',
|
||||
title: '考勤机设置',
|
||||
icon: 'machineSetting',
|
||||
bgc_color: '#eaf4d9',
|
||||
icon: MachineSettingIcon,
|
||||
url: '/pages/machine-setting/index',
|
||||
},
|
||||
]
|
||||
|
||||
// 点击跳转
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import { http } from '@/utils/http'
|
||||
|
||||
// 获取考勤机列表
|
||||
export const getMachineListAPI = (data) => {
|
||||
return http({
|
||||
method: 'GET',
|
||||
url: `bmw/pmAttDevice/list`,
|
||||
data,
|
||||
})
|
||||
}
|
||||
// 考勤机解除绑定
|
||||
export const getMachineUnbindAPI = (data) => {
|
||||
return http({
|
||||
method: 'GET',
|
||||
url: `/bmw/worker/**`,
|
||||
data,
|
||||
})
|
||||
}
|
||||
// 考勤机确认绑定
|
||||
export const getMachineConfirmBindAPI = (data) => {
|
||||
return http({
|
||||
method: 'GET',
|
||||
url: `/bmw/worker/**`,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// 根据工程ID获取分包商
|
||||
export const getSubcontractorListAPI = (data) => {
|
||||
return http({
|
||||
method: 'GET',
|
||||
url: 'bmw/pmSub/getSublistByProId',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// 根据工程ID和分包商ID获取班组
|
||||
export const getSubTeamContractListAPI = (data) => {
|
||||
return http({
|
||||
method: 'GET',
|
||||
url: `/bmw/subTeamContract/getSubTeamContractList`,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ export const getPersonListAPI = (data) => {
|
|||
export const getPersonInfoByIdAPI = (data) => {
|
||||
return http({
|
||||
method: 'POST',
|
||||
url: '/bmw/worker/select/' + data?.id,
|
||||
url: `/bmw/worker/select/${data?.id}/${data.proId}`,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
|
@ -55,3 +55,12 @@ export const editPersonEntryExitApi = (data) => {
|
|||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// 获取上海工程人员信息
|
||||
export const getShanghaiProByIdNumberAPI = (data) => {
|
||||
return http({
|
||||
url: `/bmw/worker/selectByIdNumber/${data.idNumber}`,
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
|
|
@ -70,28 +70,32 @@ const httpInterceptor = {
|
|||
|
||||
const commonStore = useCommonStore() // 请求配置
|
||||
const requestConfig = commonStore.requestConfig // 请求配置
|
||||
const env = import.meta.env.MODE
|
||||
|
||||
// 5. 增加请求配置
|
||||
// 入参加密
|
||||
options.header['encryptRequest'] = requestConfig.encryptRequest
|
||||
options.header['encryptRequest'] =
|
||||
import.meta.env.MODE === 'development' ? false : requestConfig.encryptRequest
|
||||
// 数据完整性校验
|
||||
options.header['checkIntegrity'] = requestConfig.checkIntegrity
|
||||
options.header['checkIntegrity'] =
|
||||
import.meta.env.MODE === 'development' ? false : requestConfig.checkIntegrity
|
||||
//回参是否加密
|
||||
options.header['encryptResponse'] = requestConfig.encryptResponse
|
||||
options.header['encryptResponse'] =
|
||||
import.meta.env.MODE === 'development' ? false : requestConfig.encryptResponse
|
||||
|
||||
const queryData =
|
||||
options.data instanceof Object ? JSON.stringify(options.data) : options.data
|
||||
|
||||
if (typeof queryData !== 'undefined' && options.method.toUpperCase() === 'POST') {
|
||||
// 加密数据
|
||||
if (requestConfig.encryptRequest) {
|
||||
if (requestConfig.encryptRequest && env !== 'development') {
|
||||
options.data = encryptWithSM4(queryData + '|' + hashWithSM3AndSalt(queryData))
|
||||
}
|
||||
}
|
||||
|
||||
if (options.data instanceof Object && options.method.toUpperCase() === 'GET') {
|
||||
// 加密数据
|
||||
if (requestConfig.encryptRequest) {
|
||||
if (requestConfig.encryptRequest && env !== 'development') {
|
||||
const url =
|
||||
options.url + '?' + tansParams(options.data, requestConfig.encryptRequest)
|
||||
|
||||
|
|
@ -99,8 +103,6 @@ const httpInterceptor = {
|
|||
options.url = url
|
||||
}
|
||||
}
|
||||
|
||||
console.log(options, 'options--**----')
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -117,7 +119,6 @@ export const http = (options) => {
|
|||
success(res) {
|
||||
console.log(res, '请求拦截器处解密后的返回值')
|
||||
const currentEnv = getCurrentEnv()
|
||||
console.log(currentEnv, 'currentEnv')
|
||||
// 判断是H5 还是App环境
|
||||
let isEncryptResponse = ''
|
||||
if (currentEnv === 'windows') {
|
||||
|
|
@ -127,8 +128,6 @@ export const http = (options) => {
|
|||
}
|
||||
|
||||
if (res.header[isEncryptResponse]) {
|
||||
console.log(JSON.parse(decryptWithSM4(res.data)), '解密后')
|
||||
|
||||
res.data = JSON.parse(decryptWithSM4(res.data))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default defineConfig({
|
|||
'/api': {
|
||||
// target: 'http://112.29.103.165:1616', // 测试环境
|
||||
// target: 'http://192.168.0.133:58080', // 梁超
|
||||
target: 'http://192.168.0.14:1999/hd-realname/prod-api', // 测试环境
|
||||
target: 'http://192.168.0.14:1999/hd-real-name', // 测试环境
|
||||
// target: 'http://192.168.0.234:38080', // 方亮
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue