前些时间有分享一款vue3+uniapp仿微信App聊天实例项目。今天带来最新研发的uniapp+vue3仿ios手机界面后台OA管理系统。
采用全新的手机桌面菜单模式。可分屏显示图标集合。
实现了自定义桌面栅格磁贴引擎布局、多分屏滑动管理、自定义桌面小部件、辅助触控悬浮球等功能。支持编译到H5+小程序端+App端。
技术栈
- 编辑器:HbuilderX
- 技术框架:uniapp+vue3+pinia2+vite5.x
- UI组件库:uni-ui+uv-ui(uniapp vue3组件库)
- 弹框组件:uv3-popup(基于uniapp+vue3自定义弹框组件)
- 表格组件:uv3-table(基于uniapp+vue3增强版表格)
- 图表组件:qiun-data-charts
- 模拟数据:mockjs(用于自定义表格模拟数据)
- 缓存技术:pinia-plugin-unistorage
- 支持编译:h5+小程序端+app端
项目结构图
使用hbuilderx4.创建vue3项目模板,采用vue3 setup语法编码开发。
另外在pc端支持度也很好。
目前该项目已经同步到我的作品集,欢迎去看看。
https://gf.bilibili.com/item/detail/项目中所用到的表格组件是原创自研的uniapp+vue3自定义增强版表格组件uv3Table。
支持固定表头/列、边框、斑马纹、单选/多选,自定义表头/表体插槽、左右固定列阴影高亮显示。支持编译兼容H5+小程序端+App端。
const props = defineProps({
// 表格数据
dataSource: {
type: Array,
default() {
return []
}
},
/**
* @params {string} background 对应列背景色
* @params {string} type 对应列类型(多选selection 索引index)
* @params {string} label 显示的列标题
* @params {string} prop 对应的列字段名
* @params {string} align 列水平对齐方式(left center right)
* @params {number|string} width 对应列宽度
* @params {boolean|string} fixed 该列固定到左侧(fixed:true|left)或右侧(fixed:right)
* @params {string} columnStyle 对应列自定义样式
* @params {string} className/class 表格列的类名className
*/
columns: {
type: Array,
default() {
return []
}
},
// 表格宽度
width: { type: [Number, String] },
// 表格高度
height: { type: [Number, String] },
// 表格最大高度
maxHeight: { type: [Number, String] },
// 是否为斑马纹
stripe: { type: [Boolean, String] },
// 斑马纹背景
stripeColor: { type: String, default: #fafafa },
// 是否带有边框
border: { type: [Boolean, String] },
// 列宽度(推荐默认rpx)
columnWidth: { type: [Number, String], default: },
// 单元格间距
padding: { type: String, default: 5rpx 10rpx },
// 是否显示表头
showHeader: { type: [Boolean, String], default: true },
// 表头背景色
headerBackground: { type: String, default: #ebeef5 },
// 表头颜色
headerColor: { type: String, default: # },
// 表头字体加粗
headerBold: { type: [Boolean, String], default: true },
// 表格背景色
background: { type: String, default: #fff },
// 表格颜色
color: { type: String, default: # },
// 空数据时显示的文本内容,也可以通过 #empty 设置
emptyText: { type: String, default: 暂无数据 }
})采用全新数字解锁验证模式。
<template>
<uv3-layout>
<view class=uv3__launch :style={padding-top: fixPadTop+px}>
<view v-if=splashScreen class=uv3__launch-splash flexbox flex-col @touchstart=handleTouchStart @touchmove=handleTouchUpdate>
<view class=body flex1>
<Today />
</view>
<view class=foot flexbox flex-alignc>
<view class=btn flex-c><image src=/static/svg/flashlight.svg mode=widthFix /></view>
<view class=text flex1 flexbox flex-col>
<uni-icons type=up color=#fff />
上滑解锁
</view>
<view class=btn flex-c><image src=/static/svg/camera.svg mode=widthFix /></view>
</view>
</view>
<view v-else class=uv3__launch-keyboard flexbox flex-col :class={closed: authPassed}>
<view class=uv3__launch-pwdwrap>
<view class=text>密码解锁</view>
<view class=circle flexbox>
<view v-for=(num, index) in passwordArr :key=index class=dot :class={active: num <= pwdValue.length}></view>
</view>
</view>
<view class=uv3__launch-numwrap>
<view v-for=(item, index) in keyNumbers :key=index class=numbox @click=handleClickNum(item.num)>
<view class=num>{{item.num}}</view><view class=letter>{{item.letter}}</view>
</view>
</view>
<view class=foot flexbox>
<view class=c-fff>紧急呼叫</view>
<view v-if=pwdValue class=c-fff @click=handleDel>删除</view>
<view v-else class=c-fff @click=handleBack>返回</view>
</view>
</view>
</view>
</uv3-layout>
</template>
// 点击数字键盘
const handleClickNum = (num) => {
let pwdLen = passwordArr.value.length
if(pwdValue.value.length >= pwdLen) return
pwdValue.value += num
// 校验密码
if(pwdValue.value.length == pwdLen) {
// 验证通过
if(pwdValue.value == password.value) {
// 登录逻辑处理
}else {
pwdValue.value =
}
}
}
// 删除
const handleDel = () => {
let num = Array.from(pwdValue.value)
num.splice(-1, 1)
pwdValue.value = num.join()
}桌面布局模板
<!-- 桌面模板 -->
<script setup>
import { ref } from vue
import Desk from ./components/desk.vue
import Dock from ./components/dock.vue
import Touch from ./components/touch.vue
</script>
<template>
<uv3-layout>
<!-- 桌面菜单 -->
<Desk />
<template #footer>
<!-- 底部导航 -->
<Dock />
</template>
<!-- 悬浮球(辅助触控) -->
<Touch />
</uv3-layout>
</template>桌面图标栅格布局引擎
/**
* label 图标标题
* imgico 图标(本地或网络图片) 当type: icon则为uni-icons图标名,当type: widget则为自定义小部件标识名
* type 图标类型(icon | widget) icon为uni-icons图标、widget为自定义小部件
* path 跳转路由页面
* link 跳转外部链接
* hideLabel 是否隐藏图标标题
* background 自定义图标背景色
* size 栅格磁贴布局(种) 1x1 1x2 1x3 1x4、2x1 2x2 2x3 2x4、3x1 3x2 3x3 3x4、4x1 4x2 4x3 4x4
* onClick 点击图标回调函数 * children 二级菜单
*/<template>
<swiper
class=uv3__deskmenu
:indicator-dots=true
indicator-color=rgba,,,.5)
indicator-active-color=#fff
>
<swiper-item v-for=(mitem, mindex) in deskMenu :key=mindex>
<view class=uv3__gridwrap>
<view v-for=(item, index) in mitem.list :key=index class=uv3__gridwrap-item @click=handleClickDeskMenu(item)>
<!-- 图标 -->
<view class=ico :style={background: item.background}>
<!-- 二级菜单 -->
<template v-if=Array.isArray(item.children)>
<view class=uv3__gridwrap-thumb>
...
</view>
</template>
<template v-else>
<template v-if=item.type == widget>
<!-- 自定义部件 -->
<component :is=item.imgico />
</template>
<template v-else>
<!-- 自定义图标 -->
...
</template>
</template>
</view>
<!-- 标签 -->
<view v-if=!item.hideLabel class=label clamp2>{{item.label}}</view>
</view>
</view>
</swiper-item>
</swiper>
<!-- 桌面二级菜单弹窗 -->
<Popup v-model=deskPopupVisible>
<view class=uv3__deskpopup>
...
</view>
</Popup>
...
</template>通过开发这个项目,旨在探索uniapp+vue3实战开发手机端OA系统的可行性。覆盖的知识点还是蛮多的,限于篇幅就先分享到这里。
