考勤机设置页面搭建

This commit is contained in:
BianLzhaoMin 2025-10-21 10:17:28 +08:00
parent a7f9997a36
commit b75fbc37cd
21 changed files with 799 additions and 99 deletions

View File

@ -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

View File

@ -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

View File

@ -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"
}

View File

@ -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 = []
}
},

View File

@ -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,
},
})
//

View File

@ -169,6 +169,20 @@
"navigationBarTitleText": "custom",
"navigationStyle": "custom"
}
},
//
{
"path": "pages/machine-setting/index",
"style": {
"navigationBarTitleText": "考勤机设置"
}
},
// ----
{
"path": "pages/machine-setting/components/bindSetting",
"style": {
"navigationBarTitleText": "考勤机设置"
}
}
],
"globalStyle": {

View File

@ -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) => {

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -79,7 +79,7 @@ const queryParams = ref({
pageNum: 1,
pageSize: 12,
workerName: '',
proName: commonStore?.activeProjectName,
// proName: commonStore?.activeProjectName,
})
//

View File

@ -61,7 +61,7 @@ const onFaceRecognition = () => {
})
}, 500)
} else {
uni.$u.toast('人脸识别失败,请重新识别' + data?.msg)
uni.$u.toast('人脸识别失败,请重新识别' + data.msg === null ? '' : data.msg)
}
},
fail: (err) => {

View File

@ -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 {

View File

@ -96,7 +96,9 @@ const handleTapPersonEntry = (item) => {
})
}, 500)
} else {
uni.$u.toast('人脸识别失败,请重新识别' + data?.msg)
uni.$u.toast(
'人脸识别失败,请重新识别' + data.msg === null ? '' : data.msg,
)
}
},
fail: (err) => {

View File

@ -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>

View File

@ -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',
},
]
//

View File

@ -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,
})
}

View File

@ -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

View File

@ -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))
}

View File

@ -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) => {