commit e1ad1d4ebe93e23c919b51756d72497c3238ca81 Author: yuanlei <18627959669@163.com> Date: Fri Mar 28 10:37:56 2025 +0800 初始化 diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..470abb6 --- /dev/null +++ b/.env.development @@ -0,0 +1,16 @@ +# 页面标题 +VITE_APP_TITLE = IM示例工程 + +# 开发环境配置 +VITE_APP_ENV = 'development' + +# 基础地址 +VITE_APP_BASE_URL = 'http://localhost:18081' +# VITE_APP_BASE_URL = 'https://api.ninecloud.top/msm' + +# socket地址 +# VITE_APP_SOCKET_URL = 'ws://localhost:9326' +VITE_APP_SOCKET_URL = 'wss://api.ninecloud.top/socket/' + +# 网站地址 +VITE_APP_WEB_URL = 'https://www.ninecloud.top/udemo/im/index.html' diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..36b8984 --- /dev/null +++ b/.env.production @@ -0,0 +1,14 @@ +# 页面标题 +VITE_APP_TITLE = 九云商城 + +# 生产环境配置 +VITE_APP_ENV = 'production' + +# 基础地址 +VITE_APP_BASE_URL = 'https://api.ninecloud.top/msm' + +# socket地址 +VITE_APP_SOCKET_URL = 'wss://api.ninecloud.top/socket/' + +# 网站地址 +VITE_APP_WEB_URL = 'https://www.ninecloud.top/udemo/im/index.html' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89bc518 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.hbuilderx +/unpackage \ No newline at end of file diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..9740e25 --- /dev/null +++ b/App.vue @@ -0,0 +1,104 @@ + + + diff --git a/api/chat.js b/api/chat.js new file mode 100644 index 0000000..5320148 --- /dev/null +++ b/api/chat.js @@ -0,0 +1,35 @@ +import request from "@/utils/request" + +// 查询用户所有好友 +export function getUserAllFriend() { + return request({ + url: "/im/friend/getUserAllFriend", + method: "get" + }) +} + +// 查询用户所有群 +export function getUserAllGroup() { + return request({ + url: "/im/group/getUserAllGroup", + method: "get" + }) +} + +// 查询组用户 +export function getGroupUser(id) { + return request({ + url: "/im/groupUser/getGroupUser/"+ id + "?r=" + Math.random(), + method: "get" + }) +} + + +// 通过唯一会话key获取消息 +export function getMessageByChatKey(data) { + return request({ + url: "/im/message/getMessageByChatKey", + method: "post", + data: data + }) +} diff --git a/api/login.js b/api/login.js new file mode 100644 index 0000000..64440cd --- /dev/null +++ b/api/login.js @@ -0,0 +1,62 @@ +import request from '@/utils/request' + +// 登录方法 +export function login(type, username, password, smsCode, registerFlag, code, uuid) { + const data = { + type, + username, + password, + smsCode, + registerFlag, + code, + uuid + } + return request({ + url: '/appLogin', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 注册方法 +export function register(data) { + return request({ + url: '/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + url: '/getInfo', + method: 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + url: '/logout', + method: 'post' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + url: '/captchaImage', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..912b511 --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + +
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..fafb871 --- /dev/null +++ b/main.js @@ -0,0 +1,23 @@ +import { createSSRApp } from 'vue' +import App from './App' +// 存储 +import store from '@/store' +// 路由权限控制 +import '@/permission.js' + +// 框架方法 +import frameTool from "@/utils/frameTool"; +// 插件方法 +import pluginTool from "@/plugins/pluginTool.js"; + +const app = createSSRApp(App) + +app.use(store) +app.use(frameTool) +app.use(pluginTool) + +export function createApp() { + return { + app + } +} \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..973d02f --- /dev/null +++ b/manifest.json @@ -0,0 +1,79 @@ +{ + "name" : "udemo-im", + "appid" : "__UNI__D1DA2B6", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3", + "h5" : { + "title" : "im", + "router" : { + "mode" : "hash", + "base" : "/udemo/im/" + } + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..4be6b97 --- /dev/null +++ b/pages.json @@ -0,0 +1,105 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + // 我的 + { + "path": "pages/home/user", + "style" : { + "navigationBarTitleText": "我的", + "enablePullDownRefresh": false + } + }, + { + "path": "uni_modules/vrapile-im/pages/home/chatHome", + "style": { + "enablePullDownRefresh": false, + "navigationBarTitleText": "消息" + } + }, + { + "path": "uni_modules/vrapile-im/pages/chat/chatFriend", + "style": { + "enablePullDownRefresh": true, + "navigationBarTitleText": "聊天" + } + } + ], + "subPackages": [ + //用户 + { + "root": "pages/user", + "pages": [ + { + "path": "login", + "style": { + "navigationBarTitleText": "登录", + "enablePullDownRefresh": false + } + }, + { + "path": "register", + "style": { + "navigationBarTitleText": "注册", + "enablePullDownRefresh": false + } + } + ] + }, + //设置 + { + "root": "pages/setting", + "pages": [ + { + "path" : "about", + "style" : { + "navigationBarTitleText": "关于", + "enablePullDownRefresh": false + } + }, + { + "path" : "contact", + "style" : { + "navigationBarTitleText": "联系我们", + "enablePullDownRefresh": false + } + }, + { + "path" : "setting", + "style" : { + "navigationBarTitleText": "设置", + "enablePullDownRefresh": false + } + } + ] + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "IM", + "navigationBarBackgroundColor": "#FFFFFF", + "h5": { + "titleNView": false, + "maxWidth": 1190, + "navigationBarTextStyle": "black", + "navigationBarBackgroundColor": "#FFFFFF" + }, + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "selectedColor": "#0000ff", + "list": [ + { + "pagePath": "uni_modules/vrapile-im/pages/home/chatHome", + "iconPath": "static/image/tabbar/chat.png", + "selectedIconPath": "static/image/tabbar/chat-fill.png", + "text": "消息" + }, + { + "pagePath": "pages/home/user", + "iconPath": "static/image/tabbar/user.png", + "selectedIconPath": "static/image/tabbar/user-fill.png", + "text": "我的" + } + ] + }, + "uniIdRouter": {} +} diff --git a/pages/home/user.vue b/pages/home/user.vue new file mode 100644 index 0000000..acab0d7 --- /dev/null +++ b/pages/home/user.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/pages/setting/about.vue b/pages/setting/about.vue new file mode 100644 index 0000000..48abcc1 --- /dev/null +++ b/pages/setting/about.vue @@ -0,0 +1,44 @@ + diff --git a/pages/setting/contact.vue b/pages/setting/contact.vue new file mode 100644 index 0000000..0064bc0 --- /dev/null +++ b/pages/setting/contact.vue @@ -0,0 +1,81 @@ + + + diff --git a/pages/setting/setting.vue b/pages/setting/setting.vue new file mode 100644 index 0000000..28ef981 --- /dev/null +++ b/pages/setting/setting.vue @@ -0,0 +1,75 @@ + + + diff --git a/pages/user/login.vue b/pages/user/login.vue new file mode 100644 index 0000000..eb23f2b --- /dev/null +++ b/pages/user/login.vue @@ -0,0 +1,259 @@ + + + + + diff --git a/pages/user/register.vue b/pages/user/register.vue new file mode 100644 index 0000000..4aff2ff --- /dev/null +++ b/pages/user/register.vue @@ -0,0 +1,173 @@ + + + \ No newline at end of file diff --git a/permission.js b/permission.js new file mode 100644 index 0000000..03ae2c4 --- /dev/null +++ b/permission.js @@ -0,0 +1,96 @@ +import store from '@/store' +import { getToken } from '@/utils/token' +import { setNodeId, getNodeId } from '@/utils/nodeId' +import { diyApi } from '@/utils/queryByDiy'; +import { getLongRandom } from '@/utils/nineTool'; + +// 登录页面 +const loginPage = "/pages/user/login" + +// 页面白名单 +const whiteList = [ + '/pages/user/login', + '/pages/user/register', + '/pages/user/forget', + '/pages/setting/protocol', + '/pages/common/webview/index' +] + +// 检查地址白名单 +function checkWhite(url) { + const path = url.split('?')[0] + return whiteList.indexOf(path) !== -1 +} + +// 保存访问日志 +function saveAccessLog(to, f) { + // 开发环境不保存日志 + if(import.meta.env.VITE_APP_ENV == 'development'){ + return; + } + // 生成一个nodeId,用于记录日志 + let nodeId = getNodeId(); + if(!nodeId){ + nodeId = getLongRandom(24) + setNodeId(nodeId) + } + let flag = "udemo_im_other_" + f; + // #ifdef MP-WEIXIN + flag = "udemo_im_wx_" + f; + // #endif + // #ifdef H5 + flag = "udemo_im_h5_" + f; + // #endif + // #ifdef APP-PLUS + flag = "udemo_im_app_" + f; + // #endif + let data = { + flag: flag, + fullPath: to.url.split("?")[0], + allPath: to.url, + menuName: to.tabBarText, + userId: store.state.user.userInfo.userId, + userName: store.state.user.userInfo.userName, + nodeId: nodeId + } + diyApi("/system/log/insSysAccessLog", data); +} + +// 页面跳转验证拦截器 +let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"] +list.forEach(item => { + uni.addInterceptor(item, { + invoke(to) { + if (getToken()) { + if (to.url === loginPage) { + uni.reLaunch({ url: "/" }) + } + saveAccessLog(to, "generate"); + return true + } else { + if (checkWhite(to.url)) { + saveAccessLog(to, "white"); + return true + } + saveAccessLog(to, "nologin"); + // 密码登录的,实现自动重新登录 + let loginInfo = store.state.user.loginInfo; + if(loginInfo && loginInfo.loginType == 0){ + store.dispatch('Login', { + loginType: loginInfo.loginType, + userName: loginInfo.userName, + password: loginInfo.password, + registerFlag: "N" + }).then(() => { + store.dispatch('GetInfo'); + }) + return true + } + return true + } + }, + fail(err) { + console.error(err) + } + }) +}) diff --git a/plugins/modal.js b/plugins/modal.js new file mode 100644 index 0000000..f9fbc68 --- /dev/null +++ b/plugins/modal.js @@ -0,0 +1,72 @@ +// 消息提示 +export function msg(content) { + uni.showToast({ + title: content, + icon: 'none' + }) +} +// 错误消息 +export function msgError(content) { + uni.showToast({ + title: content, + icon: 'error' + }) +} +// 成功消息 +export function msgSuccess(content) { + uni.showToast({ + title: content, + icon: 'success' + }) +} +// 隐藏消息 +export function hideMsg(content) { + uni.hideToast() +} +// 弹出提示 +export function alert(content, title) { + uni.showModal({ + title: title || '系统提示', + content: content, + showCancel: false + }) +} +// 确认窗体 +export function confirm(content, title) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: title || '系统提示', + content: content, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + if (res.confirm) { + resolve(res.confirm) + } + } + }) + }) +} +// 提示信息 +export function showToast(option) { + if (typeof option === "object") { + uni.showToast(option) + } else { + uni.showToast({ + title: option, + icon: "none", + duration: 2500 + }) + } +} +// 打开遮罩层 +export function loading(content) { + uni.showLoading({ + title: content, + icon: 'none' + }) +} +// 关闭遮罩层 +export function closeLoading() { + uni.hideLoading() +} diff --git a/plugins/pluginTool.js b/plugins/pluginTool.js new file mode 100644 index 0000000..91c0af2 --- /dev/null +++ b/plugins/pluginTool.js @@ -0,0 +1,15 @@ +import * as tab from '@/plugins/tab.js' +import * as modal from '@/plugins/modal.js' + +export default { + install(app) { + // tab工具 + Object.keys(tab).forEach((key) => { + app.config.globalProperties[key] = tab[key]; + }) + // modal工具 + Object.keys(modal).forEach((key) => { + app.config.globalProperties[key] = modal[key]; + }); + } +}; \ No newline at end of file diff --git a/plugins/tab.js b/plugins/tab.js new file mode 100644 index 0000000..f3ff2ca --- /dev/null +++ b/plugins/tab.js @@ -0,0 +1,74 @@ + // 关闭所有页面,打开到应用内的某个页面 +export function reLaunch(url) { + return uni.reLaunch({ + url: url + }) +} +export function reLaunchLogin() { + return uni.reLaunch({ + url: '/pages/user/login' + }) +} +// 跳转到tabBar页面,并关闭其他所有非tabBar页面 +export function switchTab(url) { + return uni.switchTab({ + url: url + }) +} +// 关闭当前页面,跳转到应用内的某个页面 +export function redirectTo(url) { + return uni.redirectTo({ + url: url + }) +} +// 保留当前页面,跳转到应用内的某个页面 +export function navigateTo(url) { + return uni.navigateTo({ + url: url + }) +} +// 保留当前页面,跳转到应用内的某个页面 +export function navigateToLogin() { + return uni.navigateTo({ + url: '/pages/user/login' + }) +} +// 关闭当前页面,返回上一页面或多级页面 +export function navigateBack() { + return uni.navigateBack() +} + +export function openUrl(url) { + if(!url || typeof url == 'object' || url == '#'){ + uni.showToast({ + title: '此功能正开发中,敬请期待!', + icon: 'none' + }) + return; + } + uni.navigateTo({ + url: url + }) +} + +export function pageScrollTo(scrollTop, duration=0) { + uni.pageScrollTo({ + scrollTop: scrollTop, + duration: duration + }); +} + +// 复制 +export function setClipboardData(content) { + return new Promise((resolve, reject) => { + uni.setClipboardData({ + data: content, + success: (res) => { + if (res.confirm) { + resolve(res.confirm) + } + } + }) + }) +} + diff --git a/static/image/app.png b/static/image/app.png new file mode 100644 index 0000000..3f63250 Binary files /dev/null and b/static/image/app.png differ diff --git a/static/image/favicon.ico b/static/image/favicon.ico new file mode 100644 index 0000000..3a25a29 Binary files /dev/null and b/static/image/favicon.ico differ diff --git a/static/image/ninecloud-white.png b/static/image/ninecloud-white.png new file mode 100644 index 0000000..7d80098 Binary files /dev/null and b/static/image/ninecloud-white.png differ diff --git a/static/image/tabbar/chat-fill.png b/static/image/tabbar/chat-fill.png new file mode 100644 index 0000000..5001200 Binary files /dev/null and b/static/image/tabbar/chat-fill.png differ diff --git a/static/image/tabbar/chat.png b/static/image/tabbar/chat.png new file mode 100644 index 0000000..2872220 Binary files /dev/null and b/static/image/tabbar/chat.png differ diff --git a/static/image/tabbar/home-fill.png b/static/image/tabbar/home-fill.png new file mode 100644 index 0000000..97a5446 Binary files /dev/null and b/static/image/tabbar/home-fill.png differ diff --git a/static/image/tabbar/home.png b/static/image/tabbar/home.png new file mode 100644 index 0000000..154bec6 Binary files /dev/null and b/static/image/tabbar/home.png differ diff --git a/static/image/tabbar/type-fill.png b/static/image/tabbar/type-fill.png new file mode 100644 index 0000000..1788008 Binary files /dev/null and b/static/image/tabbar/type-fill.png differ diff --git a/static/image/tabbar/type.png b/static/image/tabbar/type.png new file mode 100644 index 0000000..bff7a03 Binary files /dev/null and b/static/image/tabbar/type.png differ diff --git a/static/image/tabbar/user-fill.png b/static/image/tabbar/user-fill.png new file mode 100644 index 0000000..119edbe Binary files /dev/null and b/static/image/tabbar/user-fill.png differ diff --git a/static/image/tabbar/user.png b/static/image/tabbar/user.png new file mode 100644 index 0000000..075faff Binary files /dev/null and b/static/image/tabbar/user.png differ diff --git a/static/image/user/cc.png b/static/image/user/cc.png new file mode 100644 index 0000000..ab9d001 Binary files /dev/null and b/static/image/user/cc.png differ diff --git a/static/image/user/login-password-blue.png b/static/image/user/login-password-blue.png new file mode 100644 index 0000000..76debeb Binary files /dev/null and b/static/image/user/login-password-blue.png differ diff --git a/static/image/user/login-phone-blue.png b/static/image/user/login-phone-blue.png new file mode 100644 index 0000000..6fcc3bf Binary files /dev/null and b/static/image/user/login-phone-blue.png differ diff --git a/static/image/user/message.png b/static/image/user/message.png new file mode 100644 index 0000000..5ae809e Binary files /dev/null and b/static/image/user/message.png differ diff --git a/static/image/user/uset.png b/static/image/user/uset.png new file mode 100644 index 0000000..6d4bbea Binary files /dev/null and b/static/image/user/uset.png differ diff --git a/static/image/user/yy.png b/static/image/user/yy.png new file mode 100644 index 0000000..2ffff1b Binary files /dev/null and b/static/image/user/yy.png differ diff --git a/static/style/nine-base-001.scss b/static/style/nine-base-001.scss new file mode 100644 index 0000000..0c44685 --- /dev/null +++ b/static/style/nine-base-001.scss @@ -0,0 +1,555 @@ +.text-center{ text-align: center } +.text-right{ text-align: right } +.text-left{ text-align: left } + +.font-size6{ font-size: 6px } +.font-size8{ font-size: 8px } +.font-size10{ font-size: 10px } +.font-size12{ font-size: 12px } +.font-size14{ font-size: 14px } +.font-size16{ font-size: 16px } +.font-size18{ font-size: 18px } +.font-size20{ font-size: 20px } +.font-size22{ font-size: 22px } +.font-size24{ font-size: 24px } +.font-size26{ font-size: 26px } +.font-size28{ font-size: 28px } +.font-size30{ font-size: 30px } +.font-size32{ font-size: 32px } +.font-size34{ font-size: 34px } +.font-size36{ font-size: 36px } +.font-size38{ font-size: 38px } +.font-size40{ font-size: 40px } +.font-size60{ font-size: 60px } +.font-size80{ font-size: 80px } + +.font-bold{ font-weight: bold } + +.color-red{ color: red } +.color-green{ color: green } +.color-white{ color: white } +.color-gray{ color: gray } +.color-blue{ color: blue } +.color-yellow{ color: yellow } +.color-black{ color: black } +.color-f1f1f1{ color: #f1f1f1 } + +.bgcolor-blue{ background-color: blue } +.bgcolor-red{ background-color: red } +.bgcolor-pink{ background-color: pink } +.bgcolor-white{ background-color: white } +.bgcolor-lightblue{ background-color: lightblue } +.bgcolor-cce1e6{ background-color: #cce1e6 } +.bgcolor-787fff{ background-color: #787fff } +.bgcolor-eef0ff{ background-color: #eef0ff } +.bgcolor-ff4769{ background-color: #ff4769 } +.bgcolor-f1f1f1{ background-color: #f1f1f1 } + +.border-gray{ border: 3rpx solid gray } +.border-lightblue{ border: 3rpx solid lightblue } +.border-pink{ border: 3rpx solid pink } +.border-blue{ border: 3rpx solid blue } +.border-red{ border: 3rpx solid red } +.border-white{ border: 3rpx solid white } +.border-f1f1f1{ border: 3rpx solid #f1f1f1 } +.border-cce1e6{ border: 3rpx solid #cce1e6 } +.border-787fff{ border: 3rpx solid #787fff } +.border-eef0ff{ border: 3rpx solid #eef0ff } +.border-ff4769{ border: 3rpx solid #ff4769 } +.border-f1f1f1{ border: 3rpx solid #f1f1f1 } + +.border-radius10{ border-radius: 10rpx } + +.position-fixed{ position: fixed } +.position-absolute{ position: absolute } +.position-relative{ position: relative } + +.top0{ top: 0rpx } +.top10{ top: 10rpx } +.top20{ top: 20rpx } +.top30{ top: 30rpx } +.top40{ top: 40rpx } +.top50{ top: 50rpx } +.top60{ top: 60rpx } +.top70{ top: 70rpx } +.top80{ top: 80rpx } +.top90{ top: 90rpx } +.top100{ top: 100rpx } +.top110{ top: 110rpx } +.top120{ top: 120rpx } +.top130{ top: 130rpx } +.top140{ top: 140rpx } +.top150{ top: 150rpx } +.top200{ top: 200rpx } +.left0{ left: 0rpx } +.left10{ left: 10rpx } +.left20{ left: 20rpx } +.left30{ left: 30rpx } +.left40{ left: 40rpx } +.left50{ left: 50rpx } +.left60{ left: 60rpx } +.right0{ right: 0rpx } +.right10{ right: 10rpx } +.right20{ right: 20rpx } +.right30{ right: 30rpx } +.right40{ right: 40rpx } +.right50{ right: 50rpx } +.right60{ right: 60rpx } +.bottom0{ bottom: 0rpx } +.bottom10{ bottom: 10rpx } +.bottom20{ bottom: 20rpx } +.bottom30{ bottom: 30rpx } +.bottom40{ bottom: 40rpx } +.bottom50{ bottom: 50rpx } +.bottom60{ bottom: 60rpx } +.bottom70{ bottom: 70rpx } +.bottom80{ bottom: 80rpx } +.bottom90{ bottom: 90rpx } +.bottom100{ bottom: 100rpx } +.bottom110{ bottom: 110rpx } +.bottom120{ bottom: 120rpx } +.bottom130{ bottom: 130rpx } +.bottom140{ bottom: 140rpx } +.bottom150{ bottom: 150rpx } +.bottom200{ bottom: 200rpx } + +.lh20{ line-height: 20rpx } +.lh25{ line-height: 25rpx } +.lh30{ line-height: 30rpx } +.lh35{ line-height: 35rpx } +.lh40{ line-height: 40rpx } +.lh50{ line-height: 50rpx } + +.pa0{ padding: 0rpx } +.pa5{ padding: 5rpx } +.pa10{ padding: 10rpx } +.pa15{ padding: 15rpx } +.pa20{ padding: 20rpx } +.pa25{ padding: 25rpx } +.pa30{ padding: 30rpx } +.pa40{ padding: 40rpx } +.pa45{ padding: 45rpx } +.pa50{ padding: 50rpx } +.pa60{ padding: 60rpx } +.pa70{ padding: 70rpx } +.pa80{ padding: 80rpx } +.pa90{ padding: 90rpx } +.pa100{ padding: 100rpx } +.pa120{ padding: 120rpx } +.pa140{ padding: 140rpx } +.pa160{ padding: 160rpx } +.pa180{ padding: 180rpx } +.pa200{ padding: 200rpx } +.pa250{ padding: 250rpx } +.pa300{ padding: 300rpx } + +.ptb0{ padding-top: 0rpx; padding-bottom: 0rpx } +.ptb5{ padding-top: 5rpx; padding-bottom: 5rpx } +.ptb10{ padding-top: 10rpx; padding-bottom: 10rpx } +.ptb15{ padding-top: 15rpx; padding-bottom: 15rpx } +.ptb20{ padding-top: 20rpx; padding-bottom: 20rpx } +.ptb25{ padding-top: 25rpx; padding-bottom: 25rpx } +.ptb30{ padding-top: 30rpx; padding-bottom: 30rpx } +.ptb35{ padding-top: 35rpx; padding-bottom: 35rpx } +.ptb40{ padding-top: 40rpx; padding-bottom: 40rpx } +.ptb45{ padding-top: 45rpx; padding-bottom: 45rpx } +.ptb50{ padding-top: 50rpx; padding-bottom: 50rpx } +.ptb60{ padding-top: 60rpx; padding-bottom: 60rpx } +.ptb70{ padding-top: 70rpx; padding-bottom: 70rpx } +.ptb80{ padding-top: 80rpx; padding-bottom: 80rpx } +.ptb90{ padding-top: 90rpx; padding-bottom: 90rpx } +.ptb100{ padding-top: 100rpx; padding-bottom: 100rpx } +.ptb120{ padding-top: 120rpx; padding-bottom: 120rpx } +.ptb140{ padding-top: 140rpx; padding-bottom: 140rpx } +.ptb160{ padding-top: 160rpx; padding-bottom: 160rpx } +.ptb180{ padding-top: 180rpx; padding-bottom: 180rpx } +.ptb200{ padding-top: 200rpx; padding-bottom: 200rpx } +.ptb250{ padding-top: 250rpx; padding-bottom: 250rpx } +.ptb300{ padding-top: 300rpx; padding-bottom: 300rpx } + +.plr0{ padding-left: 0rpx; padding-right: 0rpx } +.plr5{ padding-left: 5rpx; padding-right: 5rpx } +.plr10{ padding-left: 10rpx; padding-right: 10rpx } +.plr15{ padding-left: 15rpx; padding-right: 15rpx } +.plr20{ padding-left: 20rpx; padding-right: 20rpx } +.plr25{ padding-left: 25rpx; padding-right: 25rpx } +.plr30{ padding-left: 30rpx; padding-right: 30rpx } +.plr35{ padding-left: 35rpx; padding-right: 35rpx } +.plr40{ padding-left: 40rpx; padding-right: 40rpx } +.plr45{ padding-left: 45rpx; padding-right: 45rpx } +.plr50{ padding-left: 50rpx; padding-right: 50rpx } +.plr60{ padding-left: 60rpx; padding-right: 60rpx } +.plr70{ padding-left: 70rpx; padding-right: 70rpx } +.plr80{ padding-left: 80rpx; padding-right: 80rpx } +.plr90{ padding-left: 90rpx; padding-right: 90rpx } +.plr100{ padding-left: 100rpx; padding-right: 100rpx } +.plr120{ padding-left: 120rpx; padding-right: 120rpx } +.plr140{ padding-left: 140rpx; padding-right: 140rpx } +.plr160{ padding-left: 160rpx; padding-right: 160rpx } +.plr180{ padding-left: 180rpx; padding-right: 180rpx } +.plr200{ padding-left: 200rpx; padding-right: 200rpx } +.plr250{ padding-left: 250rpx; padding-right: 250rpx } +.plr300{ padding-left: 300rpx; padding-right: 300rpx } + +.pt0{ padding-top: 0rpx } +.pt5{ padding-top: 5rpx } +.pt10{ padding-top: 10rpx } +.pt15{ padding-top: 15rpx } +.pt20{ padding-top: 20rpx } +.pt25{ padding-top: 25rpx } +.pt30{ padding-top: 30rpx } +.pt35{ padding-top: 35rpx } +.pt40{ padding-top: 40rpx } +.pt45{ padding-top: 45rpx } +.pt50{ padding-top: 50rpx } +.pt60{ padding-top: 60rpx } +.pt70{ padding-top: 70rpx } +.pt80{ padding-top: 80rpx } +.pt90{ padding-top: 90rpx } +.pt100{ padding-top: 100rpx } +.pt120{ padding-top: 120rpx } +.pt140{ padding-top: 140rpx } +.pt160{ padding-top: 160rpx } +.pt180{ padding-top: 180rpx } +.pt200{ padding-top: 200rpx } +.pt250{ padding-top: 250rpx } +.pt300{ padding-top: 300rpx } + +.pb0{ padding-bottom: 0rpx } +.pb5{ padding-bottom: 5rpx } +.pb10{ padding-bottom: 10rpx } +.pb15{ padding-bottom: 15rpx } +.pb20{ padding-bottom: 20rpx } +.pb25{ padding-bottom: 25rpx } +.pb30{ padding-bottom: 30rpx } +.pb35{ padding-bottom: 35rpx } +.pb40{ padding-bottom: 40rpx } +.pb45{ padding-bottom: 45rpx } +.pb50{ padding-bottom: 50rpx } +.pb60{ padding-bottom: 60rpx } +.pb70{ padding-bottom: 70rpx } +.pb80{ padding-bottom: 80rpx } +.pb90{ padding-bottom: 90rpx } +.pb100{ padding-bottom: 100rpx } +.pb120{ padding-bottom: 120rpx } +.pb140{ padding-bottom: 140rpx } +.pb160{ padding-bottom: 160rpx } +.pb180{ padding-bottom: 180rpx } +.pb200{ padding-bottom: 200rpx } +.pb250{ padding-bottom: 250rpx } +.pb300{ padding-bottom: 300rpx } + +.pl0{ padding-left: 0rpx } +.pl5{ padding-left: 5rpx } +.pl10{ padding-left: 10rpx } +.pl15{ padding-left: 15rpx } +.pl20{ padding-left: 20rpx } +.pl25{ padding-left: 25rpx } +.pl30{ padding-left: 30rpx } +.pl35{ padding-left: 35rpx } +.pl40{ padding-left: 40rpx } +.pl45{ padding-left: 45rpx } +.pl50{ padding-left: 50rpx } +.pl60{ padding-left: 60rpx } +.pl70{ padding-left: 70rpx } +.pl80{ padding-left: 80rpx } +.pl90{ padding-left: 90rpx } +.pl100{ padding-left: 100rpx } +.pl120{ padding-left: 120rpx } +.pl140{ padding-left: 140rpx } +.pl160{ padding-left: 160rpx } +.pl180{ padding-left: 180rpx } +.pl200{ padding-left: 200rpx } +.pl250{ padding-left: 250rpx } +.pl300{ padding-left: 300rpx } + +.pr0{ padding-right: 0rpx } +.pr5{ padding-right: 5rpx } +.pr10{ padding-right: 10rpx } +.pr15{ padding-right: 15rpx } +.pr20{ padding-right: 20rpx } +.pr25{ padding-right: 25rpx } +.pr30{ padding-right: 30rpx } +.pr35{ padding-right: 35rpx } +.pr40{ padding-right: 40rpx } +.pr45{ padding-right: 45rpx } +.pr50{ padding-right: 50rpx } +.pr60{ padding-right: 60rpx } +.pr70{ padding-right: 70rpx } +.pr80{ padding-right: 80rpx } +.pr90{ padding-right: 90rpx } +.pr100{ padding-right: 100rpx } +.pr120{ padding-right: 120rpx } +.pr140{ padding-right: 140rpx } +.pr160{ padding-right: 160rpx } +.pr180{ padding-right: 180rpx } +.pr200{ padding-right: 200rpx } +.pr250{ padding-right: 250rpx } +.pr300{ padding-right: 300rpx } + +.ma0{ margin: 0rpx } +.ma5{ margin: 5rpx } +.ma10{ margin: 10rpx } +.ma15{ margin: 15rpx } +.ma20{ margin: 20rpx } +.ma25{ margin: 25rpx } +.ma30{ margin: 30rpx } +.ma35{ margin: 35rpx } +.ma40{ margin: 40rpx } +.ma45{ margin: 45rpx } +.ma50{ margin: 50rpx } +.ma60{ margin: 60rpx } +.ma70{ margin: 70rpx } +.ma80{ margin: 80rpx } +.ma90{ margin: 90rpx } +.ma100{ margin: 100rpx } +.ma120{ margin: 120rpx } +.ma140{ margin: 140rpx } +.ma160{ margin: 160rpx } +.ma180{ margin: 180rpx } +.ma200{ margin: 200rpx } +.ma250{ margin: 250rpx } +.ma300{ margin: 300rpx } + +.mlr0{ margin-left: 0rpx; margin-right: 0rpx } +.mlr5{ margin-left: 5rpx; margin-right: 5rpx } +.mlr10{ margin-left: 10rpx; margin-right: 10rpx } +.mlr15{ margin-left: 15rpx; margin-right: 15rpx } +.mlr20{ margin-left: 20rpx; margin-right: 20rpx } +.mlr25{ margin-left: 25rpx; margin-right: 25rpx } +.mlr30{ margin-left: 30rpx; margin-right: 30rpx } +.mlr35{ margin-left: 35rpx; margin-right: 35rpx } +.mlr40{ margin-left: 40rpx; margin-right: 40rpx } +.mlr45{ margin-left: 45rpx; margin-right: 45rpx } +.mlr50{ margin-left: 50rpx; margin-right: 50rpx } +.mlr50{ margin-left: 50rpx; margin-right: 50rpx } +.mlr60{ margin-left: 60rpx; margin-right: 60rpx } +.mlr70{ margin-left: 70rpx; margin-right: 70rpx } +.mlr80{ margin-left: 80rpx; margin-right: 80rpx } +.mlr90{ margin-left: 90rpx; margin-right: 90rpx } +.mlr100{ margin-left: 100rpx; margin-right: 100rpx } +.mlr120{ margin-left: 120rpx; margin-right: 120rpx } +.mlr140{ margin-left: 140rpx; margin-right: 140rpx } +.mlr160{ margin-left: 160rpx; margin-right: 160rpx } +.mlr180{ margin-left: 180rpx; margin-right: 180rpx } +.mlr200{ margin-left: 200rpx; margin-right: 200rpx } +.mlr250{ margin-left: 250rpx; margin-right: 250rpx } +.mlr300{ margin-left: 300rpx; margin-right: 300rpx } + +.mtb0{ margin-top: 0rpx; margin-bottom: 0rpx } +.mtb5{ margin-top: 5rpx; margin-bottom: 5rpx } +.mtb10{ margin-top: 10rpx; margin-bottom: 10rpx } +.mtb15{ margin-top: 15rpx; margin-bottom: 15rpx } +.mtb20{ margin-top: 20rpx; margin-bottom: 20rpx } +.mtb25{ margin-top: 25rpx; margin-bottom: 25rpx } +.mtb30{ margin-top: 30rpx; margin-bottom: 30rpx } +.mtb35{ margin-top: 35rpx; margin-bottom: 35rpx } +.mtb40{ margin-top: 40rpx; margin-bottom: 40rpx } +.mtb45{ margin-top: 45rpx; margin-bottom: 45rpx } +.mtb50{ margin-top: 50rpx; margin-bottom: 50rpx } +.mtb60{ margin-top: 60rpx; margin-bottom: 60rpx } +.mtb70{ margin-top: 70rpx; margin-bottom: 70rpx } +.mtb80{ margin-top: 80rpx; margin-bottom: 80rpx } +.mtb90{ margin-top: 90rpx; margin-bottom: 90rpx } +.mtb100{ margin-top: 100rpx; margin-bottom: 100rpx } +.mtb120{ margin-top: 120rpx; margin-bottom: 120rpx } +.mtb140{ margin-top: 140rpx; margin-bottom: 140rpx } +.mtb160{ margin-top: 160rpx; margin-bottom: 160rpx } +.mtb180{ margin-top: 180rpx; margin-bottom: 180rpx } +.mtb200{ margin-top: 200rpx; margin-bottom: 200rpx } +.mtb250{ margin-top: 250rpx; margin-bottom: 250rpx } +.mtb300{ margin-top: 300rpx; margin-bottom: 300rpx } + +.mt0{ margin-top: 0rpx } +.mt5{ margin-top: 5rpx } +.mt10{ margin-top: 10rpx } +.mt12{ margin-top: 10rpx } +.mt15{ margin-top: 15rpx } +.mt20{ margin-top: 20rpx } +.mt25{ margin-top: 25rpx } +.mt30{ margin-top: 30rpx } +.mt35{ margin-top: 35rpx } +.mt40{ margin-top: 40rpx } +.mt45{ margin-top: 45rpx } +.mt50{ margin-top: 50rpx } +.mt60{ margin-top: 60rpx } +.mt65{ margin-top: 65rpx } +.mt70{ margin-top: 70rpx } +.mt80{ margin-top: 80rpx } +.mt90{ margin-top: 90rpx } +.mt100{ margin-top: 100rpx } +.mt120{ margin-top: 120rpx } +.mt140{ margin-top: 140rpx } +.mt160{ margin-top: 160rpx } +.mt180{ margin-top: 180rpx } +.mt200{ margin-top: 200rpx } +.mt250{ margin-top: 250rpx } +.mt300{ margin-top: 300rpx } + +.mt-1{ margin-top: -1rpx } +.mt-5{ margin-top: -5rpx } +.mt-10{ margin-top: -10rpx } +.mt-15{ margin-top: -15rpx } +.mt-20{ margin-top: -20rpx } +.mt-25{ margin-top: -25rpx } +.mt-30{ margin-top: -30rpx } +.mt-35{ margin-top: -35rpx } +.mt-40{ margin-top: -40rpx } +.mt-45{ margin-top: -45rpx } +.mt-50{ margin-top: -50rpx } +.mt-60{ margin-top: -60rpx } +.mt-70{ margin-top: -70rpx } +.mt-80{ margin-top: -80rpx } +.mt-90{ margin-top: -90rpx } +.mt-100{ margin-top: -100rpx } +.mt-120{ margin-top: -120rpx } +.mt-140{ margin-top: -140rpx } +.mt-160{ margin-top: -160rpx } +.mt-180{ margin-top: -180rpx } +.mt-200{ margin-top: -200rpx } +.mt-250{ margin-top: -250rpx } +.mt-300{ margin-top: -300rpx } + +.mb0{ margin-bottom: 0rpx } +.mb5{ margin-bottom: 5rpx } +.mb10{ margin-bottom: 10rpx } +.mb15{ margin-bottom: 15rpx } +.mb20{ margin-bottom: 20rpx } +.mb25{ margin-bottom: 25rpx } +.mb30{ margin-bottom: 30rpx } +.mb35{ margin-bottom: 35rpx } +.mb40{ margin-bottom: 40rpx } +.mb45{ margin-bottom: 45rpx } +.mb50{ margin-bottom: 50rpx } +.mb60{ margin-bottom: 60rpx } +.mb70{ margin-bottom: 70rpx } +.mb80{ margin-bottom: 80rpx } +.mb90{ margin-bottom: 90rpx } +.mb100{ margin-bottom: 100rpx } +.mb120{ margin-bottom: 120rpx } +.mb140{ margin-bottom: 140rpx } +.mb160{ margin-bottom: 160rpx } +.mb180{ margin-bottom: 180rpx } +.mb200{ margin-bottom: 200rpx } +.mb250{ margin-bottom: 250rpx } +.mb300{ margin-bottom: 300rpx } + +.mb-1{ margin-bottom: -1rpx } +.mb-5{ margin-bottom: -5rpx } +.mb-10{ margin-bottom: -10rpx } +.mb-15{ margin-bottom: -15rpx } +.mb-20{ margin-bottom: -20rpx } +.mb-25{ margin-bottom: -25rpx } +.mb-30{ margin-bottom: -30rpx } +.mb-35{ margin-bottom: -35rpx } +.mb-40{ margin-bottom: -40rpx } +.mb-45{ margin-bottom: -45rpx } +.mb-50{ margin-bottom: -50rpx } +.mb-60{ margin-bottom: -60rpx } +.mb-70{ margin-bottom: -70rpx } +.mb-80{ margin-bottom: -80rpx } +.mb-90{ margin-bottom: -90rpx } +.mb-100{ margin-bottom: -100rpx } +.mb-120{ margin-bottom: -120rpx } +.mb-140{ margin-bottom: -140rpx } +.mb-160{ margin-bottom: -160rpx } +.mb-180{ margin-bottom: -180rpx } +.mb-200{ margin-bottom: -200rpx } +.mb-250{ margin-bottom: -250rpx } +.mb-300{ margin-bottom: -300rpx } + +.ml0{ margin-left: 0rpx } +.ml5{ margin-left: 5rpx } +.ml10{ margin-left: 10rpx } +.ml15{ margin-left: 15rpx } +.ml20{ margin-left: 20rpx } +.ml25{ margin-left: 25rpx } +.ml30{ margin-left: 30rpx } +.ml35{ margin-left: 35rpx } +.ml40{ margin-left: 40rpx } +.ml45{ margin-left: 45rpx } +.ml50{ margin-left: 50rpx } +.ml60{ margin-left: 60rpx } +.ml70{ margin-left: 70rpx } +.ml80{ margin-left: 80rpx } +.ml90{ margin-left: 90rpx } +.ml100{ margin-left: 100rpx } +.ml120{ margin-left: 120rpx } +.ml140{ margin-left: 140rpx } +.ml160{ margin-left: 160rpx } +.ml180{ margin-left: 180rpx } +.ml200{ margin-left: 200rpx } +.ml250{ margin-left: 250rpx } +.ml300{ margin-left: 300rpx } + +.ml-1{ margin-left: -1rpx } +.ml-5{ margin-left: -5rpx } +.ml-10{ margin-left: -10rpx } +.ml-15{ margin-left: -15rpx } +.ml-20{ margin-left: -20rpx } +.ml-25{ margin-left: -25rpx } +.ml-30{ margin-left: -30rpx } +.ml-35{ margin-left: -35rpx } +.ml-40{ margin-left: -40rpx } +.ml-45{ margin-left: -45rpx } +.ml-50{ margin-left: -50rpx } +.ml-60{ margin-left: -60rpx } +.ml-70{ margin-left: -70rpx } +.ml-80{ margin-left: -80rpx } +.ml-90{ margin-left: -90rpx } +.ml-100{ margin-left: -100rpx } +.ml-120{ margin-left: -120rpx } +.ml-140{ margin-left: -140rpx } +.ml-160{ margin-left: -160rpx } +.ml-180{ margin-left: -180rpx } +.ml-200{ margin-left: -200rpx } +.ml-250{ margin-left: -250rpx } +.ml-300{ margin-left: -300rpx } + +.mr0{ margin-right: 0rpx } +.mr5{ margin-right: 5rpx } +.mr10{ margin-right: 10rpx } +.mr15{ margin-right: 15rpx } +.mr20{ margin-right: 20rpx } +.mr25{ margin-right: 25rpx } +.mr30{ margin-right: 30rpx } +.mr35{ margin-right: 35rpx } +.mr40{ margin-right: 40rpx } +.mr45{ margin-right: 45rpx } +.mr50{ margin-right: 50rpx } +.mr60{ margin-right: 60rpx } +.mr70{ margin-right: 70rpx } +.mr80{ margin-right: 80rpx } +.mr90{ margin-right: 90rpx } +.mr100{ margin-right: 100rpx } +.mr120{ margin-right: 120rpx } +.mr140{ margin-right: 140rpx } +.mr160{ margin-right: 160rpx } +.mr180{ margin-right: 180rpx } +.mr200{ margin-right: 200rpx } +.mr250{ margin-right: 250rpx } +.mr300{ margin-right: 300rpx } + +.mr-1{ margin-right: -1rpx } +.mr-5{ margin-right: -5rpx } +.mr-10{ margin-right: -10rpx } +.mr-15{ margin-right: -15rpx } +.mr-20{ margin-right: -20rpx } +.mr-25{ margin-right: -25rpx } +.mr-30{ margin-right: -30rpx } +.mr-35{ margin-right: -35rpx } +.mr-40{ margin-right: -40rpx } +.mr-45{ margin-right: -45rpx } +.mr-50{ margin-right: -50rpx } +.mr-60{ margin-right: -60rpx } +.mr-70{ margin-right: -70rpx } +.mr-80{ margin-right: -80rpx } +.mr-90{ margin-right: -90rpx } +.mr-100{ margin-right: -100rpx } +.mr-120{ margin-right: -120rpx } +.mr-140{ margin-right: -140rpx } +.mr-160{ margin-right: -160rpx } +.mr-180{ margin-right: -180rpx } +.mr-200{ margin-right: -200rpx } +.mr-250{ margin-right: -250rpx } +.mr-300{ margin-right: -300rpx } \ No newline at end of file diff --git a/static/style/nine-base-002.scss b/static/style/nine-base-002.scss new file mode 100644 index 0000000..4ce38eb --- /dev/null +++ b/static/style/nine-base-002.scss @@ -0,0 +1,136 @@ +.height100{ + height: 100%; +} +.width25{ + width: 25%; +} +.width30{ + width: 30%; +} +.width45{ + width: 45%; +} +.width46{ + width: 46%; +} +.width47{ + width: 47%; +} +.width48{ + width: 48%; +} +.width49{ + width: 49%; +} +.width50{ + width: 50%; +} +.width80{ + width: 80%; +} +.width90{ + width: 90%; +} +.width100{ + width: 100%; +} + +.test{ border: 3rpx solid red} +.test-red{ border: 3rpx solid red} +.test-blue{ border: 3rpx solid blue} +.test-green{ border: 3rpx solid green} +.test-white{ border: 3rpx solid white} +.test-box{ box-sizing: border-box; border: 3rpx solid red} +.test-box-red{ box-sizing: border-box; border: 3rpx solid red} +.test-box-blue{ box-sizing: border-box; border: 3rpx solid blue} +.test-box-green{ box-sizing: border-box; border: 3rpx solid green} +.test-box-white{ box-sizing: border-box; border: 3rpx solid white} + +.float{ float: left; } +.float-left{ float: left; } +.float-right{ float: right; } + +// 允许文本复制 +.nine-user-select { + cursor: auto; + -webkit-user-select: text; + user-select: text; +} + +.display-flex-row{ + display: flex; + flex-direction: row; + align-items: center; +} +.display-flex-column{ + display: flex; + flex-direction: column; +} +.display-flex-column-center{ + display: flex; + flex-direction: column; + justify-content: center; +} +.display-flex-row-between{ + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} +.display-flex-row-center{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} +.display-flex-row-around{ + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; +} +.display-flex-column-between{ + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; +} +.display-flex-column-around{ + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; +} +.justify-content-center{ + justify-content: center +} +.flex1{ + flex: 1 +} + + +.text-nowrap{ + white-space:nowrap; +} +.text-ellipsis{ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +// 放大缩小比例 +.transform-scale05{ + transform: scale(0.5); +} +.transform-scale06{ + transform: scale(0.6); +} +.transform-scale07{ + transform: scale(0.7); +} +.transform-scale08{ + transform: scale(0.8); +} +.transform-scale09{ + transform: scale(0.9); +} \ No newline at end of file diff --git a/static/style/nine-btn-001.scss b/static/style/nine-btn-001.scss new file mode 100644 index 0000000..daf61f9 --- /dev/null +++ b/static/style/nine-btn-001.scss @@ -0,0 +1,27 @@ +// 边框蓝,字体蓝,用于获取短信验证码按钮 +.nine-btn-verify-001{ + border-radius: 10rpx; + color: #1e1eff; + border: 3rpx solid #1e1eff; +} +// 保存按钮 +.nine-btn-save-001{ + padding: 20rpx; + border-radius: 10rpx; + color: #fff; + background-color: #0000ff; + text-align: center; +} +// 退出登录 +.nine-btn-login-out-001{ + padding: 20rpx; + border-radius: 10rpx; + color: red; + background: #fff; + text-align: center; +} +// 灰色横线 +.nine-line-001{ + height: 1rpx; + border-top: 1rpx solid #d9d9d9; +} \ No newline at end of file diff --git a/static/style/nine-chat-friend-001.scss b/static/style/nine-chat-friend-001.scss new file mode 100644 index 0000000..4ceda16 --- /dev/null +++ b/static/style/nine-chat-friend-001.scss @@ -0,0 +1 @@ +/* 可重写内部/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss样式 */ diff --git a/static/style/nine-chat-home-001.scss b/static/style/nine-chat-home-001.scss new file mode 100644 index 0000000..bab177d --- /dev/null +++ b/static/style/nine-chat-home-001.scss @@ -0,0 +1 @@ +/* 可重写内部/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss样式 */ diff --git a/static/style/nine-image-001.scss b/static/style/nine-image-001.scss new file mode 100644 index 0000000..fdd71d9 --- /dev/null +++ b/static/style/nine-image-001.scss @@ -0,0 +1,36 @@ +.image35{ + width: 35rpx; + height: 35rpx; +} +.image40{ + width: 40rpx; + height: 40rpx; +} +.image50{ + width: 40rpx; + height: 40rpx; +} +.image70{ + width: 70rpx; + height: 70rpx; +} +.image80{ + width: 70rpx; + height: 70rpx; +} +.image90{ + width: 90rpx; + height: 90rpx; +} +.image150{ + width: 150rpx; + height: 150rpx; +} +.image200{ + width: 200rpx; + height: 200rpx; +} +.image400{ + width: 400rpx; + height: 400rpx; +} \ No newline at end of file diff --git a/static/style/nine-list-001.scss b/static/style/nine-list-001.scss new file mode 100644 index 0000000..4780b21 --- /dev/null +++ b/static/style/nine-list-001.scss @@ -0,0 +1,9 @@ +.nine-list-001{ + padding: 10rpx; +} +.nine-list-001-item{ + background-color: #fff; + margin: 10rpx 0; + padding: 10rpx 30rpx; + border-radius: 10rpx; +} \ No newline at end of file diff --git a/static/style/nine-nav-001.scss b/static/style/nine-nav-001.scss new file mode 100644 index 0000000..7ddfb98 --- /dev/null +++ b/static/style/nine-nav-001.scss @@ -0,0 +1,39 @@ +.nine-nav-001{ + display: flex; + flex-direction: column; + padding: 10rpx; + flex: 1; + height: 100%; + overflow-y: auto; +} +.nine-nav-001-item{ + background: #fff; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin-top: 5rpx; + padding: 20rpx 15rpx; + border-radius: 1rpx; + border-style: solid; + border-width: 0px; +} +.nine-nav-001-item-left{ + display: flex; + flex-direction: row; + align-items: center; + padding: 2rpx 10rpx; +} +.nine-nav-001-item-left-text{ + font-size: 16px; + padding-left: 20rpx; +} +.nine-nav-001-item-right{ + display: flex; + flex-direction: row; + align-items: center; +} +.nine-nav-001-item-right-image{ + width: 16rpx; + height: 35rpx; +} \ No newline at end of file diff --git a/store/getters.js b/store/getters.js new file mode 100644 index 0000000..95053e9 --- /dev/null +++ b/store/getters.js @@ -0,0 +1,8 @@ +const getters = { + token: state => state.user.token, + userInfo: state => state.user.userInfo, + loginInfo: state => state.user.loginInfo, + avatar: state => state.user.avatar, + name: state => state.user.name +} +export default getters diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..2e6be07 --- /dev/null +++ b/store/index.js @@ -0,0 +1,15 @@ +// import Vue from 'vue' +import Vuex from 'vuex' +import user from '@/store/modules/user' +import getters from './getters' + +// Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + user + }, + getters +}) + +export default store diff --git a/store/modules/user.js b/store/modules/user.js new file mode 100644 index 0000000..12eeb2d --- /dev/null +++ b/store/modules/user.js @@ -0,0 +1,94 @@ +import store from '@/store' +import storage from '@/utils/storage' +import constant from '@/utils/constant' +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/utils/token' + +const user = { + state: { + token: getToken(), + userInfo: storage.get(constant.userInfo), + loginInfo: storage.get(constant.loginInfo), + name: storage.get(constant.name), + avatar: storage.get(constant.avatar) + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_USER_INFO: (state, userInfo) => { + state.userInfo = userInfo + storage.set(constant.userInfo, userInfo) + }, + SET_LOGIN_INFO: (state, loginInfo) => { + state.loginInfo = loginInfo + storage.set(constant.loginInfo, loginInfo) + }, + SET_NAME: (state, name) => { + state.name = name + storage.set(constant.name, name) + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + storage.set(constant.avatar, avatar) + } + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const loginType = userInfo.loginType + const userName = userInfo.userName + const password = userInfo.password + const smsCode = userInfo.smsCode + const registerFlag = userInfo.registerFlag + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(loginType, userName, password, smsCode, registerFlag, code, uuid).then(res => { + setToken(res.data.token) + commit('SET_TOKEN', res.data.token) + commit('SET_LOGIN_INFO', userInfo) // 保存登录信息,后续可以自动登录 + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.data.user + const avatar = (user == null || user.avatar == "" || user.avatar == null) ? "/static/image/user/yy.png" : user.avatar + const userName = (user == null || user.userName == "" || user.userName == null) ? "" : user.userName + commit('SET_USER_INFO', user) + commit('SET_NAME', userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_USER_INFO', {}) + removeToken() + storage.clean() + resolve() + }).catch(error => { + reject(error) + }) + }) + } + } +} + +export default user diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..b9249e9 --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/uni_modules/uni-icons/changelog.md b/uni_modules/uni-icons/changelog.md new file mode 100644 index 0000000..0261131 --- /dev/null +++ b/uni_modules/uni-icons/changelog.md @@ -0,0 +1,42 @@ +## 2.0.10(2024-06-07) +- 优化 uni-app x 中,size 属性的类型 +## 2.0.9(2024-01-12) +fix: 修复图标大小默认值错误的问题 +## 2.0.8(2023-12-14) +- 修复 项目未使用 ts 情况下,打包报错的bug +## 2.0.7(2023-12-14) +- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug +## 2.0.6(2023-12-11) +- 优化 兼容老版本icon类型,如 top ,bottom 等 +## 2.0.5(2023-12-11) +- 优化 兼容老版本icon类型,如 top ,bottom 等 +## 2.0.4(2023-12-06) +- 优化 uni-app x 下示例项目图标排序 +## 2.0.3(2023-12-06) +- 修复 nvue下引入组件报错的bug +## 2.0.2(2023-12-05) +-优化 size 属性支持单位 +## 2.0.1(2023-12-05) +- 新增 uni-app x 支持定义图标 +## 1.3.5(2022-01-24) +- 优化 size 属性可以传入不带单位的字符串数值 +## 1.3.4(2022-01-24) +- 优化 size 支持其他单位 +## 1.3.3(2022-01-17) +- 修复 nvue 有些图标不显示的bug,兼容老版本图标 +## 1.3.2(2021-12-01) +- 优化 示例可复制图标名称 +## 1.3.1(2021-11-23) +- 优化 兼容旧组件 type 值 +## 1.3.0(2021-11-19) +- 新增 更多图标 +- 优化 自定义图标使用方式 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons) +## 1.1.7(2021-11-08) +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.5(2021-05-12) +- 新增 组件示例地址 +## 1.1.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue new file mode 100644 index 0000000..8740559 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue @@ -0,0 +1,91 @@ + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 0000000..7da5356 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.css b/uni_modules/uni-icons/components/uni-icons/uniicons.css new file mode 100644 index 0000000..0a6b6fe --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons.css @@ -0,0 +1,664 @@ + +.uniui-cart-filled:before { + content: "\e6d0"; +} + +.uniui-gift-filled:before { + content: "\e6c4"; +} + +.uniui-color:before { + content: "\e6cf"; +} + +.uniui-wallet:before { + content: "\e6b1"; +} + +.uniui-settings-filled:before { + content: "\e6ce"; +} + +.uniui-auth-filled:before { + content: "\e6cc"; +} + +.uniui-shop-filled:before { + content: "\e6cd"; +} + +.uniui-staff-filled:before { + content: "\e6cb"; +} + +.uniui-vip-filled:before { + content: "\e6c6"; +} + +.uniui-plus-filled:before { + content: "\e6c7"; +} + +.uniui-folder-add-filled:before { + content: "\e6c8"; +} + +.uniui-color-filled:before { + content: "\e6c9"; +} + +.uniui-tune-filled:before { + content: "\e6ca"; +} + +.uniui-calendar-filled:before { + content: "\e6c0"; +} + +.uniui-notification-filled:before { + content: "\e6c1"; +} + +.uniui-wallet-filled:before { + content: "\e6c2"; +} + +.uniui-medal-filled:before { + content: "\e6c3"; +} + +.uniui-fire-filled:before { + content: "\e6c5"; +} + +.uniui-refreshempty:before { + content: "\e6bf"; +} + +.uniui-location-filled:before { + content: "\e6af"; +} + +.uniui-person-filled:before { + content: "\e69d"; +} + +.uniui-personadd-filled:before { + content: "\e698"; +} + +.uniui-arrowthinleft:before { + content: "\e6d2"; +} + +.uniui-arrowthinup:before { + content: "\e6d3"; +} + +.uniui-arrowthindown:before { + content: "\e6d4"; +} + +.uniui-back:before { + content: "\e6b9"; +} + +.uniui-forward:before { + content: "\e6ba"; +} + +.uniui-arrow-right:before { + content: "\e6bb"; +} + +.uniui-arrow-left:before { + content: "\e6bc"; +} + +.uniui-arrow-up:before { + content: "\e6bd"; +} + +.uniui-arrow-down:before { + content: "\e6be"; +} + +.uniui-arrowthinright:before { + content: "\e6d1"; +} + +.uniui-down:before { + content: "\e6b8"; +} + +.uniui-bottom:before { + content: "\e6b8"; +} + +.uniui-arrowright:before { + content: "\e6d5"; +} + +.uniui-right:before { + content: "\e6b5"; +} + +.uniui-up:before { + content: "\e6b6"; +} + +.uniui-top:before { + content: "\e6b6"; +} + +.uniui-left:before { + content: "\e6b7"; +} + +.uniui-arrowup:before { + content: "\e6d6"; +} + +.uniui-eye:before { + content: "\e651"; +} + +.uniui-eye-filled:before { + content: "\e66a"; +} + +.uniui-eye-slash:before { + content: "\e6b3"; +} + +.uniui-eye-slash-filled:before { + content: "\e6b4"; +} + +.uniui-info-filled:before { + content: "\e649"; +} + +.uniui-reload:before { + content: "\e6b2"; +} + +.uniui-micoff-filled:before { + content: "\e6b0"; +} + +.uniui-map-pin-ellipse:before { + content: "\e6ac"; +} + +.uniui-map-pin:before { + content: "\e6ad"; +} + +.uniui-location:before { + content: "\e6ae"; +} + +.uniui-starhalf:before { + content: "\e683"; +} + +.uniui-star:before { + content: "\e688"; +} + +.uniui-star-filled:before { + content: "\e68f"; +} + +.uniui-calendar:before { + content: "\e6a0"; +} + +.uniui-fire:before { + content: "\e6a1"; +} + +.uniui-medal:before { + content: "\e6a2"; +} + +.uniui-font:before { + content: "\e6a3"; +} + +.uniui-gift:before { + content: "\e6a4"; +} + +.uniui-link:before { + content: "\e6a5"; +} + +.uniui-notification:before { + content: "\e6a6"; +} + +.uniui-staff:before { + content: "\e6a7"; +} + +.uniui-vip:before { + content: "\e6a8"; +} + +.uniui-folder-add:before { + content: "\e6a9"; +} + +.uniui-tune:before { + content: "\e6aa"; +} + +.uniui-auth:before { + content: "\e6ab"; +} + +.uniui-person:before { + content: "\e699"; +} + +.uniui-email-filled:before { + content: "\e69a"; +} + +.uniui-phone-filled:before { + content: "\e69b"; +} + +.uniui-phone:before { + content: "\e69c"; +} + +.uniui-email:before { + content: "\e69e"; +} + +.uniui-personadd:before { + content: "\e69f"; +} + +.uniui-chatboxes-filled:before { + content: "\e692"; +} + +.uniui-contact:before { + content: "\e693"; +} + +.uniui-chatbubble-filled:before { + content: "\e694"; +} + +.uniui-contact-filled:before { + content: "\e695"; +} + +.uniui-chatboxes:before { + content: "\e696"; +} + +.uniui-chatbubble:before { + content: "\e697"; +} + +.uniui-upload-filled:before { + content: "\e68e"; +} + +.uniui-upload:before { + content: "\e690"; +} + +.uniui-weixin:before { + content: "\e691"; +} + +.uniui-compose:before { + content: "\e67f"; +} + +.uniui-qq:before { + content: "\e680"; +} + +.uniui-download-filled:before { + content: "\e681"; +} + +.uniui-pyq:before { + content: "\e682"; +} + +.uniui-sound:before { + content: "\e684"; +} + +.uniui-trash-filled:before { + content: "\e685"; +} + +.uniui-sound-filled:before { + content: "\e686"; +} + +.uniui-trash:before { + content: "\e687"; +} + +.uniui-videocam-filled:before { + content: "\e689"; +} + +.uniui-spinner-cycle:before { + content: "\e68a"; +} + +.uniui-weibo:before { + content: "\e68b"; +} + +.uniui-videocam:before { + content: "\e68c"; +} + +.uniui-download:before { + content: "\e68d"; +} + +.uniui-help:before { + content: "\e679"; +} + +.uniui-navigate-filled:before { + content: "\e67a"; +} + +.uniui-plusempty:before { + content: "\e67b"; +} + +.uniui-smallcircle:before { + content: "\e67c"; +} + +.uniui-minus-filled:before { + content: "\e67d"; +} + +.uniui-micoff:before { + content: "\e67e"; +} + +.uniui-closeempty:before { + content: "\e66c"; +} + +.uniui-clear:before { + content: "\e66d"; +} + +.uniui-navigate:before { + content: "\e66e"; +} + +.uniui-minus:before { + content: "\e66f"; +} + +.uniui-image:before { + content: "\e670"; +} + +.uniui-mic:before { + content: "\e671"; +} + +.uniui-paperplane:before { + content: "\e672"; +} + +.uniui-close:before { + content: "\e673"; +} + +.uniui-help-filled:before { + content: "\e674"; +} + +.uniui-paperplane-filled:before { + content: "\e675"; +} + +.uniui-plus:before { + content: "\e676"; +} + +.uniui-mic-filled:before { + content: "\e677"; +} + +.uniui-image-filled:before { + content: "\e678"; +} + +.uniui-locked-filled:before { + content: "\e668"; +} + +.uniui-info:before { + content: "\e669"; +} + +.uniui-locked:before { + content: "\e66b"; +} + +.uniui-camera-filled:before { + content: "\e658"; +} + +.uniui-chat-filled:before { + content: "\e659"; +} + +.uniui-camera:before { + content: "\e65a"; +} + +.uniui-circle:before { + content: "\e65b"; +} + +.uniui-checkmarkempty:before { + content: "\e65c"; +} + +.uniui-chat:before { + content: "\e65d"; +} + +.uniui-circle-filled:before { + content: "\e65e"; +} + +.uniui-flag:before { + content: "\e65f"; +} + +.uniui-flag-filled:before { + content: "\e660"; +} + +.uniui-gear-filled:before { + content: "\e661"; +} + +.uniui-home:before { + content: "\e662"; +} + +.uniui-home-filled:before { + content: "\e663"; +} + +.uniui-gear:before { + content: "\e664"; +} + +.uniui-smallcircle-filled:before { + content: "\e665"; +} + +.uniui-map-filled:before { + content: "\e666"; +} + +.uniui-map:before { + content: "\e667"; +} + +.uniui-refresh-filled:before { + content: "\e656"; +} + +.uniui-refresh:before { + content: "\e657"; +} + +.uniui-cloud-upload:before { + content: "\e645"; +} + +.uniui-cloud-download-filled:before { + content: "\e646"; +} + +.uniui-cloud-download:before { + content: "\e647"; +} + +.uniui-cloud-upload-filled:before { + content: "\e648"; +} + +.uniui-redo:before { + content: "\e64a"; +} + +.uniui-images-filled:before { + content: "\e64b"; +} + +.uniui-undo-filled:before { + content: "\e64c"; +} + +.uniui-more:before { + content: "\e64d"; +} + +.uniui-more-filled:before { + content: "\e64e"; +} + +.uniui-undo:before { + content: "\e64f"; +} + +.uniui-images:before { + content: "\e650"; +} + +.uniui-paperclip:before { + content: "\e652"; +} + +.uniui-settings:before { + content: "\e653"; +} + +.uniui-search:before { + content: "\e654"; +} + +.uniui-redo-filled:before { + content: "\e655"; +} + +.uniui-list:before { + content: "\e644"; +} + +.uniui-mail-open-filled:before { + content: "\e63a"; +} + +.uniui-hand-down-filled:before { + content: "\e63c"; +} + +.uniui-hand-down:before { + content: "\e63d"; +} + +.uniui-hand-up-filled:before { + content: "\e63e"; +} + +.uniui-hand-up:before { + content: "\e63f"; +} + +.uniui-heart-filled:before { + content: "\e641"; +} + +.uniui-mail-open:before { + content: "\e643"; +} + +.uniui-heart:before { + content: "\e639"; +} + +.uniui-loop:before { + content: "\e633"; +} + +.uniui-pulldown:before { + content: "\e632"; +} + +.uniui-scan:before { + content: "\e62a"; +} + +.uniui-bars:before { + content: "\e627"; +} + +.uniui-checkbox:before { + content: "\e62b"; +} + +.uniui-checkbox-filled:before { + content: "\e62c"; +} + +.uniui-shop:before { + content: "\e62f"; +} + +.uniui-headphones:before { + content: "\e630"; +} + +.uniui-cart:before { + content: "\e631"; +} diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf new file mode 100644 index 0000000..14696d0 Binary files /dev/null and b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf differ diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts new file mode 100644 index 0000000..98e93aa --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts @@ -0,0 +1,664 @@ + +export type IconsData = { + id : string + name : string + font_family : string + css_prefix_text : string + description : string + glyphs : Array +} + +export type IconsDataItem = { + font_class : string + unicode : string +} + + +export const fontData = [ + { + "font_class": "arrow-down", + "unicode": "\ue6be" + }, + { + "font_class": "arrow-left", + "unicode": "\ue6bc" + }, + { + "font_class": "arrow-right", + "unicode": "\ue6bb" + }, + { + "font_class": "arrow-up", + "unicode": "\ue6bd" + }, + { + "font_class": "auth", + "unicode": "\ue6ab" + }, + { + "font_class": "auth-filled", + "unicode": "\ue6cc" + }, + { + "font_class": "back", + "unicode": "\ue6b9" + }, + { + "font_class": "bars", + "unicode": "\ue627" + }, + { + "font_class": "calendar", + "unicode": "\ue6a0" + }, + { + "font_class": "calendar-filled", + "unicode": "\ue6c0" + }, + { + "font_class": "camera", + "unicode": "\ue65a" + }, + { + "font_class": "camera-filled", + "unicode": "\ue658" + }, + { + "font_class": "cart", + "unicode": "\ue631" + }, + { + "font_class": "cart-filled", + "unicode": "\ue6d0" + }, + { + "font_class": "chat", + "unicode": "\ue65d" + }, + { + "font_class": "chat-filled", + "unicode": "\ue659" + }, + { + "font_class": "chatboxes", + "unicode": "\ue696" + }, + { + "font_class": "chatboxes-filled", + "unicode": "\ue692" + }, + { + "font_class": "chatbubble", + "unicode": "\ue697" + }, + { + "font_class": "chatbubble-filled", + "unicode": "\ue694" + }, + { + "font_class": "checkbox", + "unicode": "\ue62b" + }, + { + "font_class": "checkbox-filled", + "unicode": "\ue62c" + }, + { + "font_class": "checkmarkempty", + "unicode": "\ue65c" + }, + { + "font_class": "circle", + "unicode": "\ue65b" + }, + { + "font_class": "circle-filled", + "unicode": "\ue65e" + }, + { + "font_class": "clear", + "unicode": "\ue66d" + }, + { + "font_class": "close", + "unicode": "\ue673" + }, + { + "font_class": "closeempty", + "unicode": "\ue66c" + }, + { + "font_class": "cloud-download", + "unicode": "\ue647" + }, + { + "font_class": "cloud-download-filled", + "unicode": "\ue646" + }, + { + "font_class": "cloud-upload", + "unicode": "\ue645" + }, + { + "font_class": "cloud-upload-filled", + "unicode": "\ue648" + }, + { + "font_class": "color", + "unicode": "\ue6cf" + }, + { + "font_class": "color-filled", + "unicode": "\ue6c9" + }, + { + "font_class": "compose", + "unicode": "\ue67f" + }, + { + "font_class": "contact", + "unicode": "\ue693" + }, + { + "font_class": "contact-filled", + "unicode": "\ue695" + }, + { + "font_class": "down", + "unicode": "\ue6b8" + }, + { + "font_class": "bottom", + "unicode": "\ue6b8" + }, + { + "font_class": "download", + "unicode": "\ue68d" + }, + { + "font_class": "download-filled", + "unicode": "\ue681" + }, + { + "font_class": "email", + "unicode": "\ue69e" + }, + { + "font_class": "email-filled", + "unicode": "\ue69a" + }, + { + "font_class": "eye", + "unicode": "\ue651" + }, + { + "font_class": "eye-filled", + "unicode": "\ue66a" + }, + { + "font_class": "eye-slash", + "unicode": "\ue6b3" + }, + { + "font_class": "eye-slash-filled", + "unicode": "\ue6b4" + }, + { + "font_class": "fire", + "unicode": "\ue6a1" + }, + { + "font_class": "fire-filled", + "unicode": "\ue6c5" + }, + { + "font_class": "flag", + "unicode": "\ue65f" + }, + { + "font_class": "flag-filled", + "unicode": "\ue660" + }, + { + "font_class": "folder-add", + "unicode": "\ue6a9" + }, + { + "font_class": "folder-add-filled", + "unicode": "\ue6c8" + }, + { + "font_class": "font", + "unicode": "\ue6a3" + }, + { + "font_class": "forward", + "unicode": "\ue6ba" + }, + { + "font_class": "gear", + "unicode": "\ue664" + }, + { + "font_class": "gear-filled", + "unicode": "\ue661" + }, + { + "font_class": "gift", + "unicode": "\ue6a4" + }, + { + "font_class": "gift-filled", + "unicode": "\ue6c4" + }, + { + "font_class": "hand-down", + "unicode": "\ue63d" + }, + { + "font_class": "hand-down-filled", + "unicode": "\ue63c" + }, + { + "font_class": "hand-up", + "unicode": "\ue63f" + }, + { + "font_class": "hand-up-filled", + "unicode": "\ue63e" + }, + { + "font_class": "headphones", + "unicode": "\ue630" + }, + { + "font_class": "heart", + "unicode": "\ue639" + }, + { + "font_class": "heart-filled", + "unicode": "\ue641" + }, + { + "font_class": "help", + "unicode": "\ue679" + }, + { + "font_class": "help-filled", + "unicode": "\ue674" + }, + { + "font_class": "home", + "unicode": "\ue662" + }, + { + "font_class": "home-filled", + "unicode": "\ue663" + }, + { + "font_class": "image", + "unicode": "\ue670" + }, + { + "font_class": "image-filled", + "unicode": "\ue678" + }, + { + "font_class": "images", + "unicode": "\ue650" + }, + { + "font_class": "images-filled", + "unicode": "\ue64b" + }, + { + "font_class": "info", + "unicode": "\ue669" + }, + { + "font_class": "info-filled", + "unicode": "\ue649" + }, + { + "font_class": "left", + "unicode": "\ue6b7" + }, + { + "font_class": "link", + "unicode": "\ue6a5" + }, + { + "font_class": "list", + "unicode": "\ue644" + }, + { + "font_class": "location", + "unicode": "\ue6ae" + }, + { + "font_class": "location-filled", + "unicode": "\ue6af" + }, + { + "font_class": "locked", + "unicode": "\ue66b" + }, + { + "font_class": "locked-filled", + "unicode": "\ue668" + }, + { + "font_class": "loop", + "unicode": "\ue633" + }, + { + "font_class": "mail-open", + "unicode": "\ue643" + }, + { + "font_class": "mail-open-filled", + "unicode": "\ue63a" + }, + { + "font_class": "map", + "unicode": "\ue667" + }, + { + "font_class": "map-filled", + "unicode": "\ue666" + }, + { + "font_class": "map-pin", + "unicode": "\ue6ad" + }, + { + "font_class": "map-pin-ellipse", + "unicode": "\ue6ac" + }, + { + "font_class": "medal", + "unicode": "\ue6a2" + }, + { + "font_class": "medal-filled", + "unicode": "\ue6c3" + }, + { + "font_class": "mic", + "unicode": "\ue671" + }, + { + "font_class": "mic-filled", + "unicode": "\ue677" + }, + { + "font_class": "micoff", + "unicode": "\ue67e" + }, + { + "font_class": "micoff-filled", + "unicode": "\ue6b0" + }, + { + "font_class": "minus", + "unicode": "\ue66f" + }, + { + "font_class": "minus-filled", + "unicode": "\ue67d" + }, + { + "font_class": "more", + "unicode": "\ue64d" + }, + { + "font_class": "more-filled", + "unicode": "\ue64e" + }, + { + "font_class": "navigate", + "unicode": "\ue66e" + }, + { + "font_class": "navigate-filled", + "unicode": "\ue67a" + }, + { + "font_class": "notification", + "unicode": "\ue6a6" + }, + { + "font_class": "notification-filled", + "unicode": "\ue6c1" + }, + { + "font_class": "paperclip", + "unicode": "\ue652" + }, + { + "font_class": "paperplane", + "unicode": "\ue672" + }, + { + "font_class": "paperplane-filled", + "unicode": "\ue675" + }, + { + "font_class": "person", + "unicode": "\ue699" + }, + { + "font_class": "person-filled", + "unicode": "\ue69d" + }, + { + "font_class": "personadd", + "unicode": "\ue69f" + }, + { + "font_class": "personadd-filled", + "unicode": "\ue698" + }, + { + "font_class": "personadd-filled-copy", + "unicode": "\ue6d1" + }, + { + "font_class": "phone", + "unicode": "\ue69c" + }, + { + "font_class": "phone-filled", + "unicode": "\ue69b" + }, + { + "font_class": "plus", + "unicode": "\ue676" + }, + { + "font_class": "plus-filled", + "unicode": "\ue6c7" + }, + { + "font_class": "plusempty", + "unicode": "\ue67b" + }, + { + "font_class": "pulldown", + "unicode": "\ue632" + }, + { + "font_class": "pyq", + "unicode": "\ue682" + }, + { + "font_class": "qq", + "unicode": "\ue680" + }, + { + "font_class": "redo", + "unicode": "\ue64a" + }, + { + "font_class": "redo-filled", + "unicode": "\ue655" + }, + { + "font_class": "refresh", + "unicode": "\ue657" + }, + { + "font_class": "refresh-filled", + "unicode": "\ue656" + }, + { + "font_class": "refreshempty", + "unicode": "\ue6bf" + }, + { + "font_class": "reload", + "unicode": "\ue6b2" + }, + { + "font_class": "right", + "unicode": "\ue6b5" + }, + { + "font_class": "scan", + "unicode": "\ue62a" + }, + { + "font_class": "search", + "unicode": "\ue654" + }, + { + "font_class": "settings", + "unicode": "\ue653" + }, + { + "font_class": "settings-filled", + "unicode": "\ue6ce" + }, + { + "font_class": "shop", + "unicode": "\ue62f" + }, + { + "font_class": "shop-filled", + "unicode": "\ue6cd" + }, + { + "font_class": "smallcircle", + "unicode": "\ue67c" + }, + { + "font_class": "smallcircle-filled", + "unicode": "\ue665" + }, + { + "font_class": "sound", + "unicode": "\ue684" + }, + { + "font_class": "sound-filled", + "unicode": "\ue686" + }, + { + "font_class": "spinner-cycle", + "unicode": "\ue68a" + }, + { + "font_class": "staff", + "unicode": "\ue6a7" + }, + { + "font_class": "staff-filled", + "unicode": "\ue6cb" + }, + { + "font_class": "star", + "unicode": "\ue688" + }, + { + "font_class": "star-filled", + "unicode": "\ue68f" + }, + { + "font_class": "starhalf", + "unicode": "\ue683" + }, + { + "font_class": "trash", + "unicode": "\ue687" + }, + { + "font_class": "trash-filled", + "unicode": "\ue685" + }, + { + "font_class": "tune", + "unicode": "\ue6aa" + }, + { + "font_class": "tune-filled", + "unicode": "\ue6ca" + }, + { + "font_class": "undo", + "unicode": "\ue64f" + }, + { + "font_class": "undo-filled", + "unicode": "\ue64c" + }, + { + "font_class": "up", + "unicode": "\ue6b6" + }, + { + "font_class": "top", + "unicode": "\ue6b6" + }, + { + "font_class": "upload", + "unicode": "\ue690" + }, + { + "font_class": "upload-filled", + "unicode": "\ue68e" + }, + { + "font_class": "videocam", + "unicode": "\ue68c" + }, + { + "font_class": "videocam-filled", + "unicode": "\ue689" + }, + { + "font_class": "vip", + "unicode": "\ue6a8" + }, + { + "font_class": "vip-filled", + "unicode": "\ue6c6" + }, + { + "font_class": "wallet", + "unicode": "\ue6b1" + }, + { + "font_class": "wallet-filled", + "unicode": "\ue6c2" + }, + { + "font_class": "weibo", + "unicode": "\ue68b" + }, + { + "font_class": "weixin", + "unicode": "\ue691" + } +] as IconsDataItem[] + +// export const fontData = JSON.parse(fontDataJson) diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js new file mode 100644 index 0000000..1cd11e1 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js @@ -0,0 +1,649 @@ + +export const fontData = [ + { + "font_class": "arrow-down", + "unicode": "\ue6be" + }, + { + "font_class": "arrow-left", + "unicode": "\ue6bc" + }, + { + "font_class": "arrow-right", + "unicode": "\ue6bb" + }, + { + "font_class": "arrow-up", + "unicode": "\ue6bd" + }, + { + "font_class": "auth", + "unicode": "\ue6ab" + }, + { + "font_class": "auth-filled", + "unicode": "\ue6cc" + }, + { + "font_class": "back", + "unicode": "\ue6b9" + }, + { + "font_class": "bars", + "unicode": "\ue627" + }, + { + "font_class": "calendar", + "unicode": "\ue6a0" + }, + { + "font_class": "calendar-filled", + "unicode": "\ue6c0" + }, + { + "font_class": "camera", + "unicode": "\ue65a" + }, + { + "font_class": "camera-filled", + "unicode": "\ue658" + }, + { + "font_class": "cart", + "unicode": "\ue631" + }, + { + "font_class": "cart-filled", + "unicode": "\ue6d0" + }, + { + "font_class": "chat", + "unicode": "\ue65d" + }, + { + "font_class": "chat-filled", + "unicode": "\ue659" + }, + { + "font_class": "chatboxes", + "unicode": "\ue696" + }, + { + "font_class": "chatboxes-filled", + "unicode": "\ue692" + }, + { + "font_class": "chatbubble", + "unicode": "\ue697" + }, + { + "font_class": "chatbubble-filled", + "unicode": "\ue694" + }, + { + "font_class": "checkbox", + "unicode": "\ue62b" + }, + { + "font_class": "checkbox-filled", + "unicode": "\ue62c" + }, + { + "font_class": "checkmarkempty", + "unicode": "\ue65c" + }, + { + "font_class": "circle", + "unicode": "\ue65b" + }, + { + "font_class": "circle-filled", + "unicode": "\ue65e" + }, + { + "font_class": "clear", + "unicode": "\ue66d" + }, + { + "font_class": "close", + "unicode": "\ue673" + }, + { + "font_class": "closeempty", + "unicode": "\ue66c" + }, + { + "font_class": "cloud-download", + "unicode": "\ue647" + }, + { + "font_class": "cloud-download-filled", + "unicode": "\ue646" + }, + { + "font_class": "cloud-upload", + "unicode": "\ue645" + }, + { + "font_class": "cloud-upload-filled", + "unicode": "\ue648" + }, + { + "font_class": "color", + "unicode": "\ue6cf" + }, + { + "font_class": "color-filled", + "unicode": "\ue6c9" + }, + { + "font_class": "compose", + "unicode": "\ue67f" + }, + { + "font_class": "contact", + "unicode": "\ue693" + }, + { + "font_class": "contact-filled", + "unicode": "\ue695" + }, + { + "font_class": "down", + "unicode": "\ue6b8" + }, + { + "font_class": "bottom", + "unicode": "\ue6b8" + }, + { + "font_class": "download", + "unicode": "\ue68d" + }, + { + "font_class": "download-filled", + "unicode": "\ue681" + }, + { + "font_class": "email", + "unicode": "\ue69e" + }, + { + "font_class": "email-filled", + "unicode": "\ue69a" + }, + { + "font_class": "eye", + "unicode": "\ue651" + }, + { + "font_class": "eye-filled", + "unicode": "\ue66a" + }, + { + "font_class": "eye-slash", + "unicode": "\ue6b3" + }, + { + "font_class": "eye-slash-filled", + "unicode": "\ue6b4" + }, + { + "font_class": "fire", + "unicode": "\ue6a1" + }, + { + "font_class": "fire-filled", + "unicode": "\ue6c5" + }, + { + "font_class": "flag", + "unicode": "\ue65f" + }, + { + "font_class": "flag-filled", + "unicode": "\ue660" + }, + { + "font_class": "folder-add", + "unicode": "\ue6a9" + }, + { + "font_class": "folder-add-filled", + "unicode": "\ue6c8" + }, + { + "font_class": "font", + "unicode": "\ue6a3" + }, + { + "font_class": "forward", + "unicode": "\ue6ba" + }, + { + "font_class": "gear", + "unicode": "\ue664" + }, + { + "font_class": "gear-filled", + "unicode": "\ue661" + }, + { + "font_class": "gift", + "unicode": "\ue6a4" + }, + { + "font_class": "gift-filled", + "unicode": "\ue6c4" + }, + { + "font_class": "hand-down", + "unicode": "\ue63d" + }, + { + "font_class": "hand-down-filled", + "unicode": "\ue63c" + }, + { + "font_class": "hand-up", + "unicode": "\ue63f" + }, + { + "font_class": "hand-up-filled", + "unicode": "\ue63e" + }, + { + "font_class": "headphones", + "unicode": "\ue630" + }, + { + "font_class": "heart", + "unicode": "\ue639" + }, + { + "font_class": "heart-filled", + "unicode": "\ue641" + }, + { + "font_class": "help", + "unicode": "\ue679" + }, + { + "font_class": "help-filled", + "unicode": "\ue674" + }, + { + "font_class": "home", + "unicode": "\ue662" + }, + { + "font_class": "home-filled", + "unicode": "\ue663" + }, + { + "font_class": "image", + "unicode": "\ue670" + }, + { + "font_class": "image-filled", + "unicode": "\ue678" + }, + { + "font_class": "images", + "unicode": "\ue650" + }, + { + "font_class": "images-filled", + "unicode": "\ue64b" + }, + { + "font_class": "info", + "unicode": "\ue669" + }, + { + "font_class": "info-filled", + "unicode": "\ue649" + }, + { + "font_class": "left", + "unicode": "\ue6b7" + }, + { + "font_class": "link", + "unicode": "\ue6a5" + }, + { + "font_class": "list", + "unicode": "\ue644" + }, + { + "font_class": "location", + "unicode": "\ue6ae" + }, + { + "font_class": "location-filled", + "unicode": "\ue6af" + }, + { + "font_class": "locked", + "unicode": "\ue66b" + }, + { + "font_class": "locked-filled", + "unicode": "\ue668" + }, + { + "font_class": "loop", + "unicode": "\ue633" + }, + { + "font_class": "mail-open", + "unicode": "\ue643" + }, + { + "font_class": "mail-open-filled", + "unicode": "\ue63a" + }, + { + "font_class": "map", + "unicode": "\ue667" + }, + { + "font_class": "map-filled", + "unicode": "\ue666" + }, + { + "font_class": "map-pin", + "unicode": "\ue6ad" + }, + { + "font_class": "map-pin-ellipse", + "unicode": "\ue6ac" + }, + { + "font_class": "medal", + "unicode": "\ue6a2" + }, + { + "font_class": "medal-filled", + "unicode": "\ue6c3" + }, + { + "font_class": "mic", + "unicode": "\ue671" + }, + { + "font_class": "mic-filled", + "unicode": "\ue677" + }, + { + "font_class": "micoff", + "unicode": "\ue67e" + }, + { + "font_class": "micoff-filled", + "unicode": "\ue6b0" + }, + { + "font_class": "minus", + "unicode": "\ue66f" + }, + { + "font_class": "minus-filled", + "unicode": "\ue67d" + }, + { + "font_class": "more", + "unicode": "\ue64d" + }, + { + "font_class": "more-filled", + "unicode": "\ue64e" + }, + { + "font_class": "navigate", + "unicode": "\ue66e" + }, + { + "font_class": "navigate-filled", + "unicode": "\ue67a" + }, + { + "font_class": "notification", + "unicode": "\ue6a6" + }, + { + "font_class": "notification-filled", + "unicode": "\ue6c1" + }, + { + "font_class": "paperclip", + "unicode": "\ue652" + }, + { + "font_class": "paperplane", + "unicode": "\ue672" + }, + { + "font_class": "paperplane-filled", + "unicode": "\ue675" + }, + { + "font_class": "person", + "unicode": "\ue699" + }, + { + "font_class": "person-filled", + "unicode": "\ue69d" + }, + { + "font_class": "personadd", + "unicode": "\ue69f" + }, + { + "font_class": "personadd-filled", + "unicode": "\ue698" + }, + { + "font_class": "personadd-filled-copy", + "unicode": "\ue6d1" + }, + { + "font_class": "phone", + "unicode": "\ue69c" + }, + { + "font_class": "phone-filled", + "unicode": "\ue69b" + }, + { + "font_class": "plus", + "unicode": "\ue676" + }, + { + "font_class": "plus-filled", + "unicode": "\ue6c7" + }, + { + "font_class": "plusempty", + "unicode": "\ue67b" + }, + { + "font_class": "pulldown", + "unicode": "\ue632" + }, + { + "font_class": "pyq", + "unicode": "\ue682" + }, + { + "font_class": "qq", + "unicode": "\ue680" + }, + { + "font_class": "redo", + "unicode": "\ue64a" + }, + { + "font_class": "redo-filled", + "unicode": "\ue655" + }, + { + "font_class": "refresh", + "unicode": "\ue657" + }, + { + "font_class": "refresh-filled", + "unicode": "\ue656" + }, + { + "font_class": "refreshempty", + "unicode": "\ue6bf" + }, + { + "font_class": "reload", + "unicode": "\ue6b2" + }, + { + "font_class": "right", + "unicode": "\ue6b5" + }, + { + "font_class": "scan", + "unicode": "\ue62a" + }, + { + "font_class": "search", + "unicode": "\ue654" + }, + { + "font_class": "settings", + "unicode": "\ue653" + }, + { + "font_class": "settings-filled", + "unicode": "\ue6ce" + }, + { + "font_class": "shop", + "unicode": "\ue62f" + }, + { + "font_class": "shop-filled", + "unicode": "\ue6cd" + }, + { + "font_class": "smallcircle", + "unicode": "\ue67c" + }, + { + "font_class": "smallcircle-filled", + "unicode": "\ue665" + }, + { + "font_class": "sound", + "unicode": "\ue684" + }, + { + "font_class": "sound-filled", + "unicode": "\ue686" + }, + { + "font_class": "spinner-cycle", + "unicode": "\ue68a" + }, + { + "font_class": "staff", + "unicode": "\ue6a7" + }, + { + "font_class": "staff-filled", + "unicode": "\ue6cb" + }, + { + "font_class": "star", + "unicode": "\ue688" + }, + { + "font_class": "star-filled", + "unicode": "\ue68f" + }, + { + "font_class": "starhalf", + "unicode": "\ue683" + }, + { + "font_class": "trash", + "unicode": "\ue687" + }, + { + "font_class": "trash-filled", + "unicode": "\ue685" + }, + { + "font_class": "tune", + "unicode": "\ue6aa" + }, + { + "font_class": "tune-filled", + "unicode": "\ue6ca" + }, + { + "font_class": "undo", + "unicode": "\ue64f" + }, + { + "font_class": "undo-filled", + "unicode": "\ue64c" + }, + { + "font_class": "up", + "unicode": "\ue6b6" + }, + { + "font_class": "top", + "unicode": "\ue6b6" + }, + { + "font_class": "upload", + "unicode": "\ue690" + }, + { + "font_class": "upload-filled", + "unicode": "\ue68e" + }, + { + "font_class": "videocam", + "unicode": "\ue68c" + }, + { + "font_class": "videocam-filled", + "unicode": "\ue689" + }, + { + "font_class": "vip", + "unicode": "\ue6a8" + }, + { + "font_class": "vip-filled", + "unicode": "\ue6c6" + }, + { + "font_class": "wallet", + "unicode": "\ue6b1" + }, + { + "font_class": "wallet-filled", + "unicode": "\ue6c2" + }, + { + "font_class": "weibo", + "unicode": "\ue68b" + }, + { + "font_class": "weixin", + "unicode": "\ue691" + } +] + +// export const fontData = JSON.parse(fontDataJson) diff --git a/uni_modules/uni-icons/package.json b/uni_modules/uni-icons/package.json new file mode 100644 index 0000000..6b681b4 --- /dev/null +++ b/uni_modules/uni-icons/package.json @@ -0,0 +1,89 @@ +{ + "id": "uni-icons", + "displayName": "uni-icons 图标", + "version": "2.0.10", + "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。", + "keywords": [ + "uni-ui", + "uniui", + "icon", + "图标" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.2.14" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y", + "app-uvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y", + "钉钉": "y", + "快手": "y", + "飞书": "y", + "京东": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-icons/readme.md b/uni_modules/uni-icons/readme.md new file mode 100644 index 0000000..86234ba --- /dev/null +++ b/uni_modules/uni-icons/readme.md @@ -0,0 +1,8 @@ +## Icons 图标 +> **组件名:uni-icons** +> 代码块: `uIcons` + +用于展示 icons 图标 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-scss/changelog.md b/uni_modules/uni-scss/changelog.md new file mode 100644 index 0000000..b863bb0 --- /dev/null +++ b/uni_modules/uni-scss/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2022-01-21) +- 优化 组件示例 +## 1.0.2(2021-11-22) +- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 +## 1.0.1(2021-11-22) +- 修复 vue3中scss语法兼容问题 +## 1.0.0(2021-11-18) +- init diff --git a/uni_modules/uni-scss/index.scss b/uni_modules/uni-scss/index.scss new file mode 100644 index 0000000..1744a5f --- /dev/null +++ b/uni_modules/uni-scss/index.scss @@ -0,0 +1 @@ +@import './styles/index.scss'; diff --git a/uni_modules/uni-scss/package.json b/uni_modules/uni-scss/package.json new file mode 100644 index 0000000..7cc0ccb --- /dev/null +++ b/uni_modules/uni-scss/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-scss", + "displayName": "uni-scss 辅助样式", + "version": "1.0.3", + "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", + "keywords": [ + "uni-scss", + "uni-ui", + "辅助样式" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-scss/readme.md b/uni_modules/uni-scss/readme.md new file mode 100644 index 0000000..b7d1c25 --- /dev/null +++ b/uni_modules/uni-scss/readme.md @@ -0,0 +1,4 @@ +`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/index.scss b/uni_modules/uni-scss/styles/index.scss new file mode 100644 index 0000000..ffac4fe --- /dev/null +++ b/uni_modules/uni-scss/styles/index.scss @@ -0,0 +1,7 @@ +@import './setting/_variables.scss'; +@import './setting/_border.scss'; +@import './setting/_color.scss'; +@import './setting/_space.scss'; +@import './setting/_radius.scss'; +@import './setting/_text.scss'; +@import './setting/_styles.scss'; diff --git a/uni_modules/uni-scss/styles/setting/_border.scss b/uni_modules/uni-scss/styles/setting/_border.scss new file mode 100644 index 0000000..12a11c3 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_border.scss @@ -0,0 +1,3 @@ +.uni-border { + border: 1px $uni-border-1 solid; +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_color.scss b/uni_modules/uni-scss/styles/setting/_color.scss new file mode 100644 index 0000000..1ededd9 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_color.scss @@ -0,0 +1,66 @@ + +// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 +// @mixin get-styles($k,$c) { +// @if $k == size or $k == weight{ +// font-#{$k}:#{$c} +// }@else{ +// #{$k}:#{$c} +// } +// } +$uni-ui-color:( + // 主色 + primary: $uni-primary, + primary-disable: $uni-primary-disable, + primary-light: $uni-primary-light, + // 辅助色 + success: $uni-success, + success-disable: $uni-success-disable, + success-light: $uni-success-light, + warning: $uni-warning, + warning-disable: $uni-warning-disable, + warning-light: $uni-warning-light, + error: $uni-error, + error-disable: $uni-error-disable, + error-light: $uni-error-light, + info: $uni-info, + info-disable: $uni-info-disable, + info-light: $uni-info-light, + // 中性色 + main-color: $uni-main-color, + base-color: $uni-base-color, + secondary-color: $uni-secondary-color, + extra-color: $uni-extra-color, + // 背景色 + bg-color: $uni-bg-color, + // 边框颜色 + border-1: $uni-border-1, + border-2: $uni-border-2, + border-3: $uni-border-3, + border-4: $uni-border-4, + // 黑色 + black:$uni-black, + // 白色 + white:$uni-white, + // 透明 + transparent:$uni-transparent +) !default; +@each $key, $child in $uni-ui-color { + .uni-#{"" + $key} { + color: $child; + } + .uni-#{"" + $key}-bg { + background-color: $child; + } +} +.uni-shadow-sm { + box-shadow: $uni-shadow-sm; +} +.uni-shadow-base { + box-shadow: $uni-shadow-base; +} +.uni-shadow-lg { + box-shadow: $uni-shadow-lg; +} +.uni-mask { + background-color:$uni-mask; +} diff --git a/uni_modules/uni-scss/styles/setting/_radius.scss b/uni_modules/uni-scss/styles/setting/_radius.scss new file mode 100644 index 0000000..9a0428b --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_radius.scss @@ -0,0 +1,55 @@ +@mixin radius($r,$d:null ,$important: false){ + $radius-value:map-get($uni-radius, $r) if($important, !important, null); + // Key exists within the $uni-radius variable + @if (map-has-key($uni-radius, $r) and $d){ + @if $d == t { + border-top-left-radius:$radius-value; + border-top-right-radius:$radius-value; + }@else if $d == r { + border-top-right-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == b { + border-bottom-left-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == l { + border-top-left-radius:$radius-value; + border-bottom-left-radius:$radius-value; + }@else if $d == tl { + border-top-left-radius:$radius-value; + }@else if $d == tr { + border-top-right-radius:$radius-value; + }@else if $d == br { + border-bottom-right-radius:$radius-value; + }@else if $d == bl { + border-bottom-left-radius:$radius-value; + } + }@else{ + border-radius:$radius-value; + } +} + +@each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $key} { + @include radius($key) + } + }@else{ + .uni-radius { + @include radius($key) + } + } +} + +@each $direction in t, r, b, l,tl, tr, br, bl { + @each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $direction}-#{"" + $key} { + @include radius($key,$direction,false) + } + }@else{ + .uni-radius-#{$direction} { + @include radius($key,$direction,false) + } + } + } +} diff --git a/uni_modules/uni-scss/styles/setting/_space.scss b/uni_modules/uni-scss/styles/setting/_space.scss new file mode 100644 index 0000000..3c89528 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_space.scss @@ -0,0 +1,56 @@ + +@mixin fn($space,$direction,$size,$n) { + @if $n { + #{$space}-#{$direction}: #{$size*$uni-space-root}px + } @else { + #{$space}-#{$direction}: #{-$size*$uni-space-root}px + } +} +@mixin get-styles($direction,$i,$space,$n){ + @if $direction == t { + @include fn($space, top,$i,$n); + } + @if $direction == r { + @include fn($space, right,$i,$n); + } + @if $direction == b { + @include fn($space, bottom,$i,$n); + } + @if $direction == l { + @include fn($space, left,$i,$n); + } + @if $direction == x { + @include fn($space, left,$i,$n); + @include fn($space, right,$i,$n); + } + @if $direction == y { + @include fn($space, top,$i,$n); + @include fn($space, bottom,$i,$n); + } + @if $direction == a { + @if $n { + #{$space}:#{$i*$uni-space-root}px; + } @else { + #{$space}:#{-$i*$uni-space-root}px; + } + } +} + +@each $orientation in m,p { + $space: margin; + @if $orientation == m { + $space: margin; + } @else { + $space: padding; + } + @for $i from 0 through 16 { + @each $direction in t, r, b, l, x, y, a { + .uni-#{$orientation}#{$direction}-#{$i} { + @include get-styles($direction,$i,$space,true); + } + .uni-#{$orientation}#{$direction}-n#{$i} { + @include get-styles($direction,$i,$space,false); + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_styles.scss b/uni_modules/uni-scss/styles/setting/_styles.scss new file mode 100644 index 0000000..689afec --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_styles.scss @@ -0,0 +1,167 @@ +/* #ifndef APP-NVUE */ + +$-color-white:#fff; +$-color-black:#000; +@mixin base-style($color) { + color: #fff; + background-color: $color; + border-color: mix($-color-black, $color, 8%); + &:not([hover-class]):active { + background: mix($-color-black, $color, 10%); + border-color: mix($-color-black, $color, 20%); + color: $-color-white; + outline: none; + } +} +@mixin is-color($color) { + @include base-style($color); + &[loading] { + @include base-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &[loading], + &:not([hover-class]):active { + color: $-color-white; + border-color: mix(darken($color,10%), $-color-white); + background-color: mix($color, $-color-white); + } + } + +} +@mixin base-plain-style($color) { + color:$color; + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 70%); + &:not([hover-class]):active { + background: mix($-color-white, $color, 80%); + color: $color; + outline: none; + border-color: mix($-color-white, $color, 50%); + } +} +@mixin is-plain($color){ + &[plain] { + @include base-plain-style($color); + &[loading] { + @include base-plain-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &:active { + color: mix($-color-white, $color, 40%); + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 80%); + } + } + } +} + + +.uni-btn { + margin: 5px; + color: #393939; + border:1px solid #ccc; + font-size: 16px; + font-weight: 200; + background-color: #F9F9F9; + // TODO 暂时处理边框隐藏一边的问题 + overflow: visible; + &::after{ + border: none; + } + + &:not([type]),&[type=default] { + color: #999; + &[loading] { + background: none; + &::before { + margin-right:5px; + } + } + + + + &[disabled]{ + color: mix($-color-white, #999, 60%); + &, + &[loading], + &:active { + color: mix($-color-white, #999, 60%); + background-color: mix($-color-white,$-color-black , 98%); + border-color: mix($-color-white, #999, 85%); + } + } + + &[plain] { + color: #999; + background: none; + border-color: $uni-border-1; + &:not([hover-class]):active { + background: none; + color: mix($-color-white, $-color-black, 80%); + border-color: mix($-color-white, $-color-black, 90%); + outline: none; + } + &[disabled]{ + &, + &[loading], + &:active { + background: none; + color: mix($-color-white, #999, 60%); + border-color: mix($-color-white, #999, 85%); + } + } + } + } + + &:not([hover-class]):active { + color: mix($-color-white, $-color-black, 50%); + } + + &[size=mini] { + font-size: 16px; + font-weight: 200; + border-radius: 8px; + } + + + + &.uni-btn-small { + font-size: 14px; + } + &.uni-btn-mini { + font-size: 12px; + } + + &.uni-btn-radius { + border-radius: 999px; + } + &[type=primary] { + @include is-color($uni-primary); + @include is-plain($uni-primary) + } + &[type=success] { + @include is-color($uni-success); + @include is-plain($uni-success) + } + &[type=error] { + @include is-color($uni-error); + @include is-plain($uni-error) + } + &[type=warning] { + @include is-color($uni-warning); + @include is-plain($uni-warning) + } + &[type=info] { + @include is-color($uni-info); + @include is-plain($uni-info) + } +} +/* #endif */ diff --git a/uni_modules/uni-scss/styles/setting/_text.scss b/uni_modules/uni-scss/styles/setting/_text.scss new file mode 100644 index 0000000..a34d08f --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_text.scss @@ -0,0 +1,24 @@ +@mixin get-styles($k,$c) { + @if $k == size or $k == weight{ + font-#{$k}:#{$c} + }@else{ + #{$k}:#{$c} + } +} + +@each $key, $child in $uni-headings { + /* #ifndef APP-NVUE */ + .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ + /* #ifdef APP-NVUE */ + .container .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ +} diff --git a/uni_modules/uni-scss/styles/setting/_variables.scss b/uni_modules/uni-scss/styles/setting/_variables.scss new file mode 100644 index 0000000..557d3d7 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_variables.scss @@ -0,0 +1,146 @@ +// @use "sass:math"; +@import '../tools/functions.scss'; +// 间距基础倍数 +$uni-space-root: 2 !default; +// 边框半径默认值 +$uni-radius-root:5px !default; +$uni-radius: () !default; +// 边框半径断点 +$uni-radius: map-deep-merge( + ( + 0: 0, + // TODO 当前版本暂时不支持 sm 属性 + // 'sm': math.div($uni-radius-root, 2), + null: $uni-radius-root, + 'lg': $uni-radius-root * 2, + 'xl': $uni-radius-root * 6, + 'pill': 9999px, + 'circle': 50% + ), + $uni-radius +); +// 字体家族 +$body-font-family: 'Roboto', sans-serif !default; +// 文本 +$heading-font-family: $body-font-family !default; +$uni-headings: () !default; +$letterSpacing: -0.01562em; +$uni-headings: map-deep-merge( + ( + 'h1': ( + size: 32px, + weight: 300, + line-height: 50px, + // letter-spacing:-0.01562em + ), + 'h2': ( + size: 28px, + weight: 300, + line-height: 40px, + // letter-spacing: -0.00833em + ), + 'h3': ( + size: 24px, + weight: 400, + line-height: 32px, + // letter-spacing: normal + ), + 'h4': ( + size: 20px, + weight: 400, + line-height: 30px, + // letter-spacing: 0.00735em + ), + 'h5': ( + size: 16px, + weight: 400, + line-height: 24px, + // letter-spacing: normal + ), + 'h6': ( + size: 14px, + weight: 500, + line-height: 18px, + // letter-spacing: 0.0125em + ), + 'subtitle': ( + size: 12px, + weight: 400, + line-height: 20px, + // letter-spacing: 0.00937em + ), + 'body': ( + font-size: 14px, + font-weight: 400, + line-height: 22px, + // letter-spacing: 0.03125em + ), + 'caption': ( + 'size': 12px, + 'weight': 400, + 'line-height': 20px, + // 'letter-spacing': 0.03333em, + // 'text-transform': false + ) + ), + $uni-headings +); + + + +// 主色 +$uni-primary: #2979ff !default; +$uni-primary-disable:lighten($uni-primary,20%) !default; +$uni-primary-light: lighten($uni-primary,25%) !default; + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37 !default; +$uni-success-disable:lighten($uni-success,20%) !default; +$uni-success-light: lighten($uni-success,25%) !default; + +$uni-warning: #f3a73f !default; +$uni-warning-disable:lighten($uni-warning,20%) !default; +$uni-warning-light: lighten($uni-warning,25%) !default; + +$uni-error: #e43d33 !default; +$uni-error-disable:lighten($uni-error,20%) !default; +$uni-error-light: lighten($uni-error,25%) !default; + +$uni-info: #8f939c !default; +$uni-info-disable:lighten($uni-info,20%) !default; +$uni-info-light: lighten($uni-info,25%) !default; + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a !default; // 主要文字 +$uni-base-color: #6a6a6a !default; // 常规文字 +$uni-secondary-color: #909399 !default; // 次要文字 +$uni-extra-color: #c7c7c7 !default; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0 !default; +$uni-border-2: #EDEDED !default; +$uni-border-3: #DCDCDC !default; +$uni-border-4: #B9B9B9 !default; + +// 常规色 +$uni-black: #000000 !default; +$uni-white: #ffffff !default; +$uni-transparent: rgba($color: #000000, $alpha: 0) !default; + +// 背景色 +$uni-bg-color: #f7f7f7 !default; + +/* 水平间距 */ +$uni-spacing-sm: 8px !default; +$uni-spacing-base: 15px !default; +$uni-spacing-lg: 30px !default; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default; +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default; + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4) !default; diff --git a/uni_modules/uni-scss/styles/tools/functions.scss b/uni_modules/uni-scss/styles/tools/functions.scss new file mode 100644 index 0000000..ac6f63e --- /dev/null +++ b/uni_modules/uni-scss/styles/tools/functions.scss @@ -0,0 +1,19 @@ +// 合并 map +@function map-deep-merge($parent-map, $child-map){ + $result: $parent-map; + @each $key, $child in $child-map { + $parent-has-key: map-has-key($result, $key); + $parent-value: map-get($result, $key); + $parent-type: type-of($parent-value); + $child-type: type-of($child); + $parent-is-map: $parent-type == map; + $child-is-map: $child-type == map; + + @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ + $result: map-merge($result, ( $key: $child )); + }@else { + $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); + } + } + @return $result; +}; diff --git a/uni_modules/uni-scss/theme.scss b/uni_modules/uni-scss/theme.scss new file mode 100644 index 0000000..80ee62f --- /dev/null +++ b/uni_modules/uni-scss/theme.scss @@ -0,0 +1,31 @@ +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; +// 主色 +$uni-primary: #2979ff; +// 辅助色 +$uni-success: #4cd964; +// 警告色 +$uni-warning: #f0ad4e; +// 错误色 +$uni-error: #dd524d; +// 描述色 +$uni-info: #909399; +// 中性色 +$uni-main-color: #303133; +$uni-base-color: #606266; +$uni-secondary-color: #909399; +$uni-extra-color: #C0C4CC; +// 背景色 +$uni-bg-color: #f5f5f5; +// 边框颜色 +$uni-border-1: #DCDFE6; +$uni-border-2: #E4E7ED; +$uni-border-3: #EBEEF5; +$uni-border-4: #F2F6FC; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); diff --git a/uni_modules/uni-scss/variables.scss b/uni_modules/uni-scss/variables.scss new file mode 100644 index 0000000..1c062d4 --- /dev/null +++ b/uni_modules/uni-scss/variables.scss @@ -0,0 +1,62 @@ +@import './styles/setting/_variables.scss'; +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; + +// 主色 +$uni-primary: #2979ff; +$uni-primary-disable:mix(#fff,$uni-primary,50%); +$uni-primary-light: mix(#fff,$uni-primary,80%); + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37; +$uni-success-disable:mix(#fff,$uni-success,50%); +$uni-success-light: mix(#fff,$uni-success,80%); + +$uni-warning: #f3a73f; +$uni-warning-disable:mix(#fff,$uni-warning,50%); +$uni-warning-light: mix(#fff,$uni-warning,80%); + +$uni-error: #e43d33; +$uni-error-disable:mix(#fff,$uni-error,50%); +$uni-error-light: mix(#fff,$uni-error,80%); + +$uni-info: #8f939c; +$uni-info-disable:mix(#fff,$uni-info,50%); +$uni-info-light: mix(#fff,$uni-info,80%); + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a; // 主要文字 +$uni-base-color: #6a6a6a; // 常规文字 +$uni-secondary-color: #909399; // 次要文字 +$uni-extra-color: #c7c7c7; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0; +$uni-border-2: #EDEDED; +$uni-border-3: #DCDCDC; +$uni-border-4: #B9B9B9; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); + +// 背景色 +$uni-bg-color: #f7f7f7; + +/* 水平间距 */ +$uni-spacing-sm: 8px; +$uni-spacing-base: 15px; +$uni-spacing-lg: 30px; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4); diff --git a/uni_modules/vrapile-im/changelog.md b/uni_modules/vrapile-im/changelog.md new file mode 100644 index 0000000..131479a --- /dev/null +++ b/uni_modules/vrapile-im/changelog.md @@ -0,0 +1,40 @@ +## 1.1.9(2025-03-27) +示例工程接口配置,改为通过环境变量实现 +## 1.1.8(2025-03-26) +上传示例工程 +## 1.1.7(2025-03-26) +更新已知问题 +## 1.1.6(2025-03-25) +将demo插件使用示例工程上传 +## 1.1.5(2025-03-18) +修复已知问题 +## 1.1.4(2025-03-18) +聊天页下拉刷新,查看更多历史功能 +## 1.1.3(2025-03-18) +优化已知问题 +## 1.1.2(2025-03-18) +解决页面组件内部store监听bug,解决问题:发送消息后没有自动滚动到最底部,也没有已读当前人 +## 1.1.1(2025-03-18) +更新插件演示程序 +## 1.1.0(2025-02-26) +修复已知问题 +## 1.0.9(2025-02-26) +修复已知问题 +## 1.0.8(2025-02-26) +将demo放在组件中,细节继续调试 +## 1.0.7(2025-02-26) +功能还在调试中,敬请期待... +## 1.0.6(2025-02-21) +开发中... +## 1.0.5(2025-02-21) +开发中... +## 1.0.4(2025-02-21) +开发中 +## 1.0.3(2025-02-21) +开发中 +## 1.0.2(2025-02-21) +开发中 +## 1.0.1(2025-02-21) +开发中 +## 1.0.0(2025-02-21) +开发中,敬请期待 diff --git a/uni_modules/vrapile-im/components/vrapile-im/vrapile-im.vue b/uni_modules/vrapile-im/components/vrapile-im/vrapile-im.vue new file mode 100644 index 0000000..a50a980 --- /dev/null +++ b/uni_modules/vrapile-im/components/vrapile-im/vrapile-im.vue @@ -0,0 +1,5 @@ + diff --git a/uni_modules/vrapile-im/package.json b/uni_modules/vrapile-im/package.json new file mode 100644 index 0000000..4da7903 --- /dev/null +++ b/uni_modules/vrapile-im/package.json @@ -0,0 +1,86 @@ +{ + "id": "vrapile-im", + "displayName": "im页面组件", + "version": "1.1.9", + "description": "实现WebSocket连接/好友/群组/新消息/历史消息,都是全局配置并本地化存储,已调试兼容H5/微信小程序/安卓App/PC多端同步通讯", + "keywords": [ + "IM页面组件,websocket应用" +], + "repository": "", + "engines": { + "HBuilderX": "^3.94" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [ + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "y", + "app-uvue": "u", + "app-harmony": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y", + "钉钉": "y", + "快手": "y", + "飞书": "y", + "京东": "y" + }, + "快应用": { + "华为": "y", + "联盟": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/vrapile-im/pages/chat/chatFriend.vue b/uni_modules/vrapile-im/pages/chat/chatFriend.vue new file mode 100644 index 0000000..e73583b --- /dev/null +++ b/uni_modules/vrapile-im/pages/chat/chatFriend.vue @@ -0,0 +1,335 @@ + + + + diff --git a/uni_modules/vrapile-im/pages/home/chatHome.vue b/uni_modules/vrapile-im/pages/home/chatHome.vue new file mode 100644 index 0000000..6f16c44 --- /dev/null +++ b/uni_modules/vrapile-im/pages/home/chatHome.vue @@ -0,0 +1,184 @@ + + + + diff --git a/uni_modules/vrapile-im/pages_init.json b/uni_modules/vrapile-im/pages_init.json new file mode 100644 index 0000000..c277650 --- /dev/null +++ b/uni_modules/vrapile-im/pages_init.json @@ -0,0 +1,20 @@ +{ + "pages": [ + // 消息 + { + "path": "uni_modules/vrapile-im/pages/home/chatHome", + "style": { + "navigationBarTitleText": "消息", + "enablePullDownRefresh": false + } + }, + // 聊天 + { + "path": "uni_modules/vrapile-im/pages/chat/chatFriend", + "style": { + "navigationBarTitleText": "聊天", + "enablePullDownRefresh": true + } + } + ] +} diff --git a/uni_modules/vrapile-im/readme.md b/uni_modules/vrapile-im/readme.md new file mode 100644 index 0000000..14116ed --- /dev/null +++ b/uni_modules/vrapile-im/readme.md @@ -0,0 +1,105 @@ +## 组件说明 +1. 此组件为页面组件,实现了Socket连接/好友/群组/新消息/历史消息,且都是全局配置全局本地化存储,兼容H5/微信小程序/安卓App(其他平台未做调试) + +2. 此组件中已提供示例工程,其中的接口和websocket服务,仅供各位开发者调试使用,正式发布需自行实现接口和websocket服务。 + + +## 自行准备内容 + +1. WebSocket服务,替换.env.development下VITE_APP_SOCKET_URL地址 + + websocket需要实现连接,实现心跳检测/离线消息/在线消息/已读回执4种消息类型 + +2. 接口服务,实现聊天/api/chat.js和/api/login.js里面的方法 + + +## 引用说明 + +### 1. 路由说明 + +导入组件后,在pages.json中会自动注册组件,若未注册可手动添加 +``` javascript +{ + "path": "uni_modules/vrapile-im/pages/home/chatHome", + "style": { + "enablePullDownRefresh": false, + "navigationBarTitleText": "消息" + } +}, +{ + "path": "uni_modules/vrapile-im/pages/chat/chatFriend", + "style": { + "enablePullDownRefresh": false, + "navigationBarTitleText": "聊天" + } +} +``` + +可在导航中配置IM消息页面 + +``` javascript +"tabBar": { + "selectedColor": "#0000ff", + "list": [ + { + "pagePath": "uni_modules/vrapile-im/pages/home/chatHome", + "iconPath": "static/image/tabbar/chat.png", + "selectedIconPath": "static/image/tabbar/chat-fill.png", + "text": "消息" + }, + { + "pagePath": "pages/home/user", + "iconPath": "static/image/tabbar/user.png", + "selectedIconPath": "static/image/tabbar/user-fill.png", + "text": "我的" + } + ] +}, +``` + +### 2. 页面样式修改 + 页面样式在/uni_modules/vrapile-im/static/style/下的nine-chat-home-001.scss和nine-chat-friend-001.scss中, + + 可通过重写/static/style/下的nine-chat-home-001.scss和nine-chat-friend-001.scss,将原样式替换 + + +## 演示说明 + +以下共用一个后端,全部互通 + +
+ +示例工程运行效果: + +https://www.ninecloud.top/udemo/im/index.html + + + +
+
+ + +演示商城H5效果: + +https://www.ninecloud.top/unine/index.html + + + +H5中可下载安卓App + +
+
+ +演示PC前端(与此组件无关,可用于多端消息互相发送测试): + +https://www.ninecloud.top/msw/index + + +
+
+ +注:新注册账号,默认添加【visitor】为好友,默认加入【客服专用群】群 + +因此,可用访客/注册账号登录以上任意系统,可任意发送消息,皆能同步显示 + +(*以上系统皆可用访客账号/密码:visitor/visitor*) \ No newline at end of file diff --git a/uni_modules/vrapile-im/static/image/emoji.png b/uni_modules/vrapile-im/static/image/emoji.png new file mode 100644 index 0000000..62091e2 Binary files /dev/null and b/uni_modules/vrapile-im/static/image/emoji.png differ diff --git a/uni_modules/vrapile-im/static/image/message.png b/uni_modules/vrapile-im/static/image/message.png new file mode 100644 index 0000000..5ae809e Binary files /dev/null and b/uni_modules/vrapile-im/static/image/message.png differ diff --git a/uni_modules/vrapile-im/static/image/more.png b/uni_modules/vrapile-im/static/image/more.png new file mode 100644 index 0000000..0833011 Binary files /dev/null and b/uni_modules/vrapile-im/static/image/more.png differ diff --git a/uni_modules/vrapile-im/static/image/voice.png b/uni_modules/vrapile-im/static/image/voice.png new file mode 100644 index 0000000..bfd3e81 Binary files /dev/null and b/uni_modules/vrapile-im/static/image/voice.png differ diff --git a/uni_modules/vrapile-im/static/image/yy.png b/uni_modules/vrapile-im/static/image/yy.png new file mode 100644 index 0000000..2ffff1b Binary files /dev/null and b/uni_modules/vrapile-im/static/image/yy.png differ diff --git a/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss b/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss new file mode 100644 index 0000000..c1c1346 --- /dev/null +++ b/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss @@ -0,0 +1,165 @@ +html, body, #app{ + height: 100%; + background-color: #f1f1f1; +} +.nine-content-001{ + display: flex; + flex-direction: column; + width: 750rpx; + height: calc(100vh - 0px); + margin: 0; + padding: 0; + background-color: #f1f1f1; +} +.chat-body { + /* #ifdef MP-WEIXIN */ + background-color: #fff; + /* #endif */ +} +.chat-body-main{ + padding-top: 20rpx; + padding-left: 20rpx; + padding-right: 20rpx; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + padding-bottom: 100rpx; +} +.chat-body-history{ + width: 100%; + height: 90rpx; + line-height: 90rpx; + font-size: 24rpx; + color: grey; + text-align: center; +} +.chat-body-history-have{ + color: rgb(79, 172, 249); +} +.chat-conversation{ + display: flex; + align-items: flex-start; + padding: 20rpx 5rpx; + word-break: break-all; +} +.chat-conversation-text{ + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 0 20rpx; +} +.chat-conversation-text-time{ + font-size: 10px; + color: gray; +} +.chat-conversation-text-text{ + position: relative; + display: flex; + align-items: center; + max-width: 70%; + min-height: 45rpx; + padding: 15rpx 20rpx; + border-radius: 10rpx; + background-color: #FFF; + /* #ifdef MP-WEIXIN */ + background-color: #f1f1f1; + /* #endif */ +} +.chat-conversation-text-text::after { + content: ''; + position: absolute; + top: 16rpx; + left: -35rpx; + border-width: 19rpx; + border-style: solid; + border-top-color: transparent; + border-left-color: transparent; + border-right-color: #FFF; + /* #ifdef MP-WEIXIN */ + border-right-color: #f1f1f1; + /* #endif */ + border-bottom-color: transparent; +} +.chat-conversation-mine{ + align-items: flex-start; + flex-direction: row-reverse; +} +.chat-conversation-mine .chat-conversation-text{ + align-items: flex-end; +} +.chat-conversation-mine .chat-conversation-text-time{ + text-align: right; +} +.chat-conversation-mine .chat-conversation-text-text{ + background: #9ede86 !important; +} +.chat-conversation-mine .chat-conversation-text-text::after { + left: auto !important; + right: -35rpx !important; + border-left-color: #9ede86 !important; + border-right-color: transparent !important; +} +.chat-conversation-image{ +} +.chat-conversation-image-image{ + width: 80rpx; + height: 80rpx; + padding: 5rpx; + border-radius: 10rpx; +} + +.chat-footer { + position: fixed; + left: 0; + right: 0; + bottom: 0; + height: 100rpx; + background-color: #fff; + display: flex; + /* #ifdef MP-WEIXIN */ + border-top: 1rpx solid #f1f1f1; + /* #endif */ +} +.chat-footer-send{ + flex-grow: 1; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 10rpx; +} +.chat-footer-send-image{ + padding: 0 10rpx; + width: 60rpx; + height: 60rpx; +} +.chat-footer-send-input{ + flex-grow: 1; + text-align: left; + padding: 15rpx; + border-radius: 5rpx; + background-color: #f9f9f9; +} +.chat-footer-send-say{ + flex-grow: 1; + text-align: center; + padding: 20rpx; + border-radius: 5rpx; + background-color: #f9f9f9; +} +.chat-footer-send-button{ + line-height: 65rpx; + margin: 0 10rpx; + color: #FFFFFF; + background-color: #0000ff; + border-radius: 10rpx; +} +.chat-footer-send-button-span{ + padding: 0 25rpx; +} + +// 允许文本复制 +.nine-user-select { + cursor: auto; + -webkit-user-select: text; + user-select: text; +} \ No newline at end of file diff --git a/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss b/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss new file mode 100644 index 0000000..20c165f --- /dev/null +++ b/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss @@ -0,0 +1,112 @@ +html, body, #app{ + height: 100%; + background-color: #f1f1f1; +} +.nine-content-002{ + display: flex; + flex-direction: column; + width: 750rpx; + height: calc(100vh - 50px); + /* #ifndef H5 */ + height: calc(100vh - 0px); + /* #endif */ + margin: 0; + padding: 0; + background-color: #f1f1f1; +} + +.chat-search{ + display: flex; + align-items: center; + padding: 5rpx; + background-color: #ffffff; +} +.chat-search-image{ + height: 45rpx; + line-height: 45rpx; + padding: 10rpx; + background-color: #f8f8f8; +} +.chat-search-input{ + width: 100%; + height: 45rpx; + line-height: 45rpx; + padding: 10rpx; + font-size: 16px; + background-color: #f8f8f8; +} + +.chat-list{ + flex: 1; + padding: 0; + overflow-y: auto; +} +.chat-list-item{ + display: flex; + align-items: center; + justify-content: space-between; + margin: 2rpx 0; + padding: 15rpx 10rpx; + border-radius: 10rpx; + background-color: #ffffff; +} +.chat-list-item-left{ + position: relative; + width: 84rpx; + height: 84rpx; +} +.chat-list-item-left-image{ + width: 82rpx; + height: 82rpx; + border: 1rpx solid #f1f1f1; + border-radius: 5rpx; +} +.chat-list-item-left-mark{ + position: absolute; + width: 30rpx; + top: -13rpx; + right: -13rpx; + padding: 1rpx; + border-radius: 50%; + font-size: 12px; + color: white; + background-color: red; + text-align: center; +} + +.chat-list-item-center{ + width: 450rpx; + margin: 0 20rpx; +} +.chat-list-item-center-top{ + width: 450rpx; + font-size: 16px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.chat-list-item-center-bottom{ + width: 450rpx; + font-size: 12px; + color: #969696; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.chat-list-item-right{ + width: 130rpx; + color: #a7a7a7; +} +.chat-list-item-right-top{ + font-size: 12px; + text-align: right; +} +.chat-list-item-right-bottom{ + padding-top: 15rpx; + text-align: right; +} +.chat-list-item-right-bottom-image{ + width: 25rpx; + height: 30rpx; +} \ No newline at end of file diff --git a/uni_modules/vrapile-im/store/getters.js b/uni_modules/vrapile-im/store/getters.js new file mode 100644 index 0000000..7ec169e --- /dev/null +++ b/uni_modules/vrapile-im/store/getters.js @@ -0,0 +1,11 @@ +const getters = { + chatList: state => state.chat.chatList, + friendList: state => state.chat.friendList, + groupList: state => state.chat.groupList, + userObject: state => state.chat.userObject, + groupObject: state => state.chat.groupObject, + + websocket: state => state.socket.websocket, + websocketData: state => state.socket.websocketData +} +export default getters diff --git a/uni_modules/vrapile-im/store/index.js b/uni_modules/vrapile-im/store/index.js new file mode 100644 index 0000000..babbcd7 --- /dev/null +++ b/uni_modules/vrapile-im/store/index.js @@ -0,0 +1,16 @@ +import Vuex from 'vuex' +import socket from '@/uni_modules/vrapile-im/store/modules/socket' +import chat from '@/uni_modules/vrapile-im/store/modules/chat' +import getters from './getters' + +// Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + chat, + socket + }, + getters +}) + +export default store diff --git a/uni_modules/vrapile-im/store/modules/chat.js b/uni_modules/vrapile-im/store/modules/chat.js new file mode 100644 index 0000000..5e83eaa --- /dev/null +++ b/uni_modules/vrapile-im/store/modules/chat.js @@ -0,0 +1,138 @@ +import storage from '@/uni_modules/vrapile-im/utils/storage' +import constant from '@/uni_modules/vrapile-im/utils/constant' +import { getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; + + // 外部需提供获取用户好友,获取用户所有群,以及群中所有用户三个接口 +import { getUserAllFriend, getUserAllGroup, getGroupUser } from '@/api/chat' + +const chat = { + state: { + friendList: storage.get(constant.friendList) || [], + groupList: storage.get(constant.groupList) || [], + userObject: storage.get(constant.userObject) || {}, + groupObject: storage.get(constant.groupObject) || {}, + chatList: storage.get(constant.chatList) || [] + }, + + mutations: { + // 清空聊天列表 + CLEAN_CHAT_LIST: (state) => { + state.chatList = new Array(); + storage.set(constant.chatList, state.chatList) + }, + // 存储好友聊天列表 + SET_CHAT_FRIEND_LIST: (state, data) => { + state.friendList = data; + storage.set(constant.friendList, data) + + for(let item of data){ + item["key"] = getChatKey(item["type"], item["friendId"], item["userId"]) + item["haveHistory"] = 1; + item["id"] = item["friendId"]; + item["name"] = item["remarkName"] || item["nickName"]; + item["messageNum"] = 0; + item["messageList"] = []; + item["messageShow"] = ""; + item["messageLast"] = {}; + state.chatList.push(item) + } + storage.set(constant.chatList, state.chatList) + }, + // 存储群聊列表 + SET_CHAT_GROUP_LIST: (state, data) => { + state.groupList = data; + storage.set(constant.groupList, data) + + for(let item of data){ + item["key"] = getChatKey(item["type"], item["id"], item["userId"]) + item["haveHistory"] = 1; + item["id"] = item["id"]; + item["name"] = item["remarkName"] || item["name"] + item["messageNum"] = 0; + item["messageList"] = []; + item["messageShow"] = ""; + item["messageLast"] = {}; + state.chatList.push(item) + } + storage.set(constant.chatList, state.chatList) + }, + // 存储用户对象,方便寻找用户名,头像等 + SET_USER_OBJECT: (state, userObject) => { + state.userObject[userObject.userId] = userObject; + storage.set(constant.userObject, state.userObject) + }, + // 存储群组对象,方便寻找群组名,头像等 + SET_GROUP_OBJECT: (state, groupObject) => { + state.groupObject[groupObject.id] = groupObject; + storage.set(constant.groupObject, state.groupObject) + } + }, + + actions: { + // 获取登录用户所有聊天列表 + GetChatList({ commit, state }, params) { + return new Promise((resolve, reject) => { + commit('CLEAN_CHAT_LIST'); + // 查询好友 + getUserAllFriend().then(res => { + let list = [] + for(let item of res.data){ + list.push({type: 0, ...item, userId: params.userId}) + commit('SET_USER_OBJECT', item) + } + commit('SET_CHAT_FRIEND_LIST', list) + + // 查询群组 + getUserAllGroup().then(res1 => { + let list = [] + for(let item1 of res1.data){ + list.push({type: 1, ...item1, userId: params.userId}) + // 查询群组人员 + getGroupUser(item1.id).then(res2 => { + for(let user of res2.data){ + commit('SET_USER_OBJECT', user) + } + resolve(res2) + }); + commit('SET_GROUP_OBJECT', item1) + } + commit('SET_CHAT_GROUP_LIST', list) + }).catch(error => { + reject(error) + }) + }).catch(error => { + reject(error) + }) + }) + } + }, + + getters: { + getUserAvatar: (state) => (userId, defaultAvatar) => { + if(state.userObject[userId] && state.userObject[userId]["avatar"]){ + return state.userObject[userId]["avatar"] + } + return defaultAvatar || '/uni_modules/vrapile-im/static/image/yy.png'; + }, + getGroupAvatar: (state) => (groupId, defaultAvatar) => { + if(state.groupObject[groupId] && state.groupObject[groupId]["avatar"]){ + return state.groupObject[groupId]["avatar"] + } + return defaultAvatar || '/uni_modules/vrapile-im/static/image/yy.png'; + }, + getUserName: (state) => (userId, defaultName) => { + if(state.userObject[userId]){ + return state.userObject[userId]["remarkName"] || state.userObject[userId]["nickName"] || defaultName + } + return defaultName || "无名"; + }, + getGroupName: (state) => (groupId, defaultName) => { + if(state.groupObject[groupId]){ + return state.groupObject[userId]["remarkName"] || state.groupObject[userId]["name"] || defaultName + } + return defaultName || "无名"; + } + } +} + +export default chat diff --git a/uni_modules/vrapile-im/store/modules/socket.js b/uni_modules/vrapile-im/store/modules/socket.js new file mode 100644 index 0000000..fe68749 --- /dev/null +++ b/uni_modules/vrapile-im/store/modules/socket.js @@ -0,0 +1,116 @@ +import store from '@/uni_modules/vrapile-im/store' +import storage from '@/uni_modules/vrapile-im/utils/storage' +import constant from '@/uni_modules/vrapile-im/utils/constant' +import { formatDate } from '@/uni_modules/vrapile-im/utils/nineTool'; +import { TioSocket, getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; + +const socket = { + state: { + websocket: storage.get(constant.websocket), + websocketData: storage.get(constant.websocketData) + }, + + mutations: { + // 存储登录链接 + SET_SOCKET: (state, socket) => { + state.websocket = socket; + storage.set(constant.websocket, socket) + }, + // 添加socket消息 + ADD_MESSAGE: (state, message) => { + state.websocketData.push(message) + storage.set(constant.websocketData, state.websocketData) + + // 添加消息 + for(let i=0;i { + // 删除未读消息 + for(let i=0;i { + let unReadNum = 0 + for(let i=0;i 0){ + uni.setTabBarBadge({ + index: getApp().globalData.msgTabBarIndex, + text: String(unReadNum), + fail: (e) => { + // console.log(e) + } + }) + }else{ + uni.removeTabBarBadge({ + index: getApp().globalData.msgTabBarIndex + }) + } + }catch(e){ + + } + }, + // 清空消息 + CLEAN_MESSAGE: (state, message) => { + state.websocketData = new Array(); + storage.set(constant.websocketData, new Array()) + } + }, + + actions: { + // 连接websocket + ConnSocket({ commit, state }, params) { + return new Promise((resolve, reject) => { + let url = params.url; + let heartbeatTimeout = 50000; // 心跳超时时间,单位:毫秒 + let reconnInterval = 5000; // 重连间隔时间,单位:毫秒 + let paramStr = "app=unine&token=" + params.token + let socket = new TioSocket(url, paramStr, heartbeatTimeout, reconnInterval); + socket.connect(false); + }) + } + } +} + +export default socket diff --git a/uni_modules/vrapile-im/utils/cache.js b/uni_modules/vrapile-im/utils/cache.js new file mode 100644 index 0000000..a248213 --- /dev/null +++ b/uni_modules/vrapile-im/utils/cache.js @@ -0,0 +1,26 @@ +const sessionCache = 'vrapile-im-session-cache' +const localCache = 'vrapile-im-local-cache' + +export function getSessionCache() { + return uni.getStorageSync(sessionCache) +} + +export function setSessionCache(cache) { + return uni.setStorageSync(sessionCache, cache) +} + +export function removeSessionCache() { + return uni.removeStorageSync(sessionCache) +} + +export function getLocalCache() { + return uni.getStorageSync(localCache) +} + +export function setLocalCache(cache) { + return uni.setStorageSync(localCache, cache) +} + +export function removeLocalCache() { + return uni.removeStorageSync(localCache) +} diff --git a/uni_modules/vrapile-im/utils/constant.js b/uni_modules/vrapile-im/utils/constant.js new file mode 100644 index 0000000..1158b94 --- /dev/null +++ b/uni_modules/vrapile-im/utils/constant.js @@ -0,0 +1,6 @@ +const constant = { + websocket: 'vuex_vrapile_im_websocket', + websocketData: 'vuex_vrapile_im_websocket_data' +} + + export default constant diff --git a/uni_modules/vrapile-im/utils/errorCode.js b/uni_modules/vrapile-im/utils/errorCode.js new file mode 100644 index 0000000..d2111ee --- /dev/null +++ b/uni_modules/vrapile-im/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/uni_modules/vrapile-im/utils/nineTool.js b/uni_modules/vrapile-im/utils/nineTool.js new file mode 100644 index 0000000..843ec96 --- /dev/null +++ b/uni_modules/vrapile-im/utils/nineTool.js @@ -0,0 +1,348 @@ + +export function isNull(o) { + if(o === 0 || o === "0"){ + return false; + } + if(o == "undefined" || o == null || o == ""){ + return true; + } + return false; +} +export function isPhone(o) { + if(/^1[23456789]\d{9}$/.test(o)){ + return true; + } + return false; +} +export function isMail(o) { + if(/^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$/.test(o)){ + return true; + } + return false; +} +export function isNumber(value) { + return !isNaN(parseFloat(value)) && isFinite(value) +} +export function isLetter(o) { + if(/^[A-Za-z]+$/.test(o)){ + return true; + } + return false; +} +export function isNumberOrLetter(o) { + if(/^[A-Za-z0-9]+$/.test(o)){ + return true; + } + return false; +} + +// 日期格式化 +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +export function formatDate(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + + if (option) { + return parseTime(time, option) + } + + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } else if (diff < 3600 * 24 * 3) { + return '2天前' + } else if (diff < 3600 * 24 * 4) { + return '3天前' + } else if (diff < 3600 * 24 * 5) { + return '4天前' + } else if (diff < 3600 * 24 * 6) { + return '5天前' + } else if (diff < 3600 * 24 * 7) { + return '6天前' + } else if (diff < 3600 * 24 * 8) { + return '7天前' + } + if(diff < 3600 * 24 * 365) { + return ( + (d.getMonth()*1 + 1) + + '月' + + d.getDate() + + '日' + ) + } else { + return ( + d.getFullYear() + + '年' + + (d.getMonth()*1 + 1) + + '月' + ) + } +} + +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + + if (option) { + return parseTime(time, option) + } + + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + return ( + d.getFullYear() + + '-' + + ((d.getMonth()*1 + 1) + "").padStart(2,0) + + '-' + + (d.getDate() + '').padStart(2,0) + + ' ' + + (d.getHours() + '').padStart(2,0) + + ':' + + (d.getMinutes() + '').padStart(2,0) + + ':' + + (d.getSeconds() + '').padStart(2,0) + ) +} + +// number:要格式化的数字, +// decimals:保留几位小数, 默认0位 +// dec_point:小数点符号, 默认 . +// thousands_sep:千分位符号 默认 , +// tail_add: 小数点后面数据是否添加0补足位数, 默认空字符 +// null_default: 如果为空的值, 默认空字符 +function numberFormat(number, decimals, dec_point, thousands_sep, tail_add="", null_default="") { + number = (number + '').replace(/[^0-9+-Ee.]/g, ''); + var n = !isFinite(+number) ? 0 : +number, + prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), + sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, + dec = (typeof dec_point === 'undefined') ? '.' : dec_point, + s = '', + toFixedFix = function (n, prec) { + var k = Math.pow(10, prec); + return '' + Math.round(n * k) / k; + }; + + s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); + var re = /(-?\d+)(\d{3})/; + if(sep.length > 0){ + while (re.test(s[0])) { + s[0] = s[0].replace(re, "$1" + sep + "$2"); + } + } + if ((s[1] || '').length < prec) { + s[1] = s[1] || ''; + s[1] += new Array(prec - s[1].length + 1).join(tail_add); + } + if((s[1] || '').length == 0){ + return s[0] + } + return s.join(dec); +} +// number:要格式化的数字, +// decimals:保留几位小数, 默认0位 +// dec_point:小数点符号, 默认 . +// thousands_sep:千分位符号 默认 , +// tail_add: 小数点后面数据是否添加0补足位数, 默认空字符 +// null_default: 如果为空的值, 默认空字符 +export function formatNumber(number, decimals, tail_add, thousands_sep, dec_point, null_default) { + if(isNull(number) || isNull(String(number).trim())){return null_default;} + if(!isNumber(String(number).trim())){return number;} + number = String(number).trim(); + return numberFormat(number, decimals, tail_add, thousands_sep, dec_point, null_default); +} +// thousands_sep:千分位符号 默认空字符 +export function formatPercent(number, decimals, tail_add, thousands_sep="", dec_point, null_default) { + if(isNull(number) || isNull(String(number).trim().replaceAll(",", ""))){return null_default;} + if(!isNumber(String(number).trim().replaceAll(",", ""))){return number;} + number = String(number).trim().replaceAll(",", ""); + let value = numberFormat(number*100, decimals, tail_add, thousands_sep, dec_point, null_default); + if(value){ + return value + "%"; + } + return ""; +} + +// get brower +export function GetCurrentBrowser () { + let ua = navigator.userAgent.toLocaleLowerCase() + let browserType = null + if (ua.match(/msie/) != null || ua.match(/trident/) != null) { + browserType = 'IE' + } else if (ua.match(/firefox/) != null) { + browserType = 'firefox' + } else if (ua.match(/ucbrowser/) != null) { + browserType = 'UC' + } else if (ua.match(/opera/) != null || ua.match(/opr/) != null) { + browserType = 'opera' + } else if (ua.match(/bidubrowser/) != null) { + browserType = 'baidu' + } else if (ua.match(/metasr/) != null) { + browserType = 'sougou' + } else if (ua.match(/tencenttraveler/) != null || ua.match(/qqbrowse/) != null) { + browserType = 'QQ' + } else if (ua.match(/maxthon/) != null) { + browserType = 'maxthon' + } else if (ua.match(/chrome/) != null) { + var is360 = _mime('type', 'application/vnd.chromium.remoting-viewer') + if (is360) { + browserType = '360' + } else { + browserType = 'chrome' + } + } else if (ua.match(/safari/) != null) { + browserType = 'Safari' + } else { + browserType = 'others' + } + return browserType +} + +function _mime (option, value) { + var mimeTypes = navigator.mimeTypes + for (var mt in mimeTypes) { + if (mimeTypes[mt][option] === value) { + return true + } + } + return false +} + +// get os +export function GetOs () { + let sUserAgent = navigator.userAgent.toLocaleLowerCase() + let isWin = (navigator.platform.toLocaleLowerCase() == 'win32') || (navigator.platform.toLocaleLowerCase() === 'windows') + let isMac = (navigator.platform.toLocaleLowerCase() === 'mac68k') || (navigator.platform.toLocaleLowerCase() === 'macppc') + || (navigator.platform === 'macintosh') || (navigator.platform.toLocaleLowerCase() === 'macintel') + if (isMac) return 'Mac' + var isUnix = (navigator.platform === 'x11') && !isWin && !isMac + if (isUnix) return 'Unix' + var isLinux = (String(navigator.platform.toLocaleLowerCase()).indexOf('linux') > -1) + if (isLinux) return 'Linux' + if (isWin) { + var isWin2K = sUserAgent.indexOf('windows nt 5.0') > -1 || sUserAgent.indexOf('windows 2000') > -1 + if (isWin2K) return 'Win2000' + var isWinXP = sUserAgent.indexOf('windows nt 5.1') > -1 || sUserAgent.indexOf('windows xp') > -1 + if (isWinXP) return 'WinXP' + var isWin2003 = sUserAgent.indexOf('windows nt 5.2') > -1 || sUserAgent.indexOf('windows 2003') > -1 + if (isWin2003) return 'Win2003' + var isWinVista = sUserAgent.indexOf('windows nt 6.0') > -1 || sUserAgent.indexOf('windows vista') > -1 + if (isWinVista) return 'WinVista' + var isWin7 = sUserAgent.indexOf('windows nt 6.1') > -1 || sUserAgent.indexOf('windows 7') > -1 + if (isWin7) return 'Win7' + var isWin8 = sUserAgent.indexOf('windows nt 6.2') > -1 || sUserAgent.indexOf('windows 8') > -1 + if (isWin8) return 'Win8' + var isWin10 = sUserAgent.indexOf('windows nt 10.0') > -1 || sUserAgent.indexOf('windows nt 6.4') > -1 || sUserAgent.indexOf('windows 10') > -1 + if (isWin10) return 'Win10' + var isSimulator = sUserAgent.indexOf('linux') > -1 && sUserAgent.indexOf('android') > -1 + if (isSimulator) return 'Win手机模拟器' + return navigator.platform + } + if (sUserAgent.indexOf('android') > -1) return 'Android' + if (sUserAgent.indexOf('iphone') > -1) return 'iPhone' + if (sUserAgent.indexOf('symbianos') > -1) return 'SymbianOS' + if (sUserAgent.indexOf('windows phone') > -1) return 'Windows Phone' + if (sUserAgent.indexOf('ipad') > -1) return 'iPad' + if (sUserAgent.indexOf('ipod') > -1) return 'iPod' + return navigator.platform +} + +export function getRandom(len){ + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return data.substr(index, len); +} + +export function getLongRandom(len){ + if(len <= 16){ + return getRandom(len) + } + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return parseTime(Date.now(), '{y}{m}{d}{h}{i}{s}') + "" + data.substr(index, len-16); +} + +export function moveInArray(array, fromIndex, toIndex) { + const element = array.splice(fromIndex, 1)[0]; + array.splice(toIndex, 0, element); +} + +export function jsonCharBigInt(s){ + if(typeof s !== 'string'){ + return s + } + let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g + return s.replaceAll(re, "$1$2$1$3$1") +} + +export function jsonParse(s){ + if(typeof s !== 'string'){ + return s + } + let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g + return JSON.parse(s.replaceAll(re, "$1$2$1$3$1")) +} \ No newline at end of file diff --git a/uni_modules/vrapile-im/utils/storage.js b/uni_modules/vrapile-im/utils/storage.js new file mode 100644 index 0000000..88dc1ed --- /dev/null +++ b/uni_modules/vrapile-im/utils/storage.js @@ -0,0 +1,33 @@ +import constant from './constant' + +// 存储变量名 +let storageKey = 'vrapile_im_socket_storage_data' + +// 存储节点变量名 +let storageNodeKeys = [constant.chatList, constant.friendList, constant.groupList, + constant.userObject, constant.groupObject, constant.websocket, constant.websocketData] + +const storage = { + set: function(key, value) { + if (storageNodeKeys.indexOf(key) != -1) { + let tmp = uni.getStorageSync(storageKey) + tmp = tmp ? tmp : {} + tmp[key] = value + uni.setStorageSync(storageKey, tmp) + } + }, + get: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + return storageData[key] || "" + }, + remove: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + delete storageData[key] + uni.setStorageSync(storageKey, storageData) + }, + clean: function() { + uni.removeStorageSync(storageKey) + } +} + +export default storage diff --git a/uni_modules/vrapile-im/utils/tiosocket.js b/uni_modules/vrapile-im/utils/tiosocket.js new file mode 100644 index 0000000..58bfc0d --- /dev/null +++ b/uni_modules/vrapile-im/utils/tiosocket.js @@ -0,0 +1,181 @@ +import store from '@/uni_modules/vrapile-im/store' + +/** + * @param {*} url wss or ws + * @param {*} paramStr 加在ws url后面的请求参数,形如:name=张三&id=12 + * @param {*} heartbeatTimeout 心跳时间 单位:毫秒 + * @param {*} reconnInterval 重连间隔时间 单位:毫秒 + */ +export class TioSocket { + constructor(url, paramStr, heartbeatTimeout, reconnInterval) { + this.firstUrl = url; + this.reconnUrl = url; + if (paramStr) { + this.firstUrl += '?' + paramStr; + this.reconnUrl += '?' + paramStr + "&reconnect=true"; + } else { + this.reconnUrl += "?reconnect=true"; + } + + this.closeByUser = false; + this.lockReconnect = false; + this.reconnectCount = 0; + + // 最后连接时间 + this.lastConnectTime = new Date().getTime(); + // 重连时间 + this.reconnInterval = reconnInterval; + // 心跳时间 + this.heartbeatTimeout = heartbeatTimeout; + + this.ws = null; + + this.connect = function(isReconnect) { + // 这里连接的时候,先关闭,避免出现多个连接 + uni.closeSocket({ + success:() => { + this.ws = uni.connectSocket({ + url: this.firstUrl, + success(res) { + console.log("WebSocket成功关闭,连接成功") + }, + fail(err) { + console.log("WebSocket成功关闭,连接失败:" + err) + } + }); + }, + fail:() => { + this.ws = uni.connectSocket({ + url: this.firstUrl, + success(res) { + console.log("WebSocket关闭失败,连接成功") + }, + fail(err) { + console.log("WebSocket关闭失败,连接失败:" + err) + } + }); + } + }) + + this.ws.onOpen((e) => { + if(!isReconnect){ + uni.sendSocketMessage({ + data: JSON.stringify({code:1}) + }) + store.commit('CLEAN_MESSAGE', {}) + } + this.reset(); + }) + + store.commit('SET_SOCKET', this) + this.ws.onMessage((e) => { + let data = JSON.parse(e.data); + if(data.code == 2){ + store.commit('ADD_MESSAGE', data.message) + } + this.reset(); + }) + + this.ws.onClose((e) => { + console.error("WebSocket关闭了:" + JSON.stringify(e)) + this.clearAllTimeoutTask(); + }) + + this.ws.onError((e) => { + console.error("WebSocket错误了:" + JSON.stringify(e)) + this.clearAllTimeoutTask(); + if(!this.closeByUser){ + this.reconn(); + } + }) + + return this.ws + } + + this.reconn = () => { + // 重连次数,防止疯狂重连导致系统挂掉 + if(this.reconnectCount++ > 10){ return;} + // 防止多个方法调用,多处重连 + if (this.lockReconnect) { return;} + this.lockReconnect = true; + this.reconnIntervalTask = setTimeout(() => { + this.ws = this.connect(true) + this.lockReconnect = false; + }, this.reconnInterval) + } + + this.ping = () => { + uni.sendSocketMessage({ + data: JSON.stringify({code:0}) + }) + }; + + this.send = (data) => { + uni.sendSocketMessage({ + data: data + }) + }; + + this.close = (bool) => { + this.lockReconnect = false; + this.closeByUser = bool; + uni.closeSocket({ + success:() => { + console.info("WebSocket关闭成功") + } + }) + }; + + this.reset = () => { + this.clearAllTimeoutTask(); + // 重置重连次数 + this.reconnectCount = 0; + // 重置最后连接时间 + this.lastConnectTime = new Date().getTime(); + // 启动心跳任务 + this.pingIntervalTask = setTimeout(() => { + this.ping(); + }, this.heartbeatTimeout); + } + + this.clearAllTimeoutTask = () => { + // 清除重连任务 + if (this.reconnIntervalTask) { + clearTimeout(this.reconnIntervalTask); + } + // 清除心跳任务 + if(this.pingIntervalTask){ + clearTimeout(this.pingIntervalTask) + } + } + + this.getReadyState = () => { + // CONNECTING:值为0,表示正在连接。 + // OPEN:值为1,表示连接成功,可以通信了。 + // CLOSING:值为2,表示连接正在关闭。 + // CLOSED:值为3,表示连接已经关闭,或者打开连接失败。 + return this.ws.readyState; + } + + } +} + +/** + * 获取聊天唯一Key + * type 0-私聊,1-群里 + * chatId 聊天对象,好友ID或群聊ID + * fromId 发消息人ID + * +*/ +export function getChatKey(type, chatId, fromId) { + // 私聊 + if(type == 0){ + if(chatId*1 < fromId*1){ + return "im:message:friend-" + chatId + "-" + fromId + }else{ + return "im:message:friend-" + fromId + "-" + chatId + } + }else{ + return "im:message:group-" + chatId + } +} diff --git a/utils/cache.js b/utils/cache.js new file mode 100644 index 0000000..62c3ca1 --- /dev/null +++ b/utils/cache.js @@ -0,0 +1,26 @@ +const sessionCache = 'session-cache' +const localCache = 'local-cache' + +export function getSessionCache() { + return uni.getStorageSync(sessionCache) +} + +export function setSessionCache(cache) { + return uni.setStorageSync(sessionCache, cache) +} + +export function removeSessionCache() { + return uni.removeStorageSync(sessionCache) +} + +export function getLocalCache() { + return uni.getStorageSync(localCache) +} + +export function setLocalCache(cache) { + return uni.setStorageSync(localCache, cache) +} + +export function removeLocalCache() { + return uni.removeStorageSync(localCache) +} diff --git a/utils/constant.js b/utils/constant.js new file mode 100644 index 0000000..b75a236 --- /dev/null +++ b/utils/constant.js @@ -0,0 +1,8 @@ +const constant = { + avatar: 'vuex_avatar', + name: 'vuex_name', + userInfo: 'vuex_user_info', + loginInfo: 'vuex_login_info' +} + + export default constant diff --git a/utils/errorCode.js b/utils/errorCode.js new file mode 100644 index 0000000..d2111ee --- /dev/null +++ b/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/utils/frameTool.js b/utils/frameTool.js new file mode 100644 index 0000000..150a7ca --- /dev/null +++ b/utils/frameTool.js @@ -0,0 +1,15 @@ + +import * as nineTool from "@/utils/nineTool.js"; +import { diyApi, diyApiGet } from '@/utils/queryByDiy.js'; + +export default { + install(app) { + // 九云工具 + Object.keys(nineTool).forEach((key) => { + app.config.globalProperties[key] = nineTool[key]; + }); + // 自定义查询工具 + app.config.globalProperties.diyApi = diyApi + app.config.globalProperties.diyApiGet = diyApiGet + } +}; diff --git a/utils/nineTool.js b/utils/nineTool.js new file mode 100644 index 0000000..b8d13c8 --- /dev/null +++ b/utils/nineTool.js @@ -0,0 +1,348 @@ + +export function isNull(o) { + if(o === 0 || o === "0"){ + return false; + } + if(o == "undefined" || o == null || o == ""){ + return true; + } + return false; +} +export function isPhone(o) { + if(/^1[23456789]\d{9}$/.test(o)){ + return true; + } + return false; +} +export function isMail(o) { + if(/^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$/.test(o)){ + return true; + } + return false; +} +export function isNumber(value) { + return !isNaN(parseFloat(value)) && isFinite(value) +} +export function isLetter(o) { + if(/^[A-Za-z]+$/.test(o)){ + return true; + } + return false; +} +export function isNumberOrLetter(o) { + if(/^[A-Za-z0-9]+$/.test(o)){ + return true; + } + return false; +} + +// 日期格式化 +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +export function formatDate(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + + if (option) { + return parseTime(time, option) + } + + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } else if (diff < 3600 * 24 * 3) { + return '2天前' + } else if (diff < 3600 * 24 * 4) { + return '3天前' + } else if (diff < 3600 * 24 * 5) { + return '4天前' + } else if (diff < 3600 * 24 * 6) { + return '5天前' + } else if (diff < 3600 * 24 * 7) { + return '6天前' + } else if (diff < 3600 * 24 * 8) { + return '7天前' + } + if(diff < 3600 * 24 * 365) { + return ( + (d.getMonth()*1 + 1) + + '月' + + d.getDate() + + '日' + ) + } else { + return ( + d.getFullYear() + + '年' + + (d.getMonth()*1 + 1) + + '月' + ) + } +} + +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + + if (option) { + return parseTime(time, option) + } + + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + return ( + d.getFullYear() + + '-' + + ((d.getMonth()*1 + 1) + "").padStart(2,0) + + '-' + + (d.getDate() + '').padStart(2,0) + + ' ' + + (d.getHours() + '').padStart(2,0) + + ':' + + (d.getMinutes() + '').padStart(2,0) + + ':' + + (d.getSeconds() + '').padStart(2,0) + ) +} + +// number:要格式化的数字, +// decimals:保留几位小数, 默认0位 +// dec_point:小数点符号, 默认 . +// thousands_sep:千分位符号 默认 , +// tail_add: 小数点后面数据是否添加0补足位数, 默认空字符 +// null_default: 如果为空的值, 默认空字符 +function numberFormat(number, decimals, tail_add="", thousands_sep, dec_point, null_default="") { + number = (number + '').replace(/[^0-9+-Ee.]/g, ''); + var n = !isFinite(+number) ? 0 : +number, + prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), + sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, + dec = (typeof dec_point === 'undefined') ? '.' : dec_point, + s = '', + toFixedFix = function (n, prec) { + var k = Math.pow(10, prec); + return '' + Math.round(n * k) / k; + }; + + s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); + var re = /(-?\d+)(\d{3})/; + if(sep.length > 0){ + while (re.test(s[0])) { + s[0] = s[0].replace(re, "$1" + sep + "$2"); + } + } + if ((s[1] || '').length < prec) { + s[1] = s[1] || ''; + s[1] += new Array(prec - s[1].length + 1).join(tail_add); + } + if((s[1] || '').length == 0){ + return s[0] + } + return s.join(dec); +} +// number:要格式化的数字, +// decimals:保留几位小数, 默认0位 +// dec_point:小数点符号, 默认 . +// thousands_sep:千分位符号 默认 , +// tail_add: 小数点后面数据是否添加0补足位数, 默认空字符 +// null_default: 如果为空的值, 默认空字符 +export function formatNumber(number, decimals, tail_add, thousands_sep, dec_point, null_default) { + if(isNull(number) || isNull(String(number).trim())){return null_default;} + if(!isNumber(String(number).trim())){return number;} + number = String(number).trim(); + return numberFormat(number, decimals, tail_add, thousands_sep, dec_point, null_default); +} +// thousands_sep:千分位符号 默认空字符 +export function formatPercent(number, decimals, tail_add, thousands_sep="", dec_point, null_default) { + if(isNull(number) || isNull(String(number).trim().replaceAll(",", ""))){return null_default;} + if(!isNumber(String(number).trim().replaceAll(",", ""))){return number;} + number = String(number).trim().replaceAll(",", ""); + let value = numberFormat(number*100, decimals, tail_add, thousands_sep, dec_point, null_default); + if(value){ + return value + "%"; + } + return ""; +} + +// get brower +export function GetCurrentBrowser () { + let ua = navigator.userAgent.toLocaleLowerCase() + let browserType = null + if (ua.match(/msie/) != null || ua.match(/trident/) != null) { + browserType = 'IE' + } else if (ua.match(/firefox/) != null) { + browserType = 'firefox' + } else if (ua.match(/ucbrowser/) != null) { + browserType = 'UC' + } else if (ua.match(/opera/) != null || ua.match(/opr/) != null) { + browserType = 'opera' + } else if (ua.match(/bidubrowser/) != null) { + browserType = 'baidu' + } else if (ua.match(/metasr/) != null) { + browserType = 'sougou' + } else if (ua.match(/tencenttraveler/) != null || ua.match(/qqbrowse/) != null) { + browserType = 'QQ' + } else if (ua.match(/maxthon/) != null) { + browserType = 'maxthon' + } else if (ua.match(/chrome/) != null) { + var is360 = _mime('type', 'application/vnd.chromium.remoting-viewer') + if (is360) { + browserType = '360' + } else { + browserType = 'chrome' + } + } else if (ua.match(/safari/) != null) { + browserType = 'Safari' + } else { + browserType = 'others' + } + return browserType +} + +function _mime (option, value) { + var mimeTypes = navigator.mimeTypes + for (var mt in mimeTypes) { + if (mimeTypes[mt][option] === value) { + return true + } + } + return false +} + +// get os +export function GetOs () { + let sUserAgent = navigator.userAgent.toLocaleLowerCase() + let isWin = (navigator.platform.toLocaleLowerCase() == 'win32') || (navigator.platform.toLocaleLowerCase() === 'windows') + let isMac = (navigator.platform.toLocaleLowerCase() === 'mac68k') || (navigator.platform.toLocaleLowerCase() === 'macppc') + || (navigator.platform === 'macintosh') || (navigator.platform.toLocaleLowerCase() === 'macintel') + if (isMac) return 'Mac' + var isUnix = (navigator.platform === 'x11') && !isWin && !isMac + if (isUnix) return 'Unix' + var isLinux = (String(navigator.platform.toLocaleLowerCase()).indexOf('linux') > -1) + if (isLinux) return 'Linux' + if (isWin) { + var isWin2K = sUserAgent.indexOf('windows nt 5.0') > -1 || sUserAgent.indexOf('windows 2000') > -1 + if (isWin2K) return 'Win2000' + var isWinXP = sUserAgent.indexOf('windows nt 5.1') > -1 || sUserAgent.indexOf('windows xp') > -1 + if (isWinXP) return 'WinXP' + var isWin2003 = sUserAgent.indexOf('windows nt 5.2') > -1 || sUserAgent.indexOf('windows 2003') > -1 + if (isWin2003) return 'Win2003' + var isWinVista = sUserAgent.indexOf('windows nt 6.0') > -1 || sUserAgent.indexOf('windows vista') > -1 + if (isWinVista) return 'WinVista' + var isWin7 = sUserAgent.indexOf('windows nt 6.1') > -1 || sUserAgent.indexOf('windows 7') > -1 + if (isWin7) return 'Win7' + var isWin8 = sUserAgent.indexOf('windows nt 6.2') > -1 || sUserAgent.indexOf('windows 8') > -1 + if (isWin8) return 'Win8' + var isWin10 = sUserAgent.indexOf('windows nt 10.0') > -1 || sUserAgent.indexOf('windows nt 6.4') > -1 || sUserAgent.indexOf('windows 10') > -1 + if (isWin10) return 'Win10' + var isSimulator = sUserAgent.indexOf('linux') > -1 && sUserAgent.indexOf('android') > -1 + if (isSimulator) return 'Win手机模拟器' + return navigator.platform + } + if (sUserAgent.indexOf('android') > -1) return 'Android' + if (sUserAgent.indexOf('iphone') > -1) return 'iPhone' + if (sUserAgent.indexOf('symbianos') > -1) return 'SymbianOS' + if (sUserAgent.indexOf('windows phone') > -1) return 'Windows Phone' + if (sUserAgent.indexOf('ipad') > -1) return 'iPad' + if (sUserAgent.indexOf('ipod') > -1) return 'iPod' + return navigator.platform +} + +export function getRandom(len){ + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return data.substr(index, len); +} + +export function getLongRandom(len){ + if(len <= 16){ + return getRandom(len) + } + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return parseTime(Date.now(), '{y}{m}{d}{h}{i}{s}') + "" + data.substr(index, len-16); +} + +export function moveInArray(array, fromIndex, toIndex) { + const element = array.splice(fromIndex, 1)[0]; + array.splice(toIndex, 0, element); +} + +export function jsonCharBigInt(s){ + if(typeof s !== 'string'){ + return s + } + let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g + return s.replaceAll(re, "$1$2$1$3$1") +} + +export function jsonParse(s){ + if(typeof s !== 'string'){ + return s + } + let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g + return JSON.parse(s.replaceAll(re, "$1$2$1$3$1")) +} \ No newline at end of file diff --git a/utils/nodeId.js b/utils/nodeId.js new file mode 100644 index 0000000..cceab2e --- /dev/null +++ b/utils/nodeId.js @@ -0,0 +1,13 @@ +const NodeIdKey = 'App-Node-Id' + +export function getNodeId() { + return uni.getStorageSync(NodeIdKey) +} + +export function setNodeId(nodeId) { + return uni.setStorageSync(NodeIdKey, nodeId) +} + +export function removeNodeId() { + return uni.removeStorageSync(NodeIdKey) +} diff --git a/utils/queryByDiy.js b/utils/queryByDiy.js new file mode 100644 index 0000000..bbc19ed --- /dev/null +++ b/utils/queryByDiy.js @@ -0,0 +1,17 @@ +import request from '@/utils/request' + +export function diyApi(url, data = {}, method = "POST", contentType = 'json') { + return request({ + 'url': url, + 'method': method, + 'data': data + }) +} + +export function diyApiGet(url, data = {}, method = "GET", contentType = 'json') { + return request({ + 'url': url, + 'method': method, + 'params': data + }) +} \ No newline at end of file diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..37bf244 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,106 @@ +import store from '@/store' +import { getToken } from '@/utils/token' +import errorCode from '@/utils/errorCode' +import { getSessionCache, setSessionCache } from '@/utils/cache' +import { toast, showConfirm, tansParams } from '@/utils/requestTool' + +let timeout = 10000 +const baseUrl = import.meta.env.VITE_APP_BASE_URL + +const request = config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false + config.header = config.header || {} + if (getToken() && !isToken) { + config.header['Authorization'] = 'Vrapile ' + getToken() + } + // get请求映射params参数 + if (config.params) { + let url = config.url + '?' + tansParams(config.params) + url = url.slice(0, -1) + config.url = url + } + if (!isRepeatSubmit) { + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const sessionObj = getSessionCache() + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + setSessionCache(requestObj) + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '数据正在处理,请勿重复提交:' + s_url; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + setSessionCache(requestObj) + } + } + } + return new Promise((resolve, reject) => { + uni.request({ + method: config.method || 'get', + timeout: config.timeout || timeout, + url: config.baseUrl || baseUrl + config.url, + data: config.data, + header: config.header, + dataType: 'json' + }).then(res => { + const code = res.data.code || res.data.status || 200 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + + if (code === 401) { + // 密码登录的,实现自动重新登录 + let loginInfo = store.state.user.loginInfo; + if(loginInfo && loginInfo.loginType == 0){ + store.dispatch('Login', { + loginType: loginInfo.loginType, + userName: loginInfo.userName, + password: loginInfo.password, + registerFlag: "N" + }).then(() => { + store.dispatch('GetInfo'); + }) + reject('无效的会话,或者会话已过期,已重新登录。') + }else{ + showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + if (res.confirm) { + uni.reLaunch({ url: '/pages/user/login' }) + } + }) + reject('无效的会话,或者会话已过期,请重新登录。') + } + } else if (code === 500) { + toast(msg) + reject('500') + } else if (code !== 200) { + toast(msg) + reject(code) + } + resolve(res.data) + }).catch(error => { + let { message } = error + if (message && message === 'Network Error') { + message = '后端接口连接异常' + } else if (message && message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message && message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常' + }else{ + message = '系统繁忙' + } + toast(message) + reject(error) + }) + }) +} + +export default request diff --git a/utils/requestTool.js b/utils/requestTool.js new file mode 100644 index 0000000..00d4137 --- /dev/null +++ b/utils/requestTool.js @@ -0,0 +1,54 @@ +/** +* 显示消息提示框 +* @param content 提示的标题 +*/ +export function toast(content) { + uni.showToast({ + icon: 'none', + title: content + }) +} + +/** +* 显示模态弹窗 +* @param content 提示的标题 +*/ +export function showConfirm(content) { + return new Promise((resolve, reject) => { + uni.showModal({ + title: '提示', + content: content, + cancelText: '取消', + confirmText: '确定', + success: function(res) { + resolve(res) + } + }) + }) +} + +/** +* 参数处理 +* @param params 参数 +*/ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName] + var part = encodeURIComponent(propName) + "=" + if (value !== null && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']' + var subPart = encodeURIComponent(params) + "=" + result += subPart + encodeURIComponent(value[key]) + "&" + } + } + } else { + result += part + encodeURIComponent(value) + "&" + } + } + } + return result +} \ No newline at end of file diff --git a/utils/storage.js b/utils/storage.js new file mode 100644 index 0000000..1ab33d1 --- /dev/null +++ b/utils/storage.js @@ -0,0 +1,32 @@ +import constant from './constant' + +// 存储变量名 +let storageKey = 'storage_data' + +// 存储节点变量名 +let storageNodeKeys = [constant.avatar, constant.name, constant.userInfo, constant.loginInfo] + +const storage = { + set: function(key, value) { + if (storageNodeKeys.indexOf(key) != -1) { + let tmp = uni.getStorageSync(storageKey) + tmp = tmp ? tmp : {} + tmp[key] = value + uni.setStorageSync(storageKey, tmp) + } + }, + get: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + return storageData[key] || "" + }, + remove: function(key) { + let storageData = uni.getStorageSync(storageKey) || {} + delete storageData[key] + uni.setStorageSync(storageKey, storageData) + }, + clean: function() { + uni.removeStorageSync(storageKey) + } +} + +export default storage diff --git a/utils/token.js b/utils/token.js new file mode 100644 index 0000000..9a7cc04 --- /dev/null +++ b/utils/token.js @@ -0,0 +1,13 @@ +const TokenKey = 'App-Token' + +export function getToken() { + return uni.getStorageSync(TokenKey) +} + +export function setToken(token) { + return uni.setStorageSync(TokenKey, token) +} + +export function removeToken() { + return uni.removeStorageSync(TokenKey) +}