网站首页 > 技术文章 正文
前些时间有分享一款vue3+uniapp仿微信App聊天实例项目。今天带来最新研发的uniapp+vue3仿ios手机界面后台OA管理系统。
采用全新的手机桌面菜单模式。可分屏显示图标集合。
实现了自定义桌面栅格磁贴引擎布局、多分屏滑动管理、自定义桌面小部件、辅助触控悬浮球等功能。支持编译到H5+小程序端+App端。
技术栈
- 编辑器:HbuilderX 4.15
- 技术框架: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.15创建vue3项目模板,采用vue3 setup语法编码开发。
另外在pc端支持度也很好。
目前该项目已经同步到我的作品集,欢迎去看看。
https://gf.bilibili.com/item/detail/1105982011项目中所用到的表格组件是原创自研的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: 200 },
    // 单元格间距
    padding: { type: String, default: '5rpx 10rpx' },
    // 是否显示表头
    showHeader: { type: [Boolean, String], default: true },
    // 表头背景色
    headerBackground: { type: String, default: '#ebeef5' },
    // 表头颜色
    headerColor: { type: String, default: '#333' },
    // 表头字体加粗
    headerBold: { type: [Boolean, String], default: true },
    // 表格背景色
    background: { type: String, default: '#fff' },
    // 表格颜色
    color: { type: String, default: '#606266' },
    // 空数据时显示的文本内容,也可以通过 #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 栅格磁贴布局(16种) 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(255,255,255,.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系统的可行性。覆盖的知识点还是蛮多的,限于篇幅就先分享到这里。
猜你喜欢
- 2024-10-02 uniapp android和微信小程序如何实现PDF在线预览
- 2024-10-02 什么是Uni App?(什么是uniapp)
- 2024-10-02 SpringBoot+Uniapp实战开发全新仿抖音短视频App「完结无秘」
- 2024-10-02 一套.NetCore+Vue+Uniapp前后端分离的低代码快速开发框架
- 2024-10-02 如何在uni-app使用vuex(uni-app vue3.0)
- 2024-10-02 三、Uni-app + vue3 页面如何跳转及传参?
- 2024-10-02 移动框架对比:uniapp和flutter选哪个好
- 2024-10-02 尤雨溪回应:Vue 与 TypeScript 为什么相性特别差?
- 2024-10-02 uni-app 多环境部署方案(uniapp 区分环境)
- 2024-10-02 uni-app组件-应用简单快速上线(uni'app)
- 最近发表
- 
- 聊一下 gRPC 的 C++ 异步编程_grpc 异步流模式
- [原创首发]安全日志管理中心实战(3)——开源NIDS之suricata部署
- 超详细手把手搭建在ubuntu系统的FFmpeg环境
- Nginx运维之路(Docker多段构建新版本并增加第三方模
- 92.1K小星星,一款开源免费的远程桌面,让你告别付费远程控制!
- Go 人脸识别教程_piwigo人脸识别
- 安卓手机安装Termux——搭建移动服务器
- ubuntu 安装开发环境(c/c++ 15)_ubuntu安装c++编译器
- Rust开发环境搭建指南:从安装到镜像配置的零坑实践
- Windows系统安装VirtualBox构造本地Linux开发环境
 
- 标签列表
- 
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (77)
- vector线程安全吗 (73)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)
 
