Merge branch 'fanpeng' into 'develop'

feat: 完成审批发起申请和审批中心的UI

See merge request StarlockTeam/starwork-uniapp!11
This commit is contained in:
刘燕峰 2025-01-17 07:04:52 +00:00
commit b6773b4d75
53 changed files with 2837 additions and 61 deletions

View File

@ -56,10 +56,11 @@
<script setup lang="ts">
import { useBasicStore } from '@/store'
import GetSystemInfoResult = UniNamespace.GetSystemInfoResult
const $basic = useBasicStore()
const systemInfo = ref(null)
const systemInfo = ref<GetSystemInfoResult>(null)
const show = ref<boolean>(false)
onMounted(async () => {

View File

@ -26,14 +26,21 @@
class="pos-absolute left-3 h-5 w-5"
@click="back"
></image>
<view class="flex-1 text-center">
<view class="line-clamp-1 max-w-60 break-all mx-auto">
<view class="flex flex-items-center">
<view class="line-clamp-1 max-w-60 break-all">
{{ title }}
</view>
</view>
<view class="pos-absolute right--3">
<slot></slot>
</view>
<view
v-if="rightButtonText"
class="text-3.5 font-normal pos-absolute right-5"
@click="rightButton"
>
{{ rightButtonText }}
</view>
</view>
</view>
</view>
@ -41,10 +48,11 @@
<script lang="ts" setup>
import { useBasicStore } from '@/store'
import GetSystemInfoResult = UniNamespace.GetSystemInfoResult
const $basic = useBasicStore()
const systemInfo = ref(null)
const systemInfo = ref<GetSystemInfoResult>(null)
defineProps({
mini: {
@ -62,16 +70,24 @@
backUrl: {
type: String,
default: '/static/images/icon_back.png'
},
rightButtonText: {
type: [String, null],
default: null
}
})
const emits = defineEmits(['back'])
const emits = defineEmits(['back', 'rightButton'])
const back = () => {
uni.navigateBack()
emits('back')
}
const rightButton = () => {
emits('rightButton')
}
onMounted(async () => {
systemInfo.value = await $basic.getSystemInfo()
})

View File

@ -60,8 +60,12 @@
}
},
{
"path": "pages/application-list/application-list",
"type": "page"
"path": "pages/approval/approval-detail",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
}
},
{
"path": "pages/approval/approval",
@ -71,6 +75,14 @@
"disableScroll": true
}
},
{
"path": "pages/approval/create-application",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
}
},
{
"path": "pages/attendance/allowed-time",
"type": "page",
@ -136,22 +148,16 @@
}
},
{
"path": "pages/code/code",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
"path": "pages/home/application-list",
"type": "page"
},
{
"path": "pages/get-code/get-code",
"path": "pages/info-publish/add-release-plan",
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/announce-notice",
@ -177,9 +183,29 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/edit-pic-video",
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/info-publish",
"type": "page"
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/material-library",
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/notice-details",
@ -197,6 +223,40 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/play-content-library",
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/info-publish/release-plan",
"type": "page",
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/login/code",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
},
{
"path": "pages/login/get-code",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
},
{
"path": "pages/login/login",
"type": "page",
@ -206,6 +266,23 @@
},
"needLogin": false
},
{
"path": "pages/login/reset-password",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
},
{
"path": "pages/mine/mine",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/notification/notification",
"type": "page"
@ -219,13 +296,20 @@
}
},
{
"path": "pages/reset-password/reset-password",
"path": "pages/select/select-access-control",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
},
"needLogin": false
}
},
{
"path": "pages/select/select-organization",
"type": "page",
"style": {
"navigationStyle": "custom",
"disableScroll": true
}
},
{
"path": "pages/workbench/workbench",
@ -281,4 +365,4 @@
}
],
"subPackages": []
}
}

View File

@ -0,0 +1,66 @@
<route lang="json5">
{
style: {
navigationStyle: 'custom',
disableScroll: true
}
}
</route>
<template>
<view class="h-100vh flex flex-col">
<TopNavigation title="详情"></TopNavigation>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<view class="pb-5">
<ApprovalContent class="mt-2" />
<ApprovalProcess class="mt-2" />
</view>
</scroll-view>
<view class="pb-safe border-#eef0f5 border-t-solid">
<view class="flex flex-items-center flex-justify-around py-3">
<view class="py-2 px-13 bg-#ef2e2f color-white rounded-2">拒绝</view>
<view class="py-2 px-13 custom-bg-blue color-white rounded-2">同意</view>
<view class="custom-color-blue text-4" @click="showActions">更多</view>
</view>
</view>
<wd-action-sheet
v-model="show"
:actions="actions"
close-on-click-action
@close="close"
@select="select"
/>
</view>
</template>
<script setup lang="ts">
import { useToast } from 'wot-design-uni'
import ApprovalContent from '@/pages/approval/components/ApprovalContent.vue'
import ApprovalProcess from '@/pages/approval/components/ApprovalProcess.vue'
const toast = useToast()
const show = ref<boolean>(false)
const actions = ref([
{
name: '专审'
},
{
name: '退回'
},
{
name: '取消'
}
])
const showActions = () => {
show.value = true
}
const close = () => {
show.value = false
}
const select = ({ item, index }) => {
toast.show(`当前选中项: ${item.title}, 下标: ${index}`)
}
</script>

View File

@ -7,14 +7,20 @@
}
</route>
<template>
<view>
<view class="h-100vh flex flex-col">
<TopNavigation :title="index === 0 ? '发起申请' : '审批'"></TopNavigation>
<ApplicationList v-show="index === 0" :list="applicationListData"></ApplicationList>
<view v-show="index === 1" class="flex-1 box-border">
<ApprovalRecords></ApprovalRecords>
</view>
<CustomTabBar :list="list" :default-index="index" @change="change"></CustomTabBar>
</view>
</template>
<script setup lang="ts">
import { TabBarItem } from '@/typings'
import ApplicationList from '@/pages/approval/components/ApplicationList.vue'
import ApprovalRecords from '@/pages/approval/components/ApprovalRecords.vue'
const index = ref<number>(0)
@ -29,6 +35,78 @@
}
]
const applicationListData = ref<Array<object>>([
{
groupId: 138603,
groupName: '出勤休假',
sort: 1,
processDefs: [
{
processDefId: 249155,
processDefName: '请假',
icon: 'https://file.hikvisionmall.com/test1/image/f39c654cd30a48d28ddf37e4b64de57a.png',
version: '1735128632'
},
{
processDefId: 249156,
processDefName: '补卡',
icon: 'https://file.hikvisionmall.com/test1/image/26209b6732f2439fae3c6dd34a39145e.png',
version: '1704439843'
},
{
processDefId: 249158,
processDefName: '外出',
icon: 'https://file.hikvisionmall.com/test1/image/5c76288745dd47a38c9e1093d9737976.png',
version: '1704439843'
},
{
processDefId: 249157,
processDefName: '出差',
icon: 'https://file.hikvisionmall.com/test1/image/df75579e70c2435e9f78d04fc401b451.png',
version: '1704439843'
},
{
processDefId: 347336,
processDefName: '加班',
icon: 'https://file.hikvisionmall.com/test1/image/e4f21377ea2443b3856b07674ba41c2a.png',
version: '1711368134'
},
{
processDefId: 891737,
processDefName: '调休',
icon: 'https://file.hikvisionmall.com/prod/image/3d134cc9657e4816ad6aa8ef206fbc89.png',
version: '1735128832'
}
]
},
{
groupId: 341473,
groupName: 'test',
sort: 2,
processDefs: [
{
processDefId: 924255,
processDefName: 'test1',
icon: 'https://file.hikvisionmall.com/prod/image/3d134cc9657e4816ad6aa8ef206fbc89.png',
version: '1736480449'
}
]
},
{
groupId: 138604,
groupName: '其他',
sort: 999,
processDefs: [
{
processDefId: 466818,
processDefName: '访客预约',
icon: 'https://file.hikmall.com/prod/image/5300a838119d462b9e1c17489603b6d8.png',
version: '1715675086'
}
]
}
])
onLoad(options => {
if (options.index) {
index.value = Number(options.index)

View File

@ -0,0 +1,65 @@
<template>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<view class="mx-4 pt-4 flex flex-items-center text-3.5 font-bold">
<view class="bg-#dfecff flex-1 px-3 py-6 rounded-2">
<view>使用指南</view>
</view>
<view class="w-4"></view>
<view class="bg-#feebda flex-1 px-3 py-6 rounded-2">
<view>常见问题</view>
</view>
</view>
<view class="py-4">
<wd-collapse v-model="collapseRoot" custom-class="!bg-transparent !border-0">
<wd-collapse-item
v-for="group in list"
:key="group.groupId"
:name="group.groupName"
:title="group.groupName"
>
<view
v-for="(item, index) in group.processDefs"
:key="item.processDefId"
:class="[index === group.processDefs.length - 1 ? '' : 'mb-2']"
class="flex flex-items-center bg-white px-3 py-3 mx-1 rounded-2"
@click="toDetail(item)"
>
<image :src="item.icon" class="w-7 h-7 rounded-2"></image>
<view class="text-3.5 ml-2">{{ item.processDefName }}</view>
</view>
</wd-collapse-item>
</wd-collapse>
</view>
</scroll-view>
</template>
<script setup lang="ts">
const collapseRoot = ref<string[]>([])
onMounted(() => {
collapseRoot.value = props.list.map(item => item.groupName)
})
const props = defineProps({
list: {
type: Array,
required: true
}
})
const toDetail = (item: Record<string, any>) => {
uni.navigateTo({
url: `/pages/approval/create-application?id=${item.processDefId}&title=${item.processDefName}`
})
}
</script>
<style lang="scss" scoped>
.wd-collapse-item::after {
height: 0 !important;
}
:deep(.wd-collapse-item__header::after) {
height: 0 !important;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<view class="bg-white rounded-2 py-2 px-4 mx-4">
<view class="flex flex-items-center">
<image
src="/static/images/icon_default_avatar.png"
class="w-10 h-10"
mode="aspectFill"
></image>
<view class="ml-4">
<view class="font-bold text-4.5">请假</view>
<view class="text-3.5 mt-1">xxx</view>
</view>
<view
class="ml-a rounded py-0.5 px-1.5 text-3.5 border-solid border-1 border-#ef811c color-#ef811c"
>
审批中
</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>所属组织</view>
<view class="mt-2 break-all">123132123的互联</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>审批编号</view>
<view class="mt-2 break-all">845465465465465465456</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>请假类型</view>
<view class="mt-2 break-all">年假</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>开始时间</view>
<view class="mt-2 break-all">2025-01-10</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>结束时间</view>
<view class="mt-2 break-all">2025-01-10</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>请假时长()</view>
<view class="mt-2 break-all">1.0</view>
</view>
<view class="my-2 h-1px w-full bg-#eef0f5"></view>
<view class="custom-color-black">
<view>请假原因</view>
<view class="mt-2 break-all">
请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假请假1111111111111111111111
</view>
</view>
</view>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,101 @@
<template>
<view class="bg-white rounded-2 py-3 px-4 mx-4 my-2 shadow-sm">
<view class="text-4">审批流程</view>
<view v-if="false" class="text-3 color-#838589 mt-2">必填信息填写完整后将显示审批流程</view>
<view v-else class="mt-4 color-#838589">
<wd-steps :active="3" vertical>
<wd-step>
<template v-slot:icon>
<view
class="custom-bg-blue w-5 h-5 rounded-50% flex flex-items-center flex-justify-center"
>
<view class="w-2.5 h-2.5 bg-white rounded-50%"></view>
</view>
</template>
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>发起人</view>
</view>
<view class="my-2">
<view>
<image
src="https://file.hikmall.com/prod/image/4921b7596d2344088f8611f503b011dc.png"
class="h-10 w-10 rounded-2"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</template>
</wd-step>
<wd-step>
<template v-slot:icon>
<view class="bg-#f0801e w-5 h-5 rounded-50% flex flex-items-center flex-justify-center">
<image src="/static/images/icon_approval.png" class="w-3 h-3"></image>
</view>
</template>
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>审批节点</view>
</view>
<view class="pt-2 color-#7e807f text-3">1人通过即可</view>
<view class="my-2 flex flex-wrap">
<view v-for="item in 8" :key="item" class="mb-2 w-fit mr-2">
<view>
<image
src="https://file.hikmall.com/prod/image/4921b7596d2344088f8611f503b011dc.png"
class="h-10 w-10 rounded-2"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</view>
</template>
</wd-step>
<wd-step>
<template v-slot:icon>
<view class="bg-#2ab6c7 w-5 h-5 rounded-50% flex flex-items-center flex-justify-center">
<image src="/static/images/icon_airplane.png" class="w-3 h-3"></image>
</view>
</template>
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>抄送节点</view>
</view>
<view class="my-2 flex flex-wrap">
<view v-for="item in 3" :key="item" class="mb-2 w-fit mr-2">
<view>
<image
src="https://file.hikmall.com/prod/image/4921b7596d2344088f8611f503b011dc.png"
class="h-10 w-10 rounded-2"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</view>
</template>
</wd-step>
</wd-steps>
</view>
</view>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
:deep(.wd-step__header) {
width: 1.25rem;
}
:deep(.wd-step__line) {
background: #255cf7;
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<view class="bg-white rounded-2 py-2 px-4 mx-4">
<view class="py-2 text-4">审批流程</view>
<wd-steps :active="1" vertical>
<wd-step icon="link">
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>发起申请</view>
<view class="ml-a color-#7e807f text-3">2504-12-25 20:11</view>
</view>
<view class="my-2">
<view class="py-1 flex flex-items-center w-fit rounded-4 bg-#f3f5fa">
<image
src="/static/images/icon_default_avatar.png"
class="h-6 w-6 rounded-50%"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</template>
</wd-step>
<wd-step icon="link">
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>审批节点</view>
<view
class="ml-3 rounded-4 py-0.5 text-3 px-2 border-solid border-#ef811c border-1 color-#ef811c"
>
审批中
</view>
</view>
<view class="pt-2 color-#7e807f text-3">1人通过即可</view>
<view class="my-2">
<view
v-for="item in 4"
:key="item"
class="mb-2 py-1 flex flex-items-center w-fit rounded-4 bg-#f3f5fa"
>
<image
src="/static/images/icon_default_avatar.png"
class="h-6 w-6 rounded-50%"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</template>
</wd-step>
<wd-step icon="link">
<template v-slot:title>
<view class="custom-color-black text-3.5">
<view class="flex-items-center flex">
<view>抄送节点</view>
</view>
<view class="my-2">
<view
v-for="item in 4"
:key="item"
class="mb-2 py-1 flex flex-items-center w-fit rounded-4 bg-#f3f5fa"
>
<image
src="/static/images/icon_default_avatar.png"
class="h-6 w-6 rounded-50%"
mode="aspectFill"
></image>
<view class="mx-2">xxx</view>
</view>
</view>
</view>
</template>
</wd-step>
</wd-steps>
</view>
</template>
<script setup lang="ts"></script>

View File

@ -0,0 +1,158 @@
<template>
<view class="mx-4 mt-2">
<wd-input
class="px-2 py-0.6 rounded-1"
placeholder="申请名称、发起人"
v-model="search"
clearable
custom-class="border-0"
:maxlength="50"
prefix-icon="search"
@change="handleChange"
/>
</view>
<wd-tabs v-model="currentIndex" class="pt-3" auto-line-width @click="handleChange">
<wd-tab :title="item" v-for="(item, index) in tabs" :key="item" :name="index" />
</wd-tabs>
<swiper :current="currentIndex" @change="changeIndex">
<swiper-item v-for="(item, index) in tabs" :key="item" class="flex flex-col">
<view @click="closeOutside">
<wd-drop-menu>
<wd-drop-menu-item
v-model="typeList[index]"
:options="typeOptionList[index]"
@change="typeChange"
/>
<wd-drop-menu-item
v-model="dateList[index]"
:options="dateOptions"
@change="dateChange"
/>
</wd-drop-menu>
</view>
<scroll-view :scroll-y="true" class="flex-1 box-border">
<view class="pt-2">
<view
v-for="item in 10"
:key="item"
class="mx-4 my-2 p-4 bg-white shadow-sm rounded-2 text-3.5"
@click="toDetail(item)"
>
<view class="flex flex-items-center mb-2">
<view class="text-4.5 font-bold">请假</view>
<view
class="ml-a px-3 py-1 border-solid border-[#2bbbc3] border-1 color-#2bbbc3 rounded"
>
通过
</view>
</view>
<view class="mb-2">请假类型年假</view>
<view class="mb-2">开始时间2025-12-31</view>
<view class="mb-2">结束时间2025-12-31</view>
<view class="flex flex-items-center">
<image class="w-8 h-8" src="/static/images/icon_default_avatar.png"></image>
<view class="ml-4">xxx</view>
<view class="ml-a">2025-12-25</view>
</view>
</view>
</view>
<view class="py-6 mx-30%">
<wd-divider color="#515357">已经到底了</wd-divider>
</view>
</scroll-view>
</swiper-item>
</swiper>
</template>
<script setup lang="ts">
import { useQueue } from 'wot-design-uni'
const search = ref<string>('')
const currentIndex = ref<number>(0)
const tabs = ref<string[]>(['待办', '已办', '抄送我', '已发起'])
const { closeOutside } = useQueue()
const typeList = ref<Array<number>>([0, 0, 0, 0])
const dateList = ref<Array<number>>([0, 0, 0, 0])
const typeOptionList = ref<Array<Array<Record<string, number>>>>([
[
{ label: '全部', value: 0 },
{ label: '补卡', value: 1 },
{ label: '请假', value: 2 }
],
[
{ label: '全部', value: 0 },
{ label: '调休', value: 1 }
],
[
{ label: '全部', value: 0 },
{ label: '补卡', value: 1 },
{ label: '请假', value: 2 }
],
[
{ label: '全部', value: 0 },
{ label: '补卡', value: 1 },
{ label: '请假', value: 2 }
]
])
const dateOptions = ref<Array<Record<string, number>>>([
{ label: '全部日期', value: 0 },
{ label: '近7日', value: 1 },
{ label: '近14日', value: 2 },
{ label: '近30日', value: 3 }
])
const typeChange = ({ value }) => {
console.log(value)
}
const dateChange = ({ value }) => {
console.log(value)
}
const toDetail = item => {
uni.navigateTo({
url: '/pages/approval/approval-detail'
})
}
const handleChange = value => {
currentIndex.value = value.index
}
const changeIndex = e => {
currentIndex.value = e.detail.current
}
</script>
<style lang="scss" scoped>
.wd-input::after {
height: 0;
}
.wd-drop-item {
top: calc(var(--window-top) + 48px) !important;
}
:deep(.wd-drop-menu__item.is-active .wd-drop-menu__item-title::after) {
opacity: 0 !important;
}
:deep(.wd-drop-menu__list) {
background-color: transparent !important;
}
:deep(.wd-tabs__nav-item) {
margin-bottom: 5px;
}
:deep(.wd-tabs__nav-item.is-active) {
font-weight: bold;
color: #255cf7;
}
</style>

View File

@ -0,0 +1,273 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative pt-2 pb-1">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<view @click="openDialog" class="flex-1 flex flex-items-center">
<view :class="[text ? 'custom-color-black' : 'color-#bfbfbf']" class="ml-a mr-2">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="py-2" @click="openDialog">
<view class="flex flex-items-center flex-justify-between">
<view :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
</view>
</view>
<wd-popup
v-model="show"
position="bottom"
custom-style="border-radius:12rpx;"
@after-leave="afterLeave"
>
<view>
<view class="p-4 text-3.5 border-b-1 border-[#dcdcdc] border-solid flex flex-items-center">
<view class="font-bold">日期</view>
<view class="font-bold ml-a" v-if="type !== 'dateHalfDay'">{{ date }}</view>
</view>
<view v-if="(type === 'date' || type === 'datetime') && showPicker">
<wd-datetime-picker-view
:formatter="formatter"
:type="type"
v-model="timestamp"
label="日期选择"
@change="change"
/>
</view>
<view v-if="type === 'dateHalfDay' && showPicker">
<wd-tabs v-model="tab">
<wd-tab :title="index === 0 ? date : halfDay" v-for="(item, index) in 2" :key="index">
<view v-show="index === 0">
<wd-datetime-picker-view
:formatter="formatter"
type="date"
v-model="timestamp"
@change="change"
/>
</view>
<view v-show="index === 1">
<wd-picker-view :columns="['上午', '下午']" v-model="halfDay" @change="change" />
</view>
</wd-tab>
</wd-tabs>
</view>
<view class="pb-safe">
<view class="flex py-3 flex-items-center flex-justify-around text-3.5 px-2 font-bold">
<view
class="w-45% bg-#eeeff4 custom-color-blue py-2.5 rounded-2 text-center"
@click="show = false"
>
取消
</view>
<view
class="w-45% custom-bg-blue color-white py-2.5 rounded-2 text-center"
@click="confirm"
>
确定
</view>
</view>
</view>
</view>
</wd-popup>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
const show = ref<boolean>(false)
const timestamp = ref<number>(0)
const text = ref<string>('')
const date = ref<string>('')
const halfDay = ref<string>('')
const showPicker = ref<boolean>(false)
const returnTimestamp = ref<number>(0)
const tab = ref<number>(0)
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
default: 'date'
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: [Number, null],
default: null
},
placeholder: {
type: String,
default: '请选择'
},
disabled: {
type: Boolean,
default: false
},
disabledText: {
type: String,
default: ''
},
minDate: {
type: [Number, null],
default: null
},
maxDate: {
type: [Number, null],
default: null
},
minDateText: {
type: String,
default: ''
},
maxDateText: {
type: String,
default: ''
},
inline: {
type: Boolean,
default: false
}
})
const formatter = (type, value) => {
switch (type) {
case 'year':
return value + '年'
case 'month':
return value + '月'
case 'date':
return value + '日'
case 'hour':
return value + '时'
case 'minute':
return value + '分'
default:
return value
}
}
const emits = defineEmits(['change'])
onMounted(() => {
if (props.value) {
timestamp.value = props.value
if (props.type === 'date') {
date.value = dayjs(props.value).format('YYYY-M-D')
text.value = date.value
} else if (props.type === 'datetime') {
date.value = dayjs(props.value).format('YYYY-M-D HH:mm')
text.value = date.value
} else if (props.type === 'dateHalfDay') {
date.value = dayjs(props.value).format('YYYY年M月D日')
halfDay.value = dayjs(props.value).hour() < 12 ? '上午' : '下午'
text.value = `${date.value} ${halfDay.value}`
}
}
})
const change = ({ value }) => {
if (props.type === 'date') {
date.value = dayjs(value).format('YYYY-M-D')
} else if (props.type === 'datetime') {
date.value = dayjs(value).format('YYYY-M-D HH:mm')
} else if (props.type === 'dateHalfDay') {
if (tab.value === 0) {
date.value = dayjs(value).format('YYYY年M月D日')
} else {
halfDay.value = value
}
}
}
const openDialog = () => {
if (props.disabled) {
uni.showToast({
title: props.disabledText,
icon: 'none'
})
return
}
if (!props.value) {
if (text.value === '') {
timestamp.value = new Date().getTime()
} else {
timestamp.value = returnTimestamp.value
}
if (props.type === 'date') {
date.value = dayjs(timestamp.value).format('YYYY-M-D')
} else if (props.type === 'datetime') {
date.value = dayjs(timestamp.value).format('YYYY-M-D HH:mm')
} else if (props.type === 'dateHalfDay') {
date.value = dayjs(timestamp.value).format('YYYY年M月D日')
halfDay.value = dayjs(timestamp.value).hour() < 12 ? '上午' : '下午'
}
}
showPicker.value = true
show.value = true
}
const confirm = () => {
if (props.minDate && timestamp.value < props.minDate) {
uni.showToast({
title: props.minDateText,
icon: 'none'
})
return
}
if (props.maxDate && timestamp.value > props.maxDate) {
uni.showToast({
title: props.maxDateText,
icon: 'none'
})
return
}
show.value = false
returnTimestamp.value = timestamp.value
if (props.type === 'dateHalfDay') {
text.value = `${date.value} ${halfDay.value}`
} else {
text.value = date.value
}
emits('change', { id: props.id, value: returnTimestamp.value, text: text.value })
}
const afterLeave = () => {
showPicker.value = false
}
const clear = () => {
text.value = ''
date.value = ''
halfDay.value = ''
returnTimestamp.value = 0
emits('change', { id: props.id, value: returnTimestamp.value, text: text.value })
}
defineExpose({
clear
})
</script>

View File

@ -0,0 +1,110 @@
<template>
<view>
<DatetimePicker
:id="1"
ref="startDatetimePicker"
title="开始时间"
@change="changeDate"
:max-date="endTimestamp"
max-date-text="开始时间不能晚于结束时间"
required
:disabled="disabled"
:disabled-text="disabledText"
:type="unit"
></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePicker
:id="2"
title="结束时间"
ref="endDatetimePicker"
:min-date="startTimestamp"
min-date-text="结束时间不能早于开始时间"
@change="changeDate"
required
:type="unit"
:disabled="disabled"
:disabled-text="disabledText"
></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<Input
:id="3"
ref="inputComponent"
type="number"
:title="`${textMap[type]}时长${unit === 'datetime' ? '(小时)' : '(天)'}`"
required
:readonly="updateTime"
placeholder="自动计算"
@change="inputChange"
></Input>
</view>
</template>
<script setup lang="ts">
import DatetimePicker from '@/pages/approval/components/DatetimePicker.vue'
import Input from '@/pages/approval/components/Input.vue'
const textMap = {
leave: '请假',
businessTrip: '出差',
goOut: '外出',
overtime: '加班'
}
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
required: true
},
unit: {
type: String,
default: 'date'
},
disabled: {
type: Boolean,
default: false
},
disabledText: {
type: String,
default: ''
},
updateTime: {
type: Boolean,
default: false
}
})
const startTimestamp = ref(0)
const endTimestamp = ref(0)
const startDatetimePicker = ref(null)
const endDatetimePicker = ref(null)
const inputComponent = ref(null)
const changeDate = e => {
if (e.id === 1) {
startTimestamp.value = e.value
} else {
endTimestamp.value = e.value
}
}
const inputChange = e => {
console.log('inputChange', e)
}
const clear = () => {
startDatetimePicker.value.clear()
endDatetimePicker.value.clear()
inputComponent.value.clear()
}
defineExpose({
clear
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,18 @@
<template>
<view class="px-2 text-3.5 pb-2">
<view class="break-all">{{ title }}</view>
</view>
</template>
<script setup lang="ts">
const props = defineProps({
id: {
type: Number,
required: true
},
title: {
type: String,
required: true
}
})
</script>

View File

@ -0,0 +1,145 @@
<template>
<view class="pb-3 mb-2">
<Visitor></Visitor>
<view class="bg-white mx-4 p-2 rounded-2 shadow-sm">
<Input
:id="0"
value="单行"
title="单行文本"
:required="true"
placeholder="单行文本"
@change="inputChange"
></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Textarea
:id="1"
title="多行文本"
:required="false"
placeholder="多行文本"
@change="textareaChange"
></Textarea>
<wd-divider color="#bcbfbe"></wd-divider>
<SelectPicker
:value="1"
:id="2"
title="单选框"
placeholder="单选"
:columns="columns"
></SelectPicker>
<wd-divider color="#bcbfbe"></wd-divider>
<SelectPicker
:value="[0]"
:id="3"
title="多选框"
placeholder="多选"
type="checkbox"
:columns="columns"
></SelectPicker>
<wd-divider color="#bcbfbe"></wd-divider>
<Input
:id="4"
type="number"
title="数字"
:required="true"
placeholder="数字"
@change="inputChange"
></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePicker :id="5" title="日期1" @change="changeDate"></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePicker
:id="6"
title="日期2"
type="dateHalfDay"
@change="changeDate"
></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePicker
:id="7"
type="datetime"
:value="1737043380000"
title="日期3"
@change="changeDate"
></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<Images :id="8" title="图片"></Images>
<wd-divider color="#bcbfbe"></wd-divider>
<Description
:id="9"
title="图片21378912378923718982371217389712397837889713247893428793142897134728900978"
></Description>
<wd-divider color="#bcbfbe"></wd-divider>
<NavigatorSelector :id="10" title="成员" type="member" :multiple="true"></NavigatorSelector>
<wd-divider color="#bcbfbe"></wd-divider>
<NavigatorSelector
:id="11"
title="部门"
type="department"
:multiple="true"
></NavigatorSelector>
<wd-divider color="#bcbfbe"></wd-divider>
<Leave :id="12"></Leave>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePickerGroup :id="13" type="businessTrip" unit="date"></DatetimePickerGroup>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePickerGroup :id="14" type="goOut" unit="dateHalfDay"></DatetimePickerGroup>
<wd-divider color="#bcbfbe"></wd-divider>
<Overtime :id="15"></Overtime>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePicker
:id="16"
type="datetime"
required
title="补卡时间"
@change="changeDate"
></DatetimePicker>
</view>
</view>
</template>
<script setup lang="ts">
import Input from '@/pages/approval/components/Input.vue'
import Textarea from '@/pages/approval/components/Textarea.vue'
import SelectPicker from '@/pages/approval/components/SelectPicker.vue'
import DatetimePicker from '@/pages/approval/components/DatetimePicker.vue'
import Images from '@/pages/approval/components/Images.vue'
import Description from '@/pages/approval/components/Description.vue'
import NavigatorSelector from '@/pages/approval/components/NavigatorSelector.vue'
import Leave from '@/pages/approval/components/Leave.vue'
import DatetimePickerGroup from '@/pages/approval/components/DatetimePickerGroup.vue'
import Overtime from '@/pages/approval/components/Overtime.vue'
import Visitor from '@/pages/approval/components/Visitor.vue'
const columns = ref<Record<number, string>>([
{
value: 0,
label: '男装'
},
{
value: 1,
label: '奢侈品'
},
{
value: 2,
label: '女装'
}
])
const inputChange = e => {
console.log('inputChange', e)
}
const textareaChange = e => {
console.log('textareaChange', e)
}
const changeDate = e => {
console.log('changeDate', e)
}
</script>
<style lang="scss" scoped>
.wd-divider {
padding: 0 0.5rem;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<view class="px-2 text-3.5">
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="pt-3">
<wd-upload
:file-list="fileList"
multiple
:limit="9"
image-mode="aspectFill"
:size-type="['original']"
action="https://mockapi.eolink.com/zhTuw2P8c29bc981a741931bdd86eb04dc1e8fd64865cb5/upload"
@change="handleChange"
></wd-upload>
</view>
</view>
</template>
<script setup lang="ts">
const fileList = ref<any[]>([])
const props = defineProps({
id: {
type: Number,
required: true
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: Array,
default: () => []
}
})
onMounted(() => {
if (props.value.length > 0) {
fileList.value = props.value
}
})
const handleChange = ({ fileList: files }) => {
console.log('handleChange', files)
fileList.value = files
}
</script>
<style scoped lang="scss">
:deep(.wd-upload__evoke),
:deep(.wd-upload__status-content),
:deep(.wd-upload__picture) {
border-radius: 12rpx;
}
</style>

View File

@ -0,0 +1,109 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<wd-input
class="flex-1 ml-2"
:type="type"
custom-class="!bg-transparent"
:custom-input-class="inline ? 'text-right' : 'text-left'"
:placeholder="placeholder"
:maxlength="maxlength ?? (type === 'text' ? 30 : 15)"
v-model="text"
:readonly="readonly"
@input="change(id, $event)"
></wd-input>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="pt-2">
<wd-input
:type="type"
custom-class="!bg-transparent"
:placeholder="placeholder"
:maxlength="maxlength ?? (type === 'text' ? 30 : 15)"
v-model="text"
:readonly="readonly"
@input="change(id, $event)"
></wd-input>
</view>
</view>
</view>
</template>
<script setup lang="ts">
const emits = defineEmits(['change'])
const text = ref<string>('')
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
default: 'text'
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请输入'
},
readonly: {
type: Boolean,
default: false
},
inline: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, null],
default: null
}
})
onMounted(() => {
text.value = props.value
})
const change = (id, data) => {
emits('change', { id, value: data.value })
}
const clear = () => {
text.value = ''
}
defineExpose({
clear
})
</script>
<style lang="scss" scoped>
.wd-input::after {
height: 0 !important;
}
:deep(.wd-input__inner) {
font-size: 0.875rem;
}
</style>

View File

@ -0,0 +1,94 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative py-1.5">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<view
class="flex-1 ml-a text-right"
@click="toSelect"
:class="[text ? 'custom-color-black' : 'color-#bfbfbf']"
>
{{ text || placeholder }}
</view>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="py-2" @click="toSelect">
<view class="flex flex-items-center flex-justify-between">
<view :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
</view>
<wd-keyboard
:mode="type"
title="键盘"
:hide-on-click-outside="true"
v-model:visible="visible"
@input="onInput"
closeText="确认"
@delete="onDelete"
/>
</view>
</template>
<script setup lang="ts">
const text = ref<string>('')
const visible = ref<boolean>(false)
const onInput = value => {
if (props.maxlength && text.value.length >= props.maxlength) return
text.value += value
}
const onDelete = () => {
text.value = text.value.slice(0, -1)
}
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
required: true
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: [Number, null],
default: null
},
placeholder: {
type: String,
default: '请输入'
},
maxlength: {
type: [Number, null],
default: null
},
inline: {
type: Boolean,
default: false
}
})
const toSelect = () => {
visible.value = true
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,97 @@
<template>
<view>
<SelectPicker
:id="0"
title="请假类型"
placeholder="请选择"
:columns="columns"
required
@change="changeSelect"
></SelectPicker>
<wd-divider color="#bcbfbe"></wd-divider>
<DatetimePickerGroup
ref="timeGroup"
type="leave"
:disabled="!leaveType"
:updateTime="updateTime"
:unit="leaveType?.unit ?? 'date'"
disabled-text="请选择请假类型"
:id="1"
></DatetimePickerGroup>
</view>
</template>
<script setup lang="ts">
import SelectPicker from '@/pages/approval/components/SelectPicker.vue'
import DatetimePickerGroup from '@/pages/approval/components/DatetimePickerGroup.vue'
const leaveType = ref(null)
const timeGroup = ref(null)
const columns = ref<Record<number, string>>([
{
value: 0,
label: '年假',
unit: 'date'
},
{
value: 1,
label: '事假',
unit: 'dateHalfDay'
},
{
value: 2,
label: '病假',
unit: 'datetime'
},
{
value: 3,
label: '婚假',
unit: 'date',
limit: 5
},
{
value: 4,
label: '产假',
unit: 'datetime',
limit: 24.5
},
{
value: 5,
label: '陪产假',
unit: 'datetime'
},
{
value: 6,
label: '丧假',
unit: 'date'
},
{
value: 7,
label: '哺乳假',
unit: 'date'
}
])
const props = defineProps({
id: {
type: Number,
required: true
},
updateTime: {
type: Boolean,
default: false
}
})
const changeSelect = e => {
leaveType.value = e.value
timeGroup.value.clear()
}
</script>
<style lang="scss" scoped>
.wd-divider {
padding: 0 0.5rem;
}
</style>

View File

@ -0,0 +1,94 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative pb-1.5" @click="toSelect">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<view class="ml-a mr-2" :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="py-2" @click="toSelect">
<view class="flex flex-items-center flex-justify-between">
<view :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
const text = ref<string | null>(null)
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
required: true
},
multiple: {
type: Boolean,
default: false
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: [Number, null],
default: null
},
placeholder: {
type: String,
default: '请选择'
},
inline: {
type: Boolean,
default: false
}
})
const toSelect = () => {
if (props.type === 'accessControl') {
uni.navigateTo({
url: `/pages/select/select-access-control`,
events: {
change: res => {
console.log(1111, res)
}
}
})
} else {
const params = {
type: props.type,
multiple: props.multiple,
title: props.type === 'member' ? '选择审批用户' : '选择部门'
}
uni.navigateTo({
url: `/pages/select/select-organization?params=${JSON.stringify(params)}`,
events: {
change: res => {
console.log(1111, res)
}
}
})
}
}
</script>

View File

@ -0,0 +1,43 @@
<template>
<view>
<DatetimePicker
:id="0"
ref="startDatetimePicker"
title="加班日期"
@change="changeDate"
required
></DatetimePicker>
<wd-divider v-if="timestamp" color="#bcbfbe"></wd-divider>
<DatetimePickerGroup
v-if="timestamp"
type="overtime"
unit="datetime"
:id="1"
></DatetimePickerGroup>
</view>
</template>
<script setup lang="ts">
import DatetimePickerGroup from '@/pages/approval/components/DatetimePickerGroup.vue'
import DatetimePicker from '@/pages/approval/components/DatetimePicker.vue'
const timestamp = ref<number>(0)
const props = defineProps({
id: {
type: Number,
required: true
}
})
const changeDate = e => {
timestamp.value = e.value
console.log('changeDate', e)
}
</script>
<style scoped lang="scss">
.wd-divider {
padding: 0 0.5rem;
}
</style>

View File

@ -0,0 +1,128 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<wd-select-picker
class="flex-1"
align-right
:type="type"
:title="placeholder"
:show-confirm="type === 'checkbox'"
v-model="picker"
:columns="columns"
size="large"
@change="change"
select-size="large"
></wd-select-picker>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="pt-2">
<wd-select-picker
:type="type"
:title="placeholder"
:show-confirm="type === 'checkbox'"
v-model="picker"
:columns="columns"
size="large"
@change="change"
select-size="large"
></wd-select-picker>
</view>
</view>
</view>
</template>
<script setup lang="ts">
const picker = ref(-1)
const props = defineProps({
id: {
type: Number,
required: true
},
type: {
type: String,
default: 'radio'
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
placeholder: {
type: String,
default: '请输入'
},
value: {
type: [Number, Array, null],
default: null
},
columns: {
type: Array,
required: true
},
inline: {
type: Boolean,
default: false
}
})
const emits = defineEmits(['change'])
onMounted(() => {
if (props.value) {
picker.value = props.value
}
})
const change = ({ value }) => {
emits('change', { id: props.id, value: props.columns.find(item => item.value === value) })
}
</script>
<style scoped lang="scss">
:deep(.wd-select-picker__cell) {
padding: var(--wot-cell-wrapper-padding, 10px) 0;
background-color: transparent;
}
:deep(.wd-radio-group),
:deep(.wd-checkbox-group) {
background-color: #ffffff;
border-radius: 0.5rem;
}
:deep(.wd-action-sheet) {
background-color: #f3f5fa;
}
:deep(.uni-scroll-view-content) {
padding-bottom: 0.5rem;
}
:deep(.wd-radio),
:deep(.wd-checkbox) {
position: relative;
padding: 1rem !important;
}
:deep(.wd-radio)::after,
:deep(.wd-checkbox)::after {
position: absolute;
bottom: 0;
left: 4%;
width: 92%;
content: '';
border-bottom: 1px solid #efefef;
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<view class="px-2 text-3.5">
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="pt-2">
<wd-textarea
custom-class="!bg-transparent"
custom-textarea-class="h-16"
:placeholder="placeholder"
:maxlength="250"
v-model="text"
show-word-limit
@input="change(id, $event)"
></wd-textarea>
</view>
</view>
</template>
<script setup lang="ts">
const emits = defineEmits(['change'])
const text = ref<string>('')
const props = defineProps({
id: {
type: Number,
required: true
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请输入'
}
})
onMounted(() => {
text.value = props.value
})
const change = (id, data) => {
emits('change', { id, value: data.value })
}
</script>
<style lang="scss" scoped>
:deep(.wd-textarea__value),
:deep(.wd-textarea__count) {
background: transparent !important;
}
:deep(.wd-textarea__inner) {
font-size: 0.875rem;
}
.wd-textarea {
padding: 0;
}
</style>

View File

@ -0,0 +1,194 @@
<template>
<view class="px-2 text-3.5">
<view v-if="inline">
<view class="flex flex-items-center pos-relative pb-1.5" @click="toSelect">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
<view class="ml-a mr-2" :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
<view v-else>
<view class="flex flex-items-center pos-relative">
<view v-if="required" class="color-#f62933 pos-absolute left--2 mt-1">*</view>
<view>{{ title }}</view>
</view>
<view class="py-2" @click="toSelect">
<view class="flex flex-items-center flex-justify-between">
<view :class="[text ? 'custom-color-black' : 'color-#bfbfbf']">
{{ text || placeholder }}
</view>
<wd-icon name="arrow-right" color="rgba(0,0,0,0.25)" size="18px"></wd-icon>
</view>
</view>
</view>
<wd-popup v-model="show" position="bottom" custom-style="border-radius:12rpx;">
<view v-if="showDuration">
<view
class="px-4 py-2 text-3.5 border-b-1 border-[#dcdcdc] border-solid flex flex-items-center"
>
<view @click="show = false">取消</view>
<view class="font-bold text-4 flex-1 text-center">访问时长</view>
<view class="flex flex-items-center" @click="changeSelect">
<view class="custom-color-blue">自定义时间</view>
<wd-icon name="arrow-right" size="14px" class="ml-1" color="#255cf7"></wd-icon>
</view>
</view>
<scroll-view class="h-60 text-3.5" :scroll-y="true">
<view
v-for="item in durationList"
:key="item.value"
@click="changeDuration(item)"
class="py-4 px-4 flex flex-items-center"
>
<view>{{ item.label }}</view>
<view
class="bg-#f3f5fa ml-a w-12 h-6 rounded-5 flex flex-items-center flex-justify-center"
>
<wd-icon
v-if="duration === item.label"
name="check"
size="15px"
class="ml-1"
color="#255cf7"
></wd-icon>
</view>
</view>
</scroll-view>
</view>
<view v-else>
<view
class="px-4 py-2 text-3.5 border-b-1 border-[#dcdcdc] border-solid flex flex-items-center"
>
<view class="flex flex-items-center" @click="showDuration = true">
<wd-icon name="arrow-left" size="14px" class="ml-1" color="#0d0f10"></wd-icon>
<view class="custom-color-black">返回</view>
</view>
<view class="font-bold text-4 flex-1 text-center">时间选择器</view>
<wd-icon
name="close"
size="14px"
class="ml-1"
color="#0d0f10"
@click="show = false"
></wd-icon>
</view>
<wd-datetime-picker-view
:formatter="formatter"
type="datetime"
v-model="timestamp"
@change="change"
/>
</view>
<view
@click="confirm"
class="py-2.5 rounded custom-bg-blue w-90% mx-5% font-bold text-center color-white text-3.5 my-2"
>
完成
</view>
</wd-popup>
</view>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
const text = ref<string | null>(null)
const show = ref<boolean>(false)
const timestamp = ref<number>(0)
const duration = ref<string>('')
const showDuration = ref<boolean>(true)
const formatter = (type, value) => {
switch (type) {
case 'year':
return value + '年'
case 'month':
return value + '月'
case 'date':
return value + '日'
case 'hour':
return value + '时'
case 'minute':
return value + '分'
default:
return value
}
}
const props = defineProps({
id: {
type: Number,
required: true
},
required: {
type: Boolean,
default: false
},
title: {
type: String,
required: true
},
value: {
type: [String, null],
default: null
},
placeholder: {
type: String,
default: '请选择'
},
inline: {
type: Boolean,
default: false
}
})
const durationList = [
{ label: '30分钟', value: 1800000 },
{ label: '1小时', value: 3600000 },
{ label: '2小时', value: 7200000 },
{ label: '3小时', value: 10800000 },
{ label: '5小时', value: 18000000 },
{ label: '8小时', value: 28800000 },
{ label: '12小时', value: 43200000 },
{ label: '24小时', value: 86400000 }
]
onMounted(() => {
if (props.value) {
text.value = props.value
duration.value = props.value
}
})
const changeSelect = () => {
timestamp.value = new Date().getTime()
showDuration.value = false
}
const toSelect = () => {
show.value = true
}
const change = value => {
timestamp.value = value.value
duration.value = ''
}
const changeDuration = item => {
duration.value = item.label
timestamp.value = 0
}
const confirm = () => {
if (timestamp.value === 0) {
text.value = duration.value
} else {
text.value = dayjs(timestamp.value).format('YYYY-M-D HH:mm')
}
show.value = false
}
</script>

View File

@ -0,0 +1,89 @@
<template>
<view class="bg-white mx-4 p-2 rounded-2 mb-2 shadow-sm">
<Input :id="0" title="访客姓名" :required="true" @change="inputChange" inline></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Input
:id="1"
title="访客手机"
:required="true"
:maxlength="11"
@change="inputChange"
inline
type="number"
></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<SelectPicker required :id="2" title="访客类型" :columns="columns" inline></SelectPicker>
<wd-divider color="#bcbfbe"></wd-divider>
<NavigatorSelector :id="3" title="通行门禁点" type="accessControl" inline></NavigatorSelector>
</view>
<view class="bg-white mx-4 p-2 rounded-2 mb-2 shadow-sm">
<Keyboard :id="4" title="车牌号码" type="car" :maxlength="8" inline></Keyboard>
</view>
<view class="bg-white mx-4 p-2 rounded-2 mb-2 shadow-sm">
<DatetimePicker
:id="5"
ref="startDatetimePicker"
title="预约到访时间"
@change="changeDate"
type="datetime"
inline
required
></DatetimePicker>
<wd-divider color="#bcbfbe"></wd-divider>
<VisitDuration :id="6" title="访问时长" required value="2小时" inline></VisitDuration>
<wd-divider color="#bcbfbe"></wd-divider>
<Input :id="7" title="同行人数" @change="inputChange" inline></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Input :id="8" title="访问单位" @change="inputChange" inline></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Input :id="9" title="到访事由说明" @change="inputChange" inline></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Input :id="10" title="访问地址" @change="inputChange" inline></Input>
<wd-divider color="#bcbfbe"></wd-divider>
<Description :id="11" title="表单通过后,访客将收到断音邀请通知"></Description>
</view>
</template>
<script setup lang="ts">
import Input from '@/pages/approval/components/Input.vue'
import SelectPicker from '@/pages/approval/components/SelectPicker.vue'
import Description from '@/pages/approval/components/Description.vue'
import Keyboard from '@/pages/approval/components/Keyboard.vue'
import DatetimePicker from '@/pages/approval/components/DatetimePicker.vue'
import NavigatorSelector from '@/pages/approval/components/NavigatorSelector.vue'
import VisitDuration from '@/pages/approval/components/VisitDuration.vue'
const columns = ref<Record<number, string>>([
{
value: 0,
label: '外卖快递'
},
{
value: 1,
label: '会议洽谈'
},
{
value: 2,
label: '探亲访友'
},
{
value: 3,
label: '业务沟通'
}
])
const inputChange = e => {
console.log('inputChange', e)
}
const changeDate = e => {
// timestamp.value = e.value
console.log('changeDate', e)
}
</script>
<style lang="scss" scoped>
.wd-divider {
padding: 0 0.5rem;
}
</style>

View File

@ -0,0 +1,42 @@
<route lang="json5">
{
style: {
navigationStyle: 'custom',
disableScroll: true
}
}
</route>
<template>
<view class="h-100vh flex flex-col">
<TopNavigation :title="title"></TopNavigation>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<Form></Form>
<ApprovalCreate></ApprovalCreate>
</scroll-view>
<view class="pb-safe border-#eef0f5 border-t-solid">
<view class="flex flex-items-center flex-justify-around py-3 px-3">
<view class="py-2 w-45% text-center bg-#e2e5ea custom-color-blue rounded-2">保存草稿</view>
<view class="opacity-60% py-2 w-45% text-center custom-bg-blue color-white rounded-2">
提交
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import Form from '@/pages/approval/components/Form.vue'
import ApprovalCreate from '@/pages/approval/components/ApprovalCreate.vue'
const title = ref<string>('')
const id = ref<number>(null)
onLoad(options => {
if (options.title) {
title.value = options.title
}
if (options.id) {
id.value = Number(options.id)
}
})
</script>

View File

@ -11,9 +11,9 @@
<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-for="(item, index) in pages" :key="index" v-show="curIndex == index">
<component :is="item"></component>
</view>
<AttendanceClockIn v-show="curIndex === 0"></AttendanceClockIn>
<AttendanceStatistics v-show="curIndex === 1"></AttendanceStatistics>
<AttendanceSet v-show="curIndex === 2"></AttendanceSet>
</scroll-view>
</view>
<CustomTabBar :list="list" :default-index="0" @change="change"></CustomTabBar>

View File

@ -50,7 +50,7 @@
const clickMenu = () => {
uni.navigateTo({
url: '/pages/application-list/application-list'
url: '/pages/home/application-list'
})
}

View File

@ -40,7 +40,7 @@
<HomeSwiper @colorChange="colorChange"></HomeSwiper>
<HomeBulletin class="my-2"></HomeBulletin>
<HomeTodo class="my-2"></HomeTodo>
<CustomTab :list="featuresList" @clickItem="clickItem"></CustomTab>
<CustomTab :list="featuresList"></CustomTab>
<HomeOpenDoor class="my-2"></HomeOpenDoor>
<HomeAttendance class="my-2"></HomeAttendance>
<HomeTeamManager class="my-2"></HomeTeamManager>
@ -56,25 +56,26 @@
</template>
<script lang="ts" setup>
import CustomTab from '@/pages/home/HomeTab.vue'
import CustomTab from '@/pages/home/compoents/HomeTab.vue'
import { useBasicStore, useUserStore } from '@/store'
import { Result } from '@/constants/result'
import { HomeTab } from '@/typings'
import HomeSwiper from '@/pages/home/HomeSwiper.vue'
import HomeBulletin from '@/pages/home/HomeBulletin.vue'
import HomeTodo from '@/pages/home/HomeTodo.vue'
import HomeOpenDoor from '@/pages/home/HomeOpenDoor.vue'
import HomeAttendance from '@/pages/home/HomeAttendance.vue'
import HomeTeamManager from '@/pages/home/HomeTeamManager.vue'
import HomeSetting from '@/pages/home/HomeSetting.vue'
import HomeAddDevice from '@/pages/home/HomeAddDevice.vue'
import HomeAddTeamManager from '@/pages/home/HomeAddTeamManager.vue'
import HomeSwiper from '@/pages/home/compoents/HomeSwiper.vue'
import HomeBulletin from '@/pages/home/compoents/HomeBulletin.vue'
import HomeTodo from '@/pages/home/compoents/HomeTodo.vue'
import HomeOpenDoor from '@/pages/home/compoents/HomeOpenDoor.vue'
import HomeAttendance from '@/pages/home/compoents/HomeAttendance.vue'
import HomeTeamManager from '@/pages/home/compoents/HomeTeamManager.vue'
import HomeSetting from '@/pages/home/compoents/HomeSetting.vue'
import HomeAddDevice from '@/pages/home/compoents/HomeAddDevice.vue'
import HomeAddTeamManager from '@/pages/home/compoents/HomeAddTeamManager.vue'
import TeamPopup from '@/components/TeamPopup/TeamPopup.vue'
import GetSystemInfoResult = UniNamespace.GetSystemInfoResult
const $user = useUserStore()
const $basic = useBasicStore()
const systemInfo = ref(null)
const systemInfo = ref<GetSystemInfoResult>(null)
const color = ref<string>('#bfcbef')
@ -318,11 +319,4 @@
const colorChange = data => {
color.value = data
}
const clickItem = item => {
console.log(item)
uni.navigateTo({
url: item.url
})
}
</script>

View File

@ -124,7 +124,7 @@
}
} else if (type.value === 'reset-password') {
await uni.redirectTo({
url: `/pages/reset-password/reset-password?phone=${phone.value}&code=${code.value}`
url: `/pages/login/reset-password?phone=${phone.value}&code=${code.value}`
})
}
}
@ -159,4 +159,8 @@
border: #b8b8b8 solid 2rpx;
border-radius: 12rpx;
}
page {
background-color: #ffffff;
}
</style>

View File

@ -63,7 +63,7 @@
uni.hideLoading()
if (result.errorCode === Result.Success.code) {
await uni.navigateTo({
url: `/pages/reset-password/reset-password?phone=${phone.value}`
url: `/pages/login/reset-password?phone=${phone.value}`
})
} else {
await uni.showToast({
@ -85,3 +85,9 @@
phone.value = value
}
</script>
<style lang="scss">
page {
background-color: #ffffff;
}
</style>

View File

@ -61,7 +61,7 @@
:disabled="!phonePass"
:round="false"
size="large"
@click="codeLogin"
@click="codeLogin(false, $event)"
>
获取验证码
</wd-button>
@ -264,7 +264,7 @@
})
uni.hideLoading()
if (result.errorCode === Result.Success.code) {
let url = `/pages/code/code?phone=${phone.value}&type=login`
let url = `/pages/login/code?phone=${phone.value}&type=login`
if (tip) {
url = url + `&tip=true`
}
@ -298,7 +298,7 @@
params = `?phone=${phone.value}`
}
uni.navigateTo({
url: `/pages/get-code/get-code${params}`
url: `/pages/login/get-code${params}`
})
}
@ -325,3 +325,9 @@
consentAgreement.value = !consentAgreement.value
}
</script>
<style lang="scss">
page {
background-color: #ffffff;
}
</style>

View File

@ -226,4 +226,8 @@
}
</script>
<style scoped lang="scss"></style>
<style lang="scss">
page {
background-color: #ffffff;
}
</style>

View File

@ -1,4 +1,4 @@
<route lang="json5" type="home">
<route lang="json5">
{
style: {
navigationStyle: 'custom',

View File

@ -0,0 +1,56 @@
<template>
<view class="flex flex-items-center py-2 text-4" @click="toClick">
<view
v-if="item.type === 'member'"
class="w-10 h-10 flex flex-justify-center flex-items-center"
>
<image
src="/static/images/icon_default_avatar.png"
class="w-8 h-8 rounded-2"
mode="aspectFill"
></image>
</view>
<view v-else class="w-10 h-10 flex flex-justify-center flex-items-center bg-#e4f1ff rounded-2">
<image src="/static/images/icon_file.png" class="w-6 h-6" mode="aspectFill"></image>
</view>
<view class="ml-2 break-all max-w-40 overflow-hidden text-ellipsis line-clamp-1">
{{ item.name }}
</view>
<view class="ml-a" v-if="item.type !== 'member'">
<wd-divider vertical></wd-divider>
</view>
<view
v-if="item.type !== 'member'"
:class="[disabled ? 'color-#87a9fb' : 'custom-color-blue']"
class="ml-1"
>
下级
</view>
<wd-icon
name="arrow-right"
size="14px"
class="ml-2"
:color="disabled ? '#87a9fb' : '#255cf7'"
v-if="item.type !== 'member'"
></wd-icon>
</view>
</template>
<script setup lang="ts">
const emits = defineEmits(['click'])
const props = defineProps({
item: {
type: Object,
required: true
},
disabled: {
type: Boolean,
default: false
}
})
const toClick = () => {
emits('click')
}
</script>

View File

@ -0,0 +1,42 @@
<template>
<view class="flex flex-items-center py-2 text-4" @click="toClick">
<view
v-if="item.type === 'member'"
class="w-10 h-10 flex flex-justify-center flex-items-center"
>
<image
src="/static/images/icon_default_avatar.png"
class="w-8 h-8 rounded-2"
mode="aspectFill"
></image>
</view>
<view v-else class="w-10 h-10 flex flex-justify-center flex-items-center bg-#e4f1ff rounded-2">
<image src="/static/images/icon_file.png" class="w-6 h-6" mode="aspectFill"></image>
</view>
<view class="ml-2">
<view class="break-all max-w-40 overflow-hidden text-ellipsis line-clamp-1">
{{ item.name }}
</view>
<view
class="color-#838589 text-3 break-all max-w-40 overflow-hidden text-ellipsis line-clamp-1"
>
xxx的互联/test
</view>
</view>
</view>
</template>
<script setup lang="ts">
const emits = defineEmits(['click'])
const props = defineProps({
item: {
type: Object,
required: true
}
})
const toClick = () => {
emits('click')
}
</script>

View File

@ -0,0 +1,100 @@
<route lang="json5">
{
style: {
navigationStyle: 'custom',
disableScroll: true
}
}
</route>
<template>
<view class="h-100vh flex flex-col">
<TopNavigation class="bg-white" title="选择门禁点"></TopNavigation>
<scroll-view class="flex-1 box-border text-3.5 custom-color-black border-1" :scroll-y="true">
<wd-checkbox-group v-model="value" size="large" @change="change">
<view class="px-4 py-1.5 bg-white mb-2">
<wd-checkbox :modelValue="item.id" v-for="item in permissionList" :key="item.id">
<view class="flex flex-items-center">
<view
class="w-10 h-10 flex flex-justify-center flex-items-center bg-#e4f1ff rounded-2"
>
<image src="/static/images/icon_file.png" class="w-6 h-6" mode="aspectFill"></image>
</view>
<view class="ml-2">{{ item.name }}</view>
</view>
</wd-checkbox>
</view>
<view
v-for="(item, index) in list"
:key="item.id"
class="bg-white border-#eef0f5 border-b-solid"
:class="[index === list.length - 1 ? 'border-b-0' : 'border-b-1']"
>
<wd-checkbox :modelValue="item.id" class="py-1.5 px-4">
<view class="flex flex-items-center">
<image
src="https://file.hikmall.com/prod/image/69c3851d052e493ebb6e7c2e7a189b61.png"
class="w-10 h-10"
></image>
<view class="ml-2">{{ item.name }}</view>
</view>
</wd-checkbox>
</view>
</wd-checkbox-group>
</scroll-view>
<view class="pb-safe border-#eef0f5 border-t-solid border-1 flex flex-items-center">
<view
@click="confirm"
class="opacity-60% w-90% py-2 mx-5% text-center custom-bg-blue color-white rounded-2 my-3"
>
确定
</view>
</view>
</view>
</template>
<script setup lang="ts">
const instance = getCurrentInstance().proxy
const eventChannel = instance.getOpenerEventChannel()
const value = ref<number[]>([])
const selected = ref<Array>([])
const permissionList = [
{
name: '[访客类型]权限组',
id: 0
}
]
const list = [
{
name: 'DS-K(FU6004429)',
id: 1
},
{
name: 'DS-K(L40959329)',
id: 2
}
]
const change = value => {
selected.value = []
selected.value.push(...permissionList.filter(item => value.value.includes(item.id)))
selected.value.push(...list.filter(item => value.value.includes(item.id)))
}
const confirm = () => {
eventChannel.emit('change', { value: selected.value })
uni.navigateBack()
}
</script>
<style scoped lang="scss">
.wd-checkbox-group {
background-color: transparent;
}
.wd-checkbox {
margin-bottom: 0;
}
</style>

View File

@ -0,0 +1,276 @@
<route lang="json5">
{
style: {
navigationStyle: 'custom',
disableScroll: true
}
}
</route>
<template>
<view>
<view v-if="showSearch" class="h-[calc(100vh-60px)] flex flex-col">
<view v-if="systemInfo" :style="{ marginTop: systemInfo.safeAreaInsets?.top + 'px' }">
<view class="h-12 pt-1 pb-2">
<wd-search
:placeholder-left="true"
:focus="false"
@change="changeSearch"
@cancel="showSearch = false"
/>
</view>
</view>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<view class="bg-white">
<view
v-for="item in list"
:key="item.id"
class="border-[#ebebeb] border-b-1 border-b-solid px-4 flex flex-items-center"
>
<view
v-if="!(type === 'member' && item.type === 'department')"
class="mr-3"
@click="toClick(item)"
>
<wd-icon
v-if="value.includes(item)"
name="check-circle-filled"
color="#255cf9"
size="26px"
></wd-icon>
<wd-icon v-else name="circle1" color="#838589" size="26px"></wd-icon>
</view>
<SearchItem class="flex-1" :item="item" @click="toClick(item)"></SearchItem>
</view>
</view>
</scroll-view>
</view>
<view v-if="!showSearch" class="h-[calc(100vh-60px-env(safe-area-inset-bottom))] flex flex-col">
<TopNavigation :title="title"></TopNavigation>
<view
@click="showSearch = true"
class="bg-white flex flex-justify-center flex-items-center rounded color-#a6a6a6 mx-4 mt-3 py-1.5"
>
<wd-icon name="search" size="16px" class="mr-2"></wd-icon>
<view>搜索</view>
</view>
<view class="flex flex-items-center m-4 text-3.5 break-all overflow-hidden whitespace-nowrap">
<view
v-for="(department, index) in organizationList"
:key="department.id"
class="flex flex-items-center"
@click="toOrganization(index)"
>
<span
:class="[index === organizationList.length - 1 ? 'color-#bfbfbf' : 'custom-color-blue']"
>
{{ department.name }}
</span>
<span v-if="index !== organizationList.length - 1" class="mx-0.5">/</span>
</view>
</view>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<view class="bg-white">
<view
v-for="item in list"
:key="item.id"
class="border-[#ebebeb] border-b-1 border-b-solid px-4 flex flex-items-center"
>
<view
v-if="!(type === 'member' && item.type === 'department')"
class="mr-3"
@click="toClick(item)"
>
<wd-icon
v-if="value.includes(item)"
name="check-circle-filled"
color="#255cf9"
size="26px"
></wd-icon>
<wd-icon v-else name="circle1" color="#838589" size="26px"></wd-icon>
</view>
<OrganizationItem
class="flex-1"
:item="item"
:disabled="item.type === 'department' && value.includes(item)"
@click="toClick(item)"
></OrganizationItem>
</view>
</view>
<view class="py-5 px-15">
<wd-divider color="#838589">仅显示已开通账号的人员</wd-divider>
</view>
</scroll-view>
</view>
<view
class="pb-safe h-60px px-4 border-[#ebebeb] border-t-1 border-t-solid text-3.5 flex flex-items-center"
>
<view class="flex flex-items-center flex-justify-between w-full">
<view class="flex flex-items-center" v-if="value.length" @click="showSelected = true">
<view class="custom-color-blue">已选中{{ value.length }}个人</view>
<wd-icon name="arrow-right" size="16px" class="ml-2" color="#255cf7"></wd-icon>
</view>
<view v-else></view>
<view class="custom-bg-blue color-white py-1 px-5 rounded" @click="confirm">确定</view>
</view>
</view>
</view>
<wd-popup v-model="showSelected" position="bottom">
<view class="h-100vh flex flex-col bg-#f3f5fa">
<TopNavigation
title="已选中"
:have-back="false"
right-button-text="确定"
@right-button="showSelected = false"
></TopNavigation>
<scroll-view class="flex-1 box-border" :scroll-y="true">
<view class="bg-white">
<view
v-for="item in value"
:key="item.id"
class="flex flex-items-center px-4 py-3 border-[#ebebeb] border-b-1 border-b-solid"
>
<image :src="item.avatar" class="w-10 h-10 rounded-2"></image>
<view class="ml-4 text-3.5">
<view>{{ item.name }}</view>
<view class="mt-1 color-#a6a6a6 text-3">{{ item.name }}</view>
</view>
<view class="p-1 ml-a bg-#f3f5f8 rounded-50%" @click="deleteItem(item)">
<image src="/static/images/icon_delete.png" class="w-5 h-5"></image>
</view>
</view>
</view>
</scroll-view>
</view>
</wd-popup>
</template>
<script setup lang="ts">
import { useBasicStore } from '@/store'
import OrganizationItem from '@/pages/select/components/OrganizationItem.vue'
import SearchItem from '@/pages/select/components/SearchItem.vue'
import GetSystemInfoResult = UniNamespace.GetSystemInfoResult
const instance = getCurrentInstance().proxy
const eventChannel = instance.getOpenerEventChannel()
const type = ref<string>('')
const multiple = ref<boolean>(false)
const title = ref<string>('')
const showSearch = ref<boolean>(false)
const organizationList = ref<Array<object>>([
{
id: 1,
type: 'department',
name: '技术部'
}
])
const $basic = useBasicStore()
const systemInfo = ref<GetSystemInfoResult>(null)
const value = ref<Array>([])
const showSelected = ref<boolean>(false)
const list = ref<Array<object>>([
{
id: 0,
type: 'department',
name: 'xxx的互联',
avatar: '/static/images/icon_file.png'
},
{
id: 1,
type: 'member',
name: '张三',
avatar: '/static/images/icon_default_avatar.png'
},
{
id: 2,
type: 'member',
name: '李四',
avatar: '/static/images/icon_default_avatar.png'
},
{
id: 3,
type: 'member',
name: '王五',
avatar: '/static/images/icon_default_avatar.png'
}
])
const toClick = item => {
if (value.value.includes(item)) {
value.value = value.value.filter(v => v !== item)
} else {
if (multiple.value || value.value.length === 0) {
value.value.push(item)
} else {
uni.showToast({
title: '最多选择一个',
icon: 'none'
})
}
}
}
const deleteItem = item => {
value.value = value.value.filter(v => v !== item)
}
onMounted(async () => {
systemInfo.value = await $basic.getSystemInfo()
})
function changeSearch({ value }) {
console.log('输入', value)
}
onLoad(options => {
const params = JSON.parse(options.params)
type.value = params.type
multiple.value = params.multiple
title.value = params.title
})
const toOrganization = index => {
if (index === organizationList.value.length - 1) {
return
}
uni.navigateBack({
delta: organizationList.value.length - index - 1
})
}
const change = e => {
console.log('change', e)
}
const confirm = () => {
eventChannel.emit('change', { value: value.value })
uni.navigateBack({
delta: organizationList.value.length
})
}
</script>
<style scoped lang="scss">
:deep(.wd-checkbox) {
margin-bottom: 0;
}
.wd-search {
background: transparent;
}
:deep(.wd-search__block) {
padding: 3px 0;
background-color: #e2e5ea;
border-radius: 0.5rem;
}
:deep(.wd-search__cancel) {
color: #a6a6a6;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -4,10 +4,10 @@
// Generated by vite-plugin-uni-pages
interface NavigateToOptions {
url: "/pages/mine/mine" |
"/pages/home/home" |
"/pages/application-list/application-list" |
url: "/pages/home/home" |
"/pages/approval/approval-detail" |
"/pages/approval/approval" |
"/pages/approval/create-application" |
"/pages/attendance/allowed-time" |
"/pages/attendance/attendance-rules" |
"/pages/attendance/attendance" |
@ -16,18 +16,27 @@ interface NavigateToOptions {
"/pages/attendance/flexible-punching" |
"/pages/attendance/issue-record-detail" |
"/pages/attendance/issue-record" |
"/pages/code/code" |
"/pages/get-code/get-code" |
"/pages/home/application-list" |
"/pages/info-publish/add-release-plan" |
"/pages/info-publish/announce-notice" |
"/pages/info-publish/basic-info" |
"/pages/info-publish/drafts-list" |
"/pages/info-publish/edit-pic-video" |
"/pages/info-publish/info-publish" |
"/pages/info-publish/material-library" |
"/pages/info-publish/notice-details" |
"/pages/info-publish/notice-manage" |
"/pages/info-publish/play-content-library" |
"/pages/info-publish/release-plan" |
"/pages/login/code" |
"/pages/login/get-code" |
"/pages/login/login" |
"/pages/login/reset-password" |
"/pages/mine/mine" |
"/pages/notification/notification" |
"/pages/personnel-passage/traffic-correlation" |
"/pages/reset-password/reset-password" |
"/pages/select/select-access-control" |
"/pages/select/select-organization" |
"/pages/workbench/workbench" |
"/pages/attendance/attendance-add-group/attendance-add-group" |
"/pages/attendance/attendance-add-group/attendance-device" |