feat: 1.班次管理 2.新增班次

This commit is contained in:
米子豪 2025-01-06 17:21:30 +08:00
parent 6dafdd6bc2
commit 5265a7c1c6
12 changed files with 363 additions and 38 deletions

View File

@ -109,6 +109,7 @@
"@dcloudio/vite-plugin-uni": "3.0.0-4020920240930001",
"@esbuild/darwin-arm64": "0.20.2",
"@esbuild/darwin-x64": "0.20.2",
"@iconify-json/bytesize": "^1.2.2",
"@iconify-json/carbon": "^1.2.4",
"@rollup/rollup-darwin-x64": "^4.28.0",
"@types/node": "^20.17.9",

20
pnpm-lock.yaml generated
View File

@ -72,8 +72,8 @@ importers:
specifier: 3.4.21
version: 3.4.21(typescript@5.7.2)
wot-design-uni:
specifier: 1.5.1
version: 1.5.1(vue@3.4.21(typescript@5.7.2))
specifier: 1.4.0
version: 1.4.0(vue@3.4.21(typescript@5.7.2))
z-paging:
specifier: ^2.8.4
version: 2.8.4
@ -105,6 +105,9 @@ importers:
'@esbuild/darwin-x64':
specifier: 0.20.2
version: 0.20.2
'@iconify-json/bytesize':
specifier: ^1.2.2
version: 1.2.2
'@iconify-json/carbon':
specifier: ^1.2.4
version: 1.2.4
@ -1223,6 +1226,9 @@ packages:
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
deprecated: Use @eslint/object-schema instead
'@iconify-json/bytesize@1.2.2':
resolution: {integrity: sha512-lI/wtPosh84caAS+UcudpeKiQk9ShfVoeaUTtzgOOBUhwQvjDuSiiHqe84v5NluHuIIFW64Fa3kuoGoluxWgpA==}
'@iconify-json/carbon@1.2.4':
resolution: {integrity: sha512-DhW2jjMVGwV0DLHc0cmDYohdtGxMra8UuwgjHrryPy+rQX4gXhJwCBBVP2h2UG/92AoRCTn7zUJve4WvY5MLYg==}
@ -5456,8 +5462,8 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
wot-design-uni@1.5.1:
resolution: {integrity: sha512-jiDRuF8r7+xAldc4Dp+2T1VnqDnOoMWsXu6aRpDg2QG7ZH+/bJl7W8H8hHbKFgA9lu1By/HCDmpG7JC45nYtBw==}
wot-design-uni@1.4.0:
resolution: {integrity: sha512-h6sjrgfg7mP0nJwGTiHn/iTLPFyRswMpQV6MKhWN3skTnXe+FAyndvtXofpXp+uLkTXefGfw5BPI0uuCMD874w==}
engines: {HBuilderX: ^3.8.7}
peerDependencies:
vue: '>=3.2.47'
@ -7190,6 +7196,10 @@ snapshots:
'@humanwhocodes/object-schema@2.0.3': {}
'@iconify-json/bytesize@1.2.2':
dependencies:
'@iconify/types': 2.0.0
'@iconify-json/carbon@1.2.4':
dependencies:
'@iconify/types': 2.0.0
@ -12236,7 +12246,7 @@ snapshots:
word-wrap@1.2.5: {}
wot-design-uni@1.5.1(vue@3.4.21(typescript@5.7.2)):
wot-design-uni@1.4.0(vue@3.4.21(typescript@5.7.2)):
dependencies:
vue: 3.4.21(typescript@5.7.2)

View File

@ -1,8 +1,11 @@
<template>
<view class="mx-2">
<view class="flex flex-row items-center py-4">
<view class="flex flex-row items-center py-3.5">
<view class="mr-0.5" :class="isMust ? 'color-red' : 'color-transparent'">*</view>
<view>{{ text }}</view>
<view v-if="text">{{ text }}</view>
<view v-if="$slots.leftChild">
<slot name="leftChild"></slot>
</view>
<view v-if="$slots.child" class="flex-1 flex flex-row mx-2">
<slot name="child" class="flex-1"></slot>
</view>

View File

@ -25,7 +25,10 @@
</view>
<view class="text-gray mt-4 ml-3 text-3 mb-2">其他设置</view>
<view class="flex flex-row flex-justify-between">
<view class="p-3.5 bg-white rounded-1.2 flex-1 mr-1 flex flex-row items-center">
<view
@click="goClasses()"
class="p-3.5 bg-white rounded-1.2 flex-1 mr-1 flex flex-row items-center"
>
<image src="/static/images/icon_wechat.png" class="w-6 h-6 mr-2" />
<view class="text-3">班次管理</view>
</view>
@ -57,6 +60,8 @@
</template>
<script lang="ts" setup>
import { TabBarItem } from '@/typings'
const list = ref<Array<TabBarItem>>([
{
title: '首页',
@ -86,6 +91,12 @@
url: '/pages/attendance/attendance-add-group/attendance-add-group'
})
}
const goClasses = () => {
console.log('goClasses')
uni.navigateTo({
url: '/pages/attendance/classes-manage'
})
}
</script>
<style lang="scss" scoped></style>

View File

@ -8,7 +8,6 @@
</route>
<template>
<TopNavigation title="添加考勤组"></TopNavigation>
<BottomPop
:show="showType"
title="考勤类型"
@ -84,20 +83,27 @@
</template>
</BottomPop>
<TopNavigation title="添加考勤组"></TopNavigation>
<view class="h-[calc(100vh-60px)] p-3 box-border">
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="考勤组名称" isMust value="有多少">
<template v-slot:child>
<input
class="text-right w-100%"
v-model="name"
placeholder="必填"
placeholder-class="color-gray"
@input="nameInput()"
:maxlength="15"
/>
</template>
</CommonItem>
<CommonItem text="考勤组名称" isMust :isNext="false" value="" hint="" noLine></CommonItem>
<view class="flex items-center px-4.3 pb-3 box-border">
<input
class="w-100%"
v-model="name"
placeholder="必填"
placeholder-class="color-gray"
:maxlength="15"
@input="nameInput"
/>
<view
@click="name = ''"
v-show="name"
class="i-carbon-close-filled color-gray text-4"
></view>
<view class="text-3 self-center color-gray ml-1">{{ name.length }}/{{ 15 }}</view>
</view>
<view class="hpx bg-gray-100 mx-2.5"></view>
<CommonItem
@click="
() => {
@ -110,7 +116,7 @@
></CommonItem>
</view>
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="考勤人员" isMust value=""></CommonItem>
<CommonItem @click="goStaff()" text="考勤人员" isMust value=""></CommonItem>
<CommonItem text="考勤时间" noLine value="周一至周五,09:00-17:00"></CommonItem>
</view>
<view class="bg-white rounded-1.2 mt-2">
@ -133,13 +139,15 @@
<CommonItem text="打卡地点" v-show="wayIndex == 1" value="" hint="未设置"></CommonItem>
<CommonItem text="打卡WIFI" v-show="wayIndex == 1" noLine value="" hint="未设置"></CommonItem>
</view>
<view @click="goOtsideRule()" v-show="wayIndex == 1" class="bg-white rounded-1.2 mt-2">
<view @click="goOutsideRule()" v-show="wayIndex == 1" class="bg-white rounded-1.2 mt-2">
<CommonItem text="外勤规则" noLine value="允许外勤卡" hint=""></CommonItem>
</view>
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="加班统计规则" noLine value="未开启" hint=""></CommonItem>
</view>
<view class="fixed bottom-0 left-0 w-full p-3 box-border">
<view
class="fixed bottom-0 left-0 w-full p-3 box-border border-solid border-0 border-t-1 border-gray-200"
>
<wd-button block>保存</wd-button>
</view>
</view>
@ -190,11 +198,16 @@
remark: false,
selectPhoto: false
}
const goOtsideRule = () => {
const goOutsideRule = () => {
uni.navigateTo({
url: '/pages/attendance/attendance-add-group/outside-rules'
})
}
const goStaff = () => {
uni.navigateTo({
url: '/pages/attendance/attendance-add-group/attendance-staff'
})
}
</script>
<style lang="scss" scoped>

View File

@ -0,0 +1,28 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationStyle: 'custom'
}
}
</route>
<template>
<TopNavigation title="考勤人员"></TopNavigation>
<view class="h-[calc(100vh-60px)] p-3 box-border">
<view class="bg-white flex flex flex-row flex-justify-center items-center rounded-1 py-1.5">
<wd-icon name="search" class="color-gray text-3.3 ml-2"></wd-icon>
<view class="color-gray ml-2">搜索</view>
</view>
</view>
</template>
<script lang="ts" setup>
//
</script>
<style lang="scss" scoped>
page {
background-color: #f6f8fc;
}
</style>

View File

@ -13,39 +13,44 @@
<view class="bg-white rounded-1.2">
<CommonItem text="允许外勤打卡" noLine value="">
<template v-slot:child>
<wd-switch v-model="checked" class="ml-a" />
<wd-switch v-model="outsideRules.allow" class="ml-a" />
</template>
</CommonItem>
</view>
<view class="bg-white rounded-1.2 mt-2">
<view v-show="outsideRules.allow" class="bg-white rounded-1.2 mt-2">
<CommonItem text="外勤打卡必须拍照" value="">
<template v-slot:child>
<wd-switch v-model="checked" class="ml-a" />
<wd-switch v-model="outsideRules.takePhoto" class="ml-a" />
</template>
</CommonItem>
<CommonItem text="外勤卡必须填写备注" value="">
<template v-slot:child>
<wd-switch v-model="checked" class="ml-a" />
<wd-switch v-model="outsideRules.remark" class="ml-a" />
</template>
</CommonItem>
<CommonItem text="允许从手机相册选择照片" noLine value="">
<template v-slot:child>
<wd-switch v-model="checked" class="ml-a" />
<wd-switch v-model="outsideRules.selectPhoto" class="ml-a" />
</template>
</CommonItem>
</view>
<view class=""></view>
<view
class="fixed bottom-0 left-0 w-full p-3 box-border border-solid border-0 border-t-1 border-gray-200"
>
<wd-button block>保存</wd-button>
</view>
</view>
</template>
<script lang="ts" setup>
import CommonItem from '@/components/CommonItemItem/CommonItem.vue'
import { OutsideRules } from '@/typings'
const checked = ref(false)
const props = defineProps({
outsideRules: {
type: OutsideRules,
default: () => ({})
}
const outsideRules = ref<OutsideRules>({
allow: false,
takePhoto: false,
remark: false,
selectPhoto: false
})
</script>

View File

@ -21,6 +21,7 @@
import AttendanceClockIn from './AttendanceClockIn.vue'
import AttendanceStatistics from './AttendanceStatistics.vue'
import AttendanceSet from './AttendanceSet.vue'
import { TabBarItem } from '@/typings'
const pages = [AttendanceClockIn, AttendanceStatistics, AttendanceSet]
const titleTab = ['考勤打卡', '考勤统计', '设置']
const list = ref<Array<TabBarItem>>([

View File

@ -0,0 +1,97 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationStyle: 'custom'
}
}
</route>
<template>
<TopNavigation title="新增班次"></TopNavigation>
<view class="h-[calc(100vh-60px)] p-3 box-border">
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="考勤组名称" isMust :isNext="false" value="" hint="" noLine></CommonItem>
<view class="flex items-center px-4.3 pb-3 box-border">
<input
class="w-100%"
v-model="name"
placeholder="必填"
placeholder-class="color-gray"
:maxlength="8"
/>
<view
@click="name = ''"
v-show="name"
class="i-carbon-close-filled color-gray text-4"
></view>
<view class="text-3 self-center color-gray ml-1">{{ name.length }}/{{ 8 }}</view>
</view>
</view>
<view v-for="(item, index) in times" :key="index">
<view class="flex items-center my-3 flex-justify-between text-3">
<view class="color-gray ml-4.2">上下班时段{{ index + 1 }}</view>
<view v-show="times.length > 1" @click="times.splice(index, 1)" class="color-red mr-4">
删除
</view>
</view>
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="上班" value="09:00"></CommonItem>
<CommonItem text="下班" value="17:00"></CommonItem>
<view
v-show="index == times.length - 1 && times.length < 3"
class="flex flex-justify-center items-center flex-row py-4 box-border"
>
<wd-icon name="add-circle mr-2" class="color-[#3372FA]" size="17"></wd-icon>
<view @click="times.push({ start: '09:00', end: '17:00' })" class="color-[#3372FA]">
添加时段
</view>
</view>
</view>
</view>
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="允许打卡时间" value="" hint=""></CommonItem>
</view>
<view class="bg-white rounded-1.2 mt-2">
<CommonItem text="弹性打卡" value="" hint="不设置"></CommonItem>
</view>
<view v-show="times.length == 1" class="bg-white rounded-1.2 mt-2">
<CommonItem value="" :noLine="haveRest ? false : true">
<template v-slot:leftChild>
<view>
<view>休息时间</view>
<view class="color-gray mt-1">中途休息时间不计入出勤时长</view>
</view>
</template>
<template v-slot:child>
<wd-switch v-model="haveRest" class="ml-a" />
</template>
</CommonItem>
<CommonItem v-show="haveRest" text="休息开始时间" value="12:00"></CommonItem>
<CommonItem v-show="haveRest" text="休息结束时间" value="13:00"></CommonItem>
</view>
<view
class="fixed bottom-0 left-0 w-full p-3 box-border border-solid border-0 border-t-1 border-gray-200"
>
<wd-button block>保存</wd-button>
</view>
</view>
</template>
<script lang="ts" setup>
import CommonItem from '@/components/CommonItemItem/CommonItem.vue'
const name = ref('')
const haveRest = ref(false)
const times = ref([
{
start: '09:00',
end: '17:00'
}
])
//
</script>
<style lang="scss" scoped>
//
</style>

View File

@ -0,0 +1,128 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationStyle: 'custom'
}
}
</route>
<template>
<TopNavigation title="班次管理"></TopNavigation>
<view class="h-[calc(100vh-60px)] p-3 box-border flex flex-col">
<view class="flex items-center bg-gray-200 p-2 rounded">
<wd-icon name="search" class="text-gray mr-2"></wd-icon>
<input
v-model="key"
type="text"
placeholder="搜索班次名称"
placeholder-class="text-gray"
class="w-100%"
/>
<view v-show="key" class="i-carbon-close-filled color-gray text-4"></view>
</view>
<view @click="goClassesAdd()" class="bg-white rounded-1.2 mt-2">
<CommonItem text="添加班次" noLine value="">
<template v-slot:child>
<wd-icon name="add-circle" class="ml-a" size="20"></wd-icon>
</template>
</CommonItem>
</view>
<scroll-view
ref="scrollView"
scroll-y
class="mt-2 flex-1"
refresher-enabled
:refresher-threshold="45"
@refresherrefresh="onRefresh()"
:refresher-triggered="scrollViewStatus"
>
<view class="bg-white rounded-1.2">
<CommonItem v-for="(item, index) in classList" :key="index" value="">
<template v-slot:leftChild>
<view>
<view>{{ item.name }}</view>
<view class="color-gray mt-1">{{ item.time }}</view>
</view>
</template>
<template v-slot:child>
<view class="ml-a i-bytesize-compose color-gray"></view>
</template>
</CommonItem>
</view>
<view class="ml-3 mt-1 text-3 color-gray">添加班次后请至考勤组中选择和使用</view>
</scroll-view>
</view>
</template>
<script lang="ts" setup>
import CommonItem from '@/components/CommonItemItem/CommonItem.vue'
const scrollViewStatus = ref(true)
const key = ref('')
const onRefresh = () => {
console.log('refresh')
setTimeout(() => {
scrollViewStatus.value = true
scrollViewStatus.value = false
}, 2000)
}
const goClassesAdd = () => {
uni.navigateTo({
url: '/pages/attendance/classes-add'
})
}
const classList = ref([
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
},
{
name: '默认班次',
time: '09:00-17:00'
}
])
//
</script>
<style lang="scss" scoped>
page {
background-color: #f6f8fc;
}
</style>

View File

@ -0,0 +1,21 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationStyle: 'custom'
}
}
</route>
<template>
<TopNavigation title="弹性打卡"></TopNavigation>
<view class=""></view>
</template>
<script lang="ts" setup>
//
</script>
<style lang="scss" scoped>
//
</style>

View File

@ -1,7 +1,14 @@
<template>
<view></view>
<view @click="goAttendance()">考勤</view>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
const goAttendance = () => {
uni.navigateTo({
url: '/pages/attendance/attendance'
})
// todo goAttendance
}
</script>
<style scoped lang="scss"></style>