Merge branch 'develop' into develop_wsy
# Conflicts: # src/pages.json # src/types/uni-pages.d.ts
@ -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 () => {
|
||||
|
||||
@ -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()
|
||||
})
|
||||
|
||||
113
src/pages.json
@ -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",
|
||||
@ -207,11 +267,13 @@
|
||||
"needLogin": false
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/mine",
|
||||
"path": "pages/login/reset-password",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
"navigationStyle": "custom",
|
||||
"disableScroll": true
|
||||
},
|
||||
"needLogin": false
|
||||
},
|
||||
{
|
||||
"path": "pages/notification/notification",
|
||||
@ -226,13 +288,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",
|
||||
@ -433,4 +502,4 @@
|
||||
}
|
||||
],
|
||||
"subPackages": []
|
||||
}
|
||||
}
|
||||
|
||||
66
src/pages/approval/approval-detail.vue
Normal 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>
|
||||
@ -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)
|
||||
|
||||
65
src/pages/approval/components/ApplicationList.vue
Normal 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>
|
||||
61
src/pages/approval/components/ApprovalContent.vue
Normal 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>
|
||||
151
src/pages/approval/components/ApprovalCreate.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<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="w-10 text-center break-all overflow-hidden text-ellipsis line-clamp-1"
|
||||
>
|
||||
213321123321312213321123
|
||||
</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 class="mb-2 w-fit mr-2">
|
||||
<view
|
||||
class="h-10 w-10 rounded-2 border-#255cf7 border-1 border-solid flex flex-items-center flex-justify-center box-border"
|
||||
>
|
||||
<wd-icon name="add" size="22px" color="#255cf7"></wd-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for="item in 8" :key="item" class="mb-2 w-fit mr-2">
|
||||
<view class="border-0">
|
||||
<image
|
||||
src="https://file.hikmall.com/prod/image/4921b7596d2344088f8611f503b011dc.png"
|
||||
class="h-10 w-10 rounded-2"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view
|
||||
class="w-10 text-center break-all overflow-hidden text-ellipsis line-clamp-1"
|
||||
>
|
||||
xxx
|
||||
</view>
|
||||
</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="w-10 text-center break-all overflow-hidden text-ellipsis line-clamp-1"
|
||||
>
|
||||
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="w-10 text-center break-all overflow-hidden text-ellipsis line-clamp-1"
|
||||
>
|
||||
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>
|
||||
81
src/pages/approval/components/ApprovalProcess.vue
Normal 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>
|
||||
158
src/pages/approval/components/ApprovalRecords.vue
Normal 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>
|
||||
273
src/pages/approval/components/DatetimePicker.vue
Normal 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>
|
||||
110
src/pages/approval/components/DatetimePickerGroup.vue
Normal 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>
|
||||
18
src/pages/approval/components/Description.vue
Normal 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>
|
||||
145
src/pages/approval/components/Form.vue
Normal 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>
|
||||
61
src/pages/approval/components/Images.vue
Normal 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>
|
||||
109
src/pages/approval/components/Input.vue
Normal 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>
|
||||
94
src/pages/approval/components/Keyboard.vue
Normal 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>
|
||||
97
src/pages/approval/components/Leave.vue
Normal 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>
|
||||
94
src/pages/approval/components/NavigatorSelector.vue
Normal 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>
|
||||
43
src/pages/approval/components/Overtime.vue
Normal 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>
|
||||
128
src/pages/approval/components/SelectPicker.vue
Normal 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>
|
||||
71
src/pages/approval/components/Textarea.vue
Normal 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>
|
||||
194
src/pages/approval/components/VisitDuration.vue
Normal 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>
|
||||
89
src/pages/approval/components/Visitor.vue
Normal 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>
|
||||
42
src/pages/approval/create-application.vue
Normal 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>
|
||||
@ -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>
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
|
||||
const clickMenu = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/application-list/application-list'
|
||||
url: '/pages/home/application-list'
|
||||
})
|
||||
}
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -269,7 +270,8 @@
|
||||
{
|
||||
id: 6093,
|
||||
icon: 'https://file.hikmall.com/prod/image/8ed90fc35e3840e782d73676efcc9a30.png',
|
||||
name: '信息发布'
|
||||
name: '信息发布',
|
||||
url: '/pages/info-publish/info-publish'
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -322,11 +324,4 @@
|
||||
const colorChange = data => {
|
||||
color.value = data
|
||||
}
|
||||
|
||||
const clickItem = item => {
|
||||
console.log(item)
|
||||
uni.navigateTo({
|
||||
url: item.url
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
281
src/pages/info-publish/add-release-plan.vue
Normal file
@ -0,0 +1,281 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="添加发布计划"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view class="plan-form">
|
||||
<!-- 计划名称 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>计划名称</text>
|
||||
</view>
|
||||
<input
|
||||
type="text"
|
||||
v-model="formData.name"
|
||||
placeholder="智慧屏202501171038843"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 计划描述 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">计划描述</view>
|
||||
<input
|
||||
type="text"
|
||||
v-model="formData.description"
|
||||
placeholder="请输入"
|
||||
class="form-input"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 播放规则 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>播放规则</text>
|
||||
</view>
|
||||
<view class="form-value" @click="handleSelectRule">
|
||||
<text>每天循环播放</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 播放时间与内容 -->
|
||||
<view class="form-section">
|
||||
<view class="section-header">
|
||||
<text class="required">*</text>
|
||||
<text>播放时间与内容</text>
|
||||
</view>
|
||||
|
||||
<view class="time-content-card">
|
||||
<view class="time-row">
|
||||
<text class="label">时段</text>
|
||||
<text class="value">00:00– 23:59</text>
|
||||
<text class="action-icon">▶</text>
|
||||
<text class="delete-icon">🗑</text>
|
||||
</view>
|
||||
<view class="content-row">
|
||||
<text class="label">内容</text>
|
||||
<text class="value ellipsis">智慧屏节目2024...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="add-time-btn" @click="handleAddTime">
|
||||
<text class="plus-icon">+</text>
|
||||
<text>添加时段</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 关联设备 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
<text>关联设备</text>
|
||||
</view>
|
||||
<view class="form-value" @click="handleSelectDevice">
|
||||
<text class="placeholder">请选择</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button class="submit-btn" @click="handleSubmit">保存并发布</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
name: '',
|
||||
description: '',
|
||||
rule: '每天循环播放',
|
||||
timeSlots: [],
|
||||
devices: []
|
||||
})
|
||||
|
||||
// 选择播放规则
|
||||
const handleSelectRule = () => {
|
||||
// 实现规则选择逻辑
|
||||
}
|
||||
|
||||
// 添加时段
|
||||
const handleAddTime = () => {
|
||||
// 实现添加时段逻辑
|
||||
}
|
||||
|
||||
// 选择设备
|
||||
const handleSelectDevice = () => {
|
||||
// 实现设备选择逻辑
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = () => {
|
||||
// 实现表单提交逻辑
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.plan-form {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
|
||||
.form-input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.form-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
margin-left: 8px;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
|
||||
.required {
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time-content-card {
|
||||
padding: 12px;
|
||||
margin-bottom: 12px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
|
||||
.time-row,
|
||||
.content-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 40px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex: 1;
|
||||
margin: 0 8px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.action-icon,
|
||||
.delete-icon {
|
||||
padding: 4px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-time-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
color: #4080ff;
|
||||
|
||||
.plus-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
@ -8,100 +8,85 @@
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="新增公告"></TopNavigation>
|
||||
<div class="announce-notice">
|
||||
<!-- 表单内容 -->
|
||||
<div class="form-content">
|
||||
<div class="form-item">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
公告标题
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
v-model="formData.title"
|
||||
placeholder="请输入公告标题"
|
||||
class="input-field"
|
||||
/>
|
||||
</div>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="新增公告"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view class="announce-notice">
|
||||
<!-- 表单内容 -->
|
||||
<div class="form-content">
|
||||
<div class="form-item">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
公告标题
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
v-model="formData.title"
|
||||
placeholder="请输入公告标题"
|
||||
class="input-field"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
公告正文
|
||||
<div class="form-item">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
公告正文
|
||||
</div>
|
||||
<textarea
|
||||
v-model="formData.content"
|
||||
placeholder="请输入要发布的内容"
|
||||
class="textarea-field"
|
||||
@input="handleContentInput"
|
||||
></textarea>
|
||||
<div class="word-count">{{ contentLength }}/2000</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea
|
||||
v-model="formData.content"
|
||||
placeholder="请输入要发布的内容"
|
||||
class="textarea-field"
|
||||
@input="handleContentInput"
|
||||
></textarea>
|
||||
<div class="word-count">{{ contentLength }}/2000</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-btns">
|
||||
<button class="nextstep-btn" @click="handleNextStep">下一步</button>
|
||||
</view>
|
||||
</div>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-btns">
|
||||
<button class="nextstep-btn" @click="handleNextStep">下一步</button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
title: '',
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentLength() {
|
||||
return this.formData.content.length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.back()
|
||||
},
|
||||
handleContentInput() {
|
||||
if (this.formData.content.length > 2000) {
|
||||
this.formData.content = this.formData.content.slice(0, 2000)
|
||||
}
|
||||
},
|
||||
handleNextStep() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/info-publish/basic-info'
|
||||
})
|
||||
}
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
title: '',
|
||||
content: ''
|
||||
})
|
||||
|
||||
// 计算字数
|
||||
const contentLength = computed(() => formData.value.content.length)
|
||||
|
||||
// 处理内容输入
|
||||
const handleContentInput = () => {
|
||||
if (formData.value.content.length > 2000) {
|
||||
formData.value.content = formData.value.content.slice(0, 2000)
|
||||
}
|
||||
}
|
||||
|
||||
// 下一步按钮点击处理
|
||||
const handleNextStep = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/info-publish/basic-info'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.announce-notice {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
padding: 0 15px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
@ -117,6 +102,8 @@
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
@ -156,19 +143,17 @@
|
||||
padding: 10px 15px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.nextstep-btn {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.nextstep-btn {
|
||||
color: #fff;
|
||||
background-color: #007aff;
|
||||
}
|
||||
.nextstep-btn {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #007aff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -8,98 +8,100 @@
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<TopNavigation title="公告管理"></TopNavigation>
|
||||
<div class="basic-info">
|
||||
<!-- 基本信息区域 -->
|
||||
<div class="content">
|
||||
<div class="section-title">基本信息</div>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="公告管理"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view class="basic-info">
|
||||
<!-- 基本信息区域 -->
|
||||
<view class="content">
|
||||
<view class="section-title">基本信息</view>
|
||||
|
||||
<!-- 发布对象 -->
|
||||
<div class="form-item" @click="selectTarget">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
<span>发布对象</span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<span class="placeholder">请选择</span>
|
||||
<i class="arrow">></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 发布对象 -->
|
||||
<view class="form-item" @click="selectTarget">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>发布对象</text>
|
||||
</view>
|
||||
<view class="value">
|
||||
<text class="placeholder">请选择</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 发布类型 -->
|
||||
<div class="form-item" @click="showTimePicker = true">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
<span>发布时间</span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<span>{{ publishType }}</span>
|
||||
<i class="arrow">></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 发布类型 -->
|
||||
<view class="form-item" @click="handleShowTimePicker">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>发布时间</text>
|
||||
</view>
|
||||
<view class="value">
|
||||
<text>{{ publishType }}</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 发布日期 - 仅在定时发布时显示 -->
|
||||
<div class="form-item" v-if="isScheduled" @click="showDatePicker = true">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
<span>发布日期</span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<span>{{ publishDate }}</span>
|
||||
<i class="arrow">></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 发布日期 - 仅在定时发布时显示 -->
|
||||
<view class="form-item" v-if="isScheduled" @click="showDatePicker = true">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>发布日期</text>
|
||||
</view>
|
||||
<view class="value">
|
||||
<text>{{ publishDate }}</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 发布时间 - 仅在定时发布时显示 -->
|
||||
<div class="form-item" v-if="isScheduled" @click="showTimePickerDetail = true">
|
||||
<div class="label">
|
||||
<span class="required">*</span>
|
||||
<span>发布时间</span>
|
||||
</div>
|
||||
<div class="value">
|
||||
<span>{{ publishTimeDetail }}</span>
|
||||
<i class="arrow">></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 发布时间 - 仅在定时发布时显示 -->
|
||||
<view class="form-item" v-if="isScheduled" @click="showTimePickerDetail = true">
|
||||
<view class="label">
|
||||
<text class="required">*</text>
|
||||
<text>发布时间</text>
|
||||
</view>
|
||||
<view class="value">
|
||||
<text>{{ publishTimeDetail }}</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<div class="footer">
|
||||
<button class="draft-btn" @click="saveDraft">保存为草稿</button>
|
||||
<button class="publish-btn" @click="publish">发布公告</button>
|
||||
</div>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button class="draft-btn" @click="saveDraft">保存为草稿</button>
|
||||
<button class="publish-btn" @click="publish">发布公告</button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 发布类型选择弹窗 -->
|
||||
<transition name="slide-up">
|
||||
<div class="popup" v-if="showTimePicker">
|
||||
<div class="mask" @click="hideTimePicker"></div>
|
||||
<div class="popup-content">
|
||||
<div class="popup-header">
|
||||
<div class="popup-title">请选择发布时间</div>
|
||||
<div class="popup-close" @click="showTimePicker = false">×</div>
|
||||
</div>
|
||||
<div class="popup-body">
|
||||
<div
|
||||
class="time-option"
|
||||
:class="{ active: !isScheduled }"
|
||||
@click="selectPublishType('now')"
|
||||
>
|
||||
立即发布
|
||||
<i class="check-icon" v-if="!isScheduled">✓</i>
|
||||
</div>
|
||||
<div
|
||||
class="time-option"
|
||||
:class="{ active: isScheduled }"
|
||||
@click="selectPublishType('schedule')"
|
||||
>
|
||||
定时发布
|
||||
<i class="check-icon" v-if="isScheduled">✓</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
<view class="popup" v-if="showTimePicker">
|
||||
<view class="mask" @click="handleCloseTimePicker"></view>
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<view class="popup-title">请选择发布时间</view>
|
||||
<view class="popup-close" @click="handleCloseTimePicker">×</view>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view
|
||||
class="time-option"
|
||||
:class="{ active: !isScheduled }"
|
||||
@click="selectPublishType('now')"
|
||||
>
|
||||
<text>立即发布</text>
|
||||
<text class="check-icon" v-if="!isScheduled">✓</text>
|
||||
</view>
|
||||
<view
|
||||
class="time-option"
|
||||
:class="{ active: isScheduled }"
|
||||
@click="selectPublishType('schedule')"
|
||||
>
|
||||
<text>定时发布</text>
|
||||
<text class="check-icon" v-if="isScheduled">✓</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -155,6 +157,14 @@
|
||||
const publish = () => {
|
||||
// 发布公告逻辑
|
||||
}
|
||||
|
||||
const handleShowTimePicker = () => {
|
||||
showTimePicker.value = true
|
||||
}
|
||||
|
||||
const handleCloseTimePicker = () => {
|
||||
showTimePicker.value = false
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.basic-info {
|
||||
|
||||
161
src/pages/info-publish/edit-pic-video.vue
Normal file
@ -0,0 +1,161 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="编辑图片/视频轮播"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<view class="content-form">
|
||||
<!-- 名称 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">名称</view>
|
||||
<view class="form-value">
|
||||
<input
|
||||
type="text"
|
||||
v-model="formData.name"
|
||||
placeholder="请输入名称"
|
||||
class="form-input"
|
||||
/>
|
||||
<text v-if="formData.name" class="clear-icon" @click="clearName">×</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 屏幕方向 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">屏幕方向</view>
|
||||
<view class="form-value">
|
||||
<text>横屏</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 屏幕分辨率 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">屏幕分辨率</view>
|
||||
<view class="form-value">
|
||||
<text>1920*1080</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容类型 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">内容类型</view>
|
||||
<view class="form-value">
|
||||
<text>图片/视频轮播</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button class="next-btn" @click="handleNext">下一步</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
name: '智慧屏节目202412260150523'
|
||||
})
|
||||
|
||||
// 清除名称
|
||||
const clearName = () => {
|
||||
formData.value.name = ''
|
||||
}
|
||||
|
||||
// 下一步按钮点击事件
|
||||
const handleNext = () => {
|
||||
// 实现下一步逻辑
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.content-form {
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-value {
|
||||
display: flex;
|
||||
flex: 1; // 添加这行,让表单值区域占据剩余空间
|
||||
align-items: center;
|
||||
justify-content: flex-end; // 添加这行,让内容靠右对齐
|
||||
|
||||
.form-input {
|
||||
flex: 1; // 让输入框占据剩余空间
|
||||
height: 20px; // 设置合适的高度
|
||||
padding: 0; // 移除默认内边距
|
||||
margin-left: 16px; // 与左侧标签保持间距
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #333;
|
||||
text-align: right; // 文本右对齐
|
||||
background: transparent; // 透明背景
|
||||
border: none; // 移除边框
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
flex-shrink: 0; // 防止图标被压缩
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 8px;
|
||||
line-height: 16px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.next-btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,206 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view></view>
|
||||
<view class="h-[calc(100vh-50px)] flex flex-col">
|
||||
<TopNavigation title="信息发布"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<!-- 使用说明卡片 -->
|
||||
<view class="instruction-card">
|
||||
<view class="card-content">
|
||||
<view class="title">信息发布使用说明</view>
|
||||
<view class="subtitle">快速上手信息发布</view>
|
||||
<view class="detail-btn">
|
||||
看详情
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="card-icon" src="@/static/images/publish_icon.png" mode="aspectFit" />
|
||||
</view>
|
||||
|
||||
<!-- 功能列表 -->
|
||||
<view class="function-list">
|
||||
<view
|
||||
class="function-item"
|
||||
v-for="(item, index) in functionList"
|
||||
:key="index"
|
||||
@click="navigateTo(item.path)"
|
||||
>
|
||||
<view class="item-left">
|
||||
<image class="item-icon" :src="item.icon" mode="aspectFit" />
|
||||
<view class="item-info">
|
||||
<view class="item-title">{{ item.title }}</view>
|
||||
<view class="item-desc">{{ item.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<CustomTabBar :list="tabList" :default-index="0" @change="handleTabChange"></CustomTabBar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { TabBarItem } from '@/typings'
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
// 功能列表数据
|
||||
const functionList = ref([
|
||||
{
|
||||
title: '素材库',
|
||||
description: '管理图片、音频、视频等素材',
|
||||
icon: '/static/images/material_icon.png',
|
||||
path: '/pages/info-publish/material-library'
|
||||
},
|
||||
{
|
||||
title: '播放内容库',
|
||||
description: '将文字、图片、视频素材组合成节目',
|
||||
icon: '/static/images/content_icon.png',
|
||||
path: '/pages/info-publish/play-content-library'
|
||||
},
|
||||
{
|
||||
title: '发布计划',
|
||||
description: '设置播放内容与时间规则同步到设备',
|
||||
icon: '/static/images/plan_icon.png',
|
||||
path: '/pages/info-publish/release-plan'
|
||||
},
|
||||
{
|
||||
title: '公告管理',
|
||||
description: '发布手机公告给团队成员',
|
||||
icon: '/static/images/notice_icon.png',
|
||||
path: '/pages/info-publish/notice-manage'
|
||||
}
|
||||
])
|
||||
|
||||
// 底部标签栏配置
|
||||
const tabList = ref<Array<TabBarItem>>([
|
||||
{
|
||||
title: '首页',
|
||||
icon: 'home'
|
||||
},
|
||||
{
|
||||
title: '屏幕控制',
|
||||
icon: 'home'
|
||||
}
|
||||
])
|
||||
|
||||
// 页面跳转
|
||||
const navigateTo = (path: string) => {
|
||||
uni.navigateTo({
|
||||
url: path
|
||||
})
|
||||
}
|
||||
|
||||
// 标签切换处理
|
||||
const handleTabChange = (data: { value: number }) => {
|
||||
// 处理标签切换逻辑
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f6f8fc;
|
||||
}
|
||||
/* 通用箭头样式 - 放在最前面 */
|
||||
.arrow {
|
||||
font-size: 16px;
|
||||
color: #ccc;
|
||||
}
|
||||
/* 说明卡片样式 */
|
||||
.instruction-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 16px;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
border-radius: 12px;
|
||||
|
||||
.card-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.detail-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 12px;
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
|
||||
.arrow {
|
||||
color: #fff; /* 覆盖通用箭头样式 */
|
||||
}
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
/* 功能列表样式 */
|
||||
.function-list {
|
||||
margin: 16px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.function-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
.item-title {
|
||||
margin-bottom: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.item-desc {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
309
src/pages/info-publish/material-library.vue
Normal file
@ -0,0 +1,309 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="素材库"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<!-- 存储容量卡片 -->
|
||||
<view class="storage-card">
|
||||
<view class="storage-title">素材存储容量</view>
|
||||
<view class="storage-info">
|
||||
<text class="used-text">已用 0.00%</text>
|
||||
<text class="remain-text">剩余19.99 G/ 20.00 G</text>
|
||||
</view>
|
||||
<view class="progress-bar">
|
||||
<view class="progress" :style="{ width: usedPercentage + '%' }"></view>
|
||||
</view>
|
||||
<view class="storage-details">
|
||||
<view class="detail-item">
|
||||
<text class="size image">833.67 K</text>
|
||||
<text class="type">图片</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<text class="size audio">0 B</text>
|
||||
<text class="type">音频</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<text class="size video">0 B</text>
|
||||
<text class="type">视频</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 素材类型标签 -->
|
||||
<view class="material-tabs">
|
||||
<view
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === index }"
|
||||
@click="handleTabChange(index)"
|
||||
>
|
||||
<text>{{ tab.name }}({{ tab.count }})</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 素材列表 -->
|
||||
<view class="material-list">
|
||||
<view v-for="(item, index) in materialList" :key="index" class="material-item">
|
||||
<image class="material-icon" :src="item.icon" mode="aspectFill" />
|
||||
<view class="material-info">
|
||||
<text class="material-name">{{ item.name }}</text>
|
||||
<text class="material-id">{{ item.id }}</text>
|
||||
<text class="material-time">{{ item.time }}</text>
|
||||
</view>
|
||||
<view class="right-wrapper">
|
||||
<text class="status-tag">已通过</text>
|
||||
<text class="arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button class="upload-btn">上传列表</button>
|
||||
<button class="add-btn">添加图片素材</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 使用率
|
||||
const usedPercentage = ref(0.0)
|
||||
|
||||
// 标签页配置
|
||||
const tabs = ref([
|
||||
{ name: '图片', count: 4 },
|
||||
{ name: '音频', count: 0 },
|
||||
{ name: '视频', count: 0 }
|
||||
])
|
||||
|
||||
// 当前选中的标签
|
||||
const currentTab = ref(0)
|
||||
|
||||
// 素材列表数据
|
||||
const materialList = ref([
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png',
|
||||
name: 'house_resource.png',
|
||||
id: 'HikMall_30013234',
|
||||
time: '2024-12-26 15:11:18'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png',
|
||||
name: 'app_icon.png',
|
||||
id: 'HikMall_30013234',
|
||||
time: '2024-12-26 15:10:37'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png',
|
||||
name: 'home.png',
|
||||
id: 'HikMall_30013234',
|
||||
time: '2024-12-26 15:05:10'
|
||||
},
|
||||
{
|
||||
icon: 'https://file.hikmall.com/prod/image/885eb6ac104e4a76941e67eb738142ec.png',
|
||||
name: '锁通通 2.jpg',
|
||||
id: 'HikMall_30013234',
|
||||
time: '2024-12-26 15:05:10'
|
||||
}
|
||||
])
|
||||
|
||||
// 切换标签
|
||||
const handleTabChange = (index: number) => {
|
||||
currentTab.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.storage-card {
|
||||
padding: 20px;
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
.storage-title {
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.storage-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 4px;
|
||||
margin-bottom: 16px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 2px;
|
||||
|
||||
.progress {
|
||||
height: 100%;
|
||||
background: #4080ff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.storage-details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.size {
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
|
||||
&.image {
|
||||
color: #4080ff;
|
||||
}
|
||||
&.audio {
|
||||
color: #00c1d4;
|
||||
}
|
||||
&.video {
|
||||
color: #ffb100;
|
||||
}
|
||||
}
|
||||
|
||||
.type {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.material-tabs {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.tab-item {
|
||||
position: relative;
|
||||
padding: 8px 0;
|
||||
margin-right: 24px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
content: '';
|
||||
background: #4080ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.material-list {
|
||||
padding: 0 16px;
|
||||
|
||||
.material-item {
|
||||
position: relative; // 添加相对定位
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.material-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-right: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.material-info {
|
||||
flex: 1;
|
||||
|
||||
.material-name {
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.material-id,
|
||||
.material-time {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
position: absolute; // 添加绝对定位
|
||||
top: 0; // 距离顶部 8px
|
||||
right: 0; // 距离右侧 16px
|
||||
padding: 2px 6px; // 添加内边距
|
||||
font-size: 12px;
|
||||
color: #52c41a;
|
||||
background-color: rgba(82, 196, 26, 0.1); // 添加浅绿色背景
|
||||
border-radius: 2px; // 添加圆角
|
||||
}
|
||||
|
||||
.arrow {
|
||||
margin-top: 24px; // 向下偏移以对齐底部
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
|
||||
&.upload-btn {
|
||||
margin-right: 12px;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
&.add-btn {
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
235
src/pages/info-publish/play-content-library.vue
Normal file
@ -0,0 +1,235 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="播放内容库"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<!-- 设备类型切换 -->
|
||||
<view class="device-tabs">
|
||||
<view
|
||||
v-for="(tab, index) in deviceTabs"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ active: currentDeviceTab === index }"
|
||||
@click="handleDeviceTabChange(index)"
|
||||
>
|
||||
<text>{{ tab.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 右上角按钮 -->
|
||||
<!-- <view class="action-btn">
|
||||
<text>图片/视频轮播</text>
|
||||
</view> -->
|
||||
|
||||
<!-- 内容卡片 -->
|
||||
<view class="content-card">
|
||||
<view class="card-header">
|
||||
<view class="content-title">智慧屏节目202412260150523</view>
|
||||
<view class="content-type">图片/视频轮播</view>
|
||||
</view>
|
||||
|
||||
<view class="content-info">
|
||||
<view class="info-item">
|
||||
<text class="label">分辨率</text>
|
||||
<text class="value">1920*1080</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">更新人员</text>
|
||||
<text class="value">HikMall_30013234</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">更新时间</text>
|
||||
<text class="value">2024-12-26 15:05:31</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮组 -->
|
||||
<view class="action-group">
|
||||
<button class="action-button" @click="handlePreview">预览</button>
|
||||
<button class="action-button" @click="handleEdit">编辑</button>
|
||||
<button class="action-button" @click="handleDelete">删除</button>
|
||||
<button class="action-button" @click="handlePublish">发布</button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button class="add-btn">添加智慧屏节目</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 设备类型标签
|
||||
const deviceTabs = ref([{ name: '智慧屏' }, { name: '门禁' }])
|
||||
|
||||
// 当前选中的设备类型
|
||||
const currentDeviceTab = ref(0)
|
||||
|
||||
// 切换设备类型
|
||||
const handleDeviceTabChange = (index: number) => {
|
||||
currentDeviceTab.value = index
|
||||
}
|
||||
|
||||
// 操作按钮事件处理
|
||||
const handlePreview = () => {
|
||||
// 实现预览逻辑
|
||||
}
|
||||
|
||||
const handleEdit = () => {
|
||||
// 实现编辑逻辑
|
||||
uni.navigateTo({
|
||||
url: '/pages/info-publish/edit-pic-video'
|
||||
})
|
||||
}
|
||||
|
||||
const handleDelete = () => {
|
||||
// 实现删除逻辑
|
||||
}
|
||||
|
||||
const handlePublish = () => {
|
||||
// 实现发布逻辑
|
||||
uni.navigateTo({
|
||||
url: '/pages/info-publish/add-release-plan'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.device-tabs {
|
||||
display: flex;
|
||||
padding: 8px 16px;
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.content-card {
|
||||
padding: 16px;
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
flex: 1;
|
||||
margin-right: 12px; // 为右侧标识留出空间
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.content-type {
|
||||
padding: 2px 8px;
|
||||
margin-top: 0px;
|
||||
font-size: 12px;
|
||||
color: #4080ff;
|
||||
white-space: nowrap;
|
||||
background: rgba(64, 128, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: space-between;
|
||||
|
||||
.action-button {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
line-height: 32px;
|
||||
color: #4080ff;
|
||||
background: #fff;
|
||||
border: 1px solid #4080ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.add-btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
138
src/pages/info-publish/release-plan.vue
Normal file
@ -0,0 +1,138 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="h-[calc(100vh-0px)] flex flex-col">
|
||||
<TopNavigation title="发布计划"></TopNavigation>
|
||||
<scroll-view class="flex-1 box-border" scroll-y>
|
||||
<!-- 设备类型切换 -->
|
||||
<view class="device-tabs">
|
||||
<view
|
||||
v-for="(tab, index) in deviceTabs"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ active: currentDeviceTab === index }"
|
||||
@click="handleDeviceTabChange(index)"
|
||||
>
|
||||
<text>{{ tab.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态展示 -->
|
||||
<view class="empty-state" v-if="!hasData">
|
||||
<image class="empty-icon" src="/static/images/empty-box.png" mode="aspectFit" />
|
||||
<text class="empty-text">暂无数据</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮组 -->
|
||||
<view class="footer">
|
||||
<button class="history-btn">下发记录</button>
|
||||
<button class="add-btn">添加计划</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 设备类型标签
|
||||
const deviceTabs = ref([{ name: '智慧屏' }, { name: '门禁' }])
|
||||
|
||||
// 当前选中的设备类型
|
||||
const currentDeviceTab = ref(0)
|
||||
|
||||
// 是否有数据
|
||||
const hasData = ref(false)
|
||||
|
||||
// 切换设备类型
|
||||
const handleDeviceTabChange = (index: number) => {
|
||||
currentDeviceTab.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.device-tabs {
|
||||
display: flex;
|
||||
padding: 4px;
|
||||
margin: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 200px;
|
||||
|
||||
.empty-icon {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 12px; // 按钮之间的间距
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
button {
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.history-btn {
|
||||
flex: 1;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
background: #4080ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
|
||||
@ -226,4 +226,8 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
56
src/pages/select/components/OrganizationItem.vue
Normal 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>
|
||||
42
src/pages/select/components/SearchItem.vue
Normal 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>
|
||||
100
src/pages/select/select-access-control.vue
Normal 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>
|
||||
276
src/pages/select/select-organization.vue
Normal 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>
|
||||
BIN
src/static/images/content_icon.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/static/images/icon_airplane.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/static/images/icon_approval.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/static/images/icon_default_avatar.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/static/images/icon_delete.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/static/images/icon_file.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/static/images/icon_publish_control_grey.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/static/images/icon_publish_home_blue.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/static/images/material_icon.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
src/static/images/notice_icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src/static/images/plan_icon.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
src/static/images/publish_icon.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
16
src/types/uni-pages.d.ts
vendored
@ -6,7 +6,9 @@
|
||||
interface NavigateToOptions {
|
||||
url: "/pages/home/home" |
|
||||
"/pages/application-list/application-list" |
|
||||
"/pages/approval/approval-detail" |
|
||||
"/pages/approval/approval" |
|
||||
"/pages/approval/create-application" |
|
||||
"/pages/attendance/allowed-time" |
|
||||
"/pages/attendance/attendance-rules" |
|
||||
"/pages/attendance/attendance" |
|
||||
@ -15,19 +17,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/mine/mine" |
|
||||
"/pages/login/reset-password" |
|
||||
"/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" |
|
||||
|
||||