diff --git a/package.json b/package.json index 68f3e363..4240893a 100644 --- a/package.json +++ b/package.json @@ -58,12 +58,12 @@ "luch-request": "^3.0.8", "pinia": "^2.0.33", "pinia-plugin-persist-uni": "^1.2.0", - "vue": "^3.4.21", - "vue-i18n": "^9.1.9", - "weixin-js-sdk": "^1.6.0", "pinyin-pro": "^3.23.1", "quill": "^1.3.7", - "quill-image-resize-mp": "^3.0.1" + "quill-image-resize-mp": "^3.0.1", + "vue": "^3.4.21", + "vue-i18n": "^9.1.9", + "weixin-js-sdk": "^1.6.0" }, "devDependencies": { "@dcloudio/types": "^3.4.8", diff --git a/src/.env.js b/src/.env.js deleted file mode 100644 index c9e42cfd..00000000 --- a/src/.env.js +++ /dev/null @@ -1,25 +0,0 @@ -//设置环境(打包前修改此变量) -const ENV = "DEV"; -const UNI_APP = {}; -// 表情包路径 -UNI_APP.EMO_URL = "/static/emoji/"; -// #ifdef MP-WEIXIN -// 微信小程序的本地表情包经常莫名失效,建议将表情放到服务器中 -// UNI_APP.EMO_URL = "https://www.boxim.online/emoji/"; -// #endif - -if (ENV == "DEV") { - UNI_APP.BASE_URL = "http://chatsever.zianxin.com"; - // UNI_APP.BASE_URL = "https://www.boxim.online/api"; - UNI_APP.WS_URL = "ws://chatapp.zianxin.com/im"; - // UNI_APP.WS_URL = "wss://www.boxim.online/im"; - // H5 走本地代理解决跨域问题 - // #ifdef H5 - UNI_APP.BASE_URL = "/api"; - // #endif -} -if (ENV == "PROD") { - UNI_APP.BASE_URL = "https://www.boxim.online/api"; - UNI_APP.WS_URL = "wss://www.boxim.online/im"; -} -export default UNI_APP; diff --git a/src/App.vue b/src/App.vue index b10ac82c..d4a3e3f6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,13 +2,16 @@ import { onLaunch, onShow, onError } from '@dcloudio/uni-app'; import { ShoproInit } from './sheep'; import RecentApi from './sheep/api/member/recent'; + + // 与聊天相关的导入 import http from './common/request'; import * as msgType from './common/messageType'; import * as enums from './common/enums'; import * as wsApi from './common/wssocket'; - import UNI_APP from '@/.env.js'; + import CHAT_ENV from '@/chat-env.js'; export default { + /** ↓↓↓ 以下为app启动聊天相关模块初始化,WebSocket链接,加载聊天消息,加载离线消息,加载群组消息,初始化聊天相关的全局状态仓库 */ data() { return { isExit: false, // 是否已退出 @@ -20,8 +23,6 @@ }, methods: { init() { - console.log('xxxc'); - this.reconnecting = false; this.isExit = false; // 加载数据 @@ -37,7 +38,7 @@ }, initWebSocket() { let loginInfo = uni.getStorageSync('loginInfo'); - wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken); + wsApi.connect(CHAT_ENV.WS_URL, loginInfo.accessToken); wsApi.onConnect(() => { if (this.reconnecting) { // 重连成功 @@ -87,8 +88,6 @@ }); }, loadStore() { - console.log(this.userStore); - return this.userStore.loadUser().then(() => { const promises = []; promises.push(this.friendStore.loadFriend()); @@ -200,9 +199,9 @@ // 单人视频信令 if (msgType.isRtcPrivate(msg.type)) { // #ifdef MP-WEIXIN - // 小程序不支持音视频 - return; + return; // 小程序不支持音视频 // #endif + // 被呼叫,弹出视频页面 let delayTime = 100; if ( @@ -315,9 +314,9 @@ // 群视频信令 if (msgType.isRtcGroup(msg.type)) { // #ifdef MP-WEIXIN - // 小程序不支持音视频 - return; + return; // 小程序不支持音视频 // #endif + // 被呼叫,弹出视频页面 let delayTime = 100; if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) { @@ -404,6 +403,7 @@ // this.audioTip.src = "/static/audio/tip.wav"; // this.audioTip.play(); }, + // 刷新token refreshToken(loginInfo) { return new Promise((resolve, reject) => { if (!loginInfo || !loginInfo.refreshToken) { @@ -443,7 +443,7 @@ }); // 重新连接 let loginInfo = uni.getStorageSync('loginInfo'); - wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken); + wsApi.reconnect(CHAT_ENV.WS_URL, loginInfo.accessToken); }) .catch(() => { // 5s后重试 @@ -483,6 +483,8 @@ // #endif }, }, + /** ↑↑↑ 以上为app启动聊天相关模块初始化,WebSocket链接,加载聊天消息,加载离线消息,加载群组消息,初始化聊天相关的全局状态仓库 */ + onLaunch() { // 隐藏原生导航栏 使用自定义底部导航 // uni.hideTabBar({ @@ -490,7 +492,7 @@ // }); // 加载Shopro底层依赖 ShoproInit(); - // 更新用户位置 + // app启动时更新用户位置 uni.getLocation({ success: (res) => { const params = { @@ -505,8 +507,7 @@ }); this.$mountStore(); - // 延迟1s,避免用户看到页面跳转 - this.closeSplashscreen(1000); + this.closeSplashscreen(1000); // 延迟1s,避免用户看到页面跳转 uni.setStorageSync('loginInfo', { accessToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyIiwiZXhwIjoxNzY0MDU5ODk2LCJpbmZvIjoie1wibmlja05hbWVcIjpcInd3d1wiLFwidGVybWluYWxcIjoxLFwidXNlcklkXCI6MixcInVzZXJOYW1lXCI6XCJ3d3dcIn0ifQ.xBfQJg6FFHQGzkK_IUGZUjVN8g5tex3VtWsTr1gGjzg', @@ -519,21 +520,13 @@ let loginInfo = uni.getStorageSync('loginInfo'); this.refreshToken(loginInfo) .then(() => { - // #ifdef H5 - // 跳转到聊天页 - uni.switchTab({ - url: '/pages/message/message', - }); - // #endif - // 初始化 + // 聊天初始化 this.init(); this.closeSplashscreen(0); }) .catch(() => { // 跳转到登录页 - // uni.navigateTo({ - // url: '/pages/login/login', - // }); + uni.redirectTo({ url: '/pages/login/login' }); }); }, onShow() { @@ -554,6 +547,35 @@ diff --git a/src/chat-env.js b/src/chat-env.js new file mode 100644 index 00000000..353b4a4c --- /dev/null +++ b/src/chat-env.js @@ -0,0 +1,22 @@ +const ENV = 'DEV'; //设置环境(打包前修改此变量) + +const CHAT_ENV = {}; + +if (ENV == 'DEV') { + CHAT_ENV.BASE_URL = 'http://chatsever.zianxin.com'; + // CHAT_ENV.BASE_URL = "https://www.boxim.online/api"; + CHAT_ENV.WS_URL = 'ws://chatapp.zianxin.com/im'; + // CHAT_ENV.WS_URL = "wss://www.boxim.online/im"; + + // H5 走本地代理解决跨域问题 + // #ifdef H5 + CHAT_ENV.BASE_URL = '/api'; + // #endif +} + +if (ENV == 'PROD') { + CHAT_ENV.BASE_URL = 'https://www.boxim.online/api'; + CHAT_ENV.WS_URL = 'wss://www.boxim.online/im'; +} + +export default CHAT_ENV; diff --git a/src/store/chatStore.js b/src/chat-store/chatStore.js similarity index 100% rename from src/store/chatStore.js rename to src/chat-store/chatStore.js diff --git a/src/store/configStore.js b/src/chat-store/configStore.js similarity index 100% rename from src/store/configStore.js rename to src/chat-store/configStore.js diff --git a/src/store/friendStore.js b/src/chat-store/friendStore.js similarity index 100% rename from src/store/friendStore.js rename to src/chat-store/friendStore.js diff --git a/src/store/groupStore.js b/src/chat-store/groupStore.js similarity index 100% rename from src/store/groupStore.js rename to src/chat-store/groupStore.js diff --git a/src/store/userStore.js b/src/chat-store/userStore.js similarity index 100% rename from src/store/userStore.js rename to src/chat-store/userStore.js diff --git a/src/common/emotion.js b/src/common/emotion.js index f7dfe374..a79d571b 100644 --- a/src/common/emotion.js +++ b/src/common/emotion.js @@ -1,43 +1,98 @@ -import UNI_APP from '@/.env.js' +const EMO_URL = '/static/emoji/'; +// #ifdef MP-WEIXIN +// 微信小程序的本地表情包经常莫名失效,建议将表情放到服务器中 +// CHAT_ENV.EMO_URL = "https://www.boxim.online/emoji/"; +// #endif - -const emoTextList = ['憨笑', '媚眼', '开心', '坏笑', '可怜', '爱心', '笑哭', '拍手', '惊喜', '打气', - '大哭', '流泪', '饥饿', '难受', '健身', '示爱', '色色', '眨眼', '暴怒', '惊恐', - '思考', '头晕', '大吐', '酷笑', '翻滚', '享受', '鼻涕', '快乐', '雀跃', '微笑', - '贪婪', '红心', '粉心', '星星', '大火', '眼睛', '音符', "叹号", "问号", "绿叶", - "燃烧", "喇叭", "警告", "信封", "房子", "礼物", "点赞", "举手", "拍手", "点头", - "摇头", "偷瞄", "庆祝", "疾跑", "打滚", "惊吓", "起跳" +const emoTextList = [ + '憨笑', + '媚眼', + '开心', + '坏笑', + '可怜', + '爱心', + '笑哭', + '拍手', + '惊喜', + '打气', + '大哭', + '流泪', + '饥饿', + '难受', + '健身', + '示爱', + '色色', + '眨眼', + '暴怒', + '惊恐', + '思考', + '头晕', + '大吐', + '酷笑', + '翻滚', + '享受', + '鼻涕', + '快乐', + '雀跃', + '微笑', + '贪婪', + '红心', + '粉心', + '星星', + '大火', + '眼睛', + '音符', + '叹号', + '问号', + '绿叶', + '燃烧', + '喇叭', + '警告', + '信封', + '房子', + '礼物', + '点赞', + '举手', + '拍手', + '点头', + '摇头', + '偷瞄', + '庆祝', + '疾跑', + '打滚', + '惊吓', + '起跳', ]; const regex = /\#[\u4E00-\u9FA5]{1,3}\;/gi; let containEmoji = (content) => { - return regex.test(content) -} + return regex.test(content); +}; let transform = (content, extClass) => { - return content.replace(regex, (emoText)=>{ - // 将匹配结果替换表情图片 - let word = emoText.replace(/\#|\;/gi, ''); - let idx = emoTextList.indexOf(word); - if (idx == -1) { - return emoText; - } - let path = textToPath(emoText); - let img = ``; - return img; - }); -} + return content.replace(regex, (emoText) => { + // 将匹配结果替换表情图片 + let word = emoText.replace(/\#|\;/gi, ''); + let idx = emoTextList.indexOf(word); + if (idx == -1) { + return emoText; + } + let path = textToPath(emoText); + let img = ``; + return img; + }); +}; let textToPath = (emoText) => { - let word = emoText.replace(/\#|\;/gi, ''); - let idx = emoTextList.indexOf(word); - return UNI_APP.EMO_URL + idx + ".gif"; -} + let word = emoText.replace(/\#|\;/gi, ''); + let idx = emoTextList.indexOf(word); + return EMO_URL + idx + '.gif'; +}; export default { - containEmoji, - emoTextList, - transform, - textToPath -} \ No newline at end of file + containEmoji, + emoTextList, + transform, + textToPath, +}; diff --git a/src/common/enums.js b/src/common/enums.js index fa7ada08..505e9065 100644 --- a/src/common/enums.js +++ b/src/common/enums.js @@ -1,70 +1,64 @@ - const MESSAGE_TYPE = { - TEXT: 0, - IMAGE: 1, - FILE: 2, - AUDIO: 3, - VIDEO: 4, - RECALL: 10, - READED: 11, - RECEIPT: 12, - TIP_TIME: 20, - TIP_TEXT: 21, - LOADING: 30, - ACT_RT_VOICE: 40, - ACT_RT_VIDEO: 41, - USER_BANNED: 50, - FRIEND_NEW: 80, - FRIEND_DEL: 81, - FRIEND_DND: 82, - GROUP_NEW: 90, - GROUP_DEL: 91, - GROUP_DND: 92, - RTC_CALL_VOICE: 100, - RTC_CALL_VIDEO: 101, - RTC_ACCEPT: 102, - RTC_REJECT: 103, - RTC_CANCEL: 104, - RTC_FAILED: 105, - RTC_HANDUP: 106, - RTC_CANDIDATE: 107, - RTC_GROUP_SETUP: 200, - RTC_GROUP_ACCEPT: 201, - RTC_GROUP_REJECT: 202, - RTC_GROUP_FAILED: 203, - RTC_GROUP_CANCEL: 204, - RTC_GROUP_QUIT: 205, - RTC_GROUP_INVITE: 206, - RTC_GROUP_JOIN: 207, - RTC_GROUP_OFFER: 208, - RTC_GROUP_ANSWER: 209, - RTC_GROUP_CANDIDATE: 210, - RTC_GROUP_DEVICE: 211 -} + TEXT: 0, + IMAGE: 1, + FILE: 2, + AUDIO: 3, + VIDEO: 4, + RECALL: 10, + READED: 11, + RECEIPT: 12, + TIP_TIME: 20, + TIP_TEXT: 21, + LOADING: 30, + ACT_RT_VOICE: 40, + ACT_RT_VIDEO: 41, + USER_BANNED: 50, + FRIEND_NEW: 80, + FRIEND_DEL: 81, + FRIEND_DND: 82, + GROUP_NEW: 90, + GROUP_DEL: 91, + GROUP_DND: 92, + RTC_CALL_VOICE: 100, + RTC_CALL_VIDEO: 101, + RTC_ACCEPT: 102, + RTC_REJECT: 103, + RTC_CANCEL: 104, + RTC_FAILED: 105, + RTC_HANDUP: 106, + RTC_CANDIDATE: 107, + RTC_GROUP_SETUP: 200, + RTC_GROUP_ACCEPT: 201, + RTC_GROUP_REJECT: 202, + RTC_GROUP_FAILED: 203, + RTC_GROUP_CANCEL: 204, + RTC_GROUP_QUIT: 205, + RTC_GROUP_INVITE: 206, + RTC_GROUP_JOIN: 207, + RTC_GROUP_OFFER: 208, + RTC_GROUP_ANSWER: 209, + RTC_GROUP_CANDIDATE: 210, + RTC_GROUP_DEVICE: 211, +}; const USER_STATE = { - OFFLINE: 0, - FREE: 1, - BUSY: 2 -} + OFFLINE: 0, + FREE: 1, + BUSY: 2, +}; const TERMINAL_TYPE = { - WEB: 0, - APP: 1 -} + WEB: 0, + APP: 1, +}; const MESSAGE_STATUS = { - FAILED: -2, // 发送失败 - SENDING: -1, // 发送中(消息没到服务器) - PENDING: 0, // 未送达(消息已到服务器,但对方没收到) - DELIVERED: 1, // 已送达(对方已收到,但是未读消息) - RECALL: 2, // 已撤回 - READED: 3, // 消息已读 -} + FAILED: -2, // 发送失败 + SENDING: -1, // 发送中(消息没到服务器) + PENDING: 0, // 未送达(消息已到服务器,但对方没收到) + DELIVERED: 1, // 已送达(对方已收到,但是未读消息) + RECALL: 2, // 已撤回 + READED: 3, // 消息已读 +}; -export { - MESSAGE_TYPE, - USER_STATE, - TERMINAL_TYPE, - MESSAGE_STATUS -} +export { MESSAGE_TYPE, USER_STATE, TERMINAL_TYPE, MESSAGE_STATUS }; diff --git a/src/common/messageType.js b/src/common/messageType.js index f6b1cafc..289b6a38 100644 --- a/src/common/messageType.js +++ b/src/common/messageType.js @@ -1,40 +1,31 @@ - // 是否普通消息 let isNormal = function (type) { - return type >= 0 && type < 10; -} + return type >= 0 && type < 10; +}; // 是否状态消息 let isStatus = function (type) { - return type >= 10 && type < 20; -} + return type >= 10 && type < 20; +}; // 是否提示消息 let isTip = function (type) { - return type >= 20 && type < 30; -} + return type >= 20 && type < 30; +}; // 操作交互类消息 let isAction = function (type) { - return type >= 40 && type < 50; -} + return type >= 40 && type < 50; +}; // 单人通话信令 let isRtcPrivate = function (type) { - return type >= 100 && type < 200; -} + return type >= 100 && type < 200; +}; // 多人通话信令 let isRtcGroup = function (type) { - return type >= 200 && type < 300; -} + return type >= 200 && type < 300; +}; - -export { - isNormal, - isStatus, - isTip, - isAction, - isRtcPrivate, - isRtcGroup -} \ No newline at end of file +export { isNormal, isStatus, isTip, isAction, isRtcPrivate, isRtcGroup }; diff --git a/src/common/recorder-app.js b/src/common/recorder-app.js index f114bbb3..389e5b65 100644 --- a/src/common/recorder-app.js +++ b/src/common/recorder-app.js @@ -1,67 +1,61 @@ -import UNI_APP from '@/.env.js'; +import CHAT_ENV from '@/chat-env.js'; const rc = uni.getRecorderManager(); // 录音开始时间 let startTime = null; -let checkIsEnable = ()=>{ - return true; -} +let checkIsEnable = () => { + return true; +}; let start = () => { - return new Promise((resolve, reject) => { - rc.onStart(() => { - startTime = new Date(); - resolve() - }); - rc.onError((e) => { - console.log(e); - reject(e) - }) - rc.start({ - format: 'mp3' // 录音格式,可选值:aac/mp3 - }); - }) -} + return new Promise((resolve, reject) => { + rc.onStart(() => { + startTime = new Date(); + resolve(); + }); + rc.onError((e) => { + console.log(e); + reject(e); + }); + rc.start({ + format: 'mp3', // 录音格式,可选值:aac/mp3 + }); + }); +}; let close = () => { - rc.stop(); -} + rc.stop(); +}; let upload = () => { - return new Promise((resolve, reject) => { - rc.onStop((wavFile, a, b) => { - uni.uploadFile({ - url: UNI_APP.BASE_URL + '/file/upload', - header: { - accessToken: uni.getStorageSync("loginInfo").accessToken - }, - filePath: wavFile.tempFilePath, - name: 'file', - success: (res) => { - let r = JSON.parse(res.data); - if (r.code != 200) { - reject(r.message); - } else { - const duration = (new Date().getTime() - startTime.getTime()) / - 1000 - const data = { - duration: Math.round(duration), - url: r.data - } - resolve(data); - } - }, - fail: (e) => { - reject(e); - } - }) - }); - }) -} + return new Promise((resolve, reject) => { + rc.onStop((wavFile, a, b) => { + uni.uploadFile({ + url: CHAT_ENV.BASE_URL + '/file/upload', + header: { + accessToken: uni.getStorageSync('loginInfo').accessToken, + }, + filePath: wavFile.tempFilePath, + name: 'file', + success: (res) => { + let r = JSON.parse(res.data); + if (r.code != 200) { + reject(r.message); + } else { + const duration = (new Date().getTime() - startTime.getTime()) / 1000; + const data = { + duration: Math.round(duration), + url: r.data, + }; + resolve(data); + } + }, + fail: (e) => { + reject(e); + }, + }); + }); + }); +}; -export { - checkIsEnable, - start, - close, - upload -} \ No newline at end of file +export { checkIsEnable, start, close, upload }; diff --git a/src/common/recorder-h5.js b/src/common/recorder-h5.js index 38559426..a82b3e8c 100644 --- a/src/common/recorder-h5.js +++ b/src/common/recorder-h5.js @@ -1,92 +1,89 @@ -import UNI_APP from '@/.env.js'; +import CHAT_ENV from '@/chat-env.js'; let rc = null; let duration = 0; let chunks = []; let stream = null; -let startTime = null; +let startTime = null; let checkIsEnable = () => { - if (origin.indexOf('https') === -1 && origin.indexOf('localhost') === -1 && - origin.indexOf('127.0.0.1') === -1) { - uni.showToast({ - title: '请在https环境中使用录音功能', - icon: 'error' - }) - return false; - } - if (!navigator.mediaDevices || !window.MediaRecorder) { - uni.showToast({ - title: '当前浏览器不支持录音', - icon: 'error' - }) - return false; - } - return true; -} + if ( + origin.indexOf('https') === -1 && + origin.indexOf('localhost') === -1 && + origin.indexOf('127.0.0.1') === -1 + ) { + uni.showToast({ + title: '请在https环境中使用录音功能', + icon: 'error', + }); + return false; + } + if (!navigator.mediaDevices || !window.MediaRecorder) { + uni.showToast({ + title: '当前浏览器不支持录音', + icon: 'error', + }); + return false; + } + return true; +}; let start = () => { - return navigator.mediaDevices.getUserMedia({ audio: true }).then(audioStream => { - startTime = new Date().getTime(); - chunks = []; - stream = audioStream; - rc = new MediaRecorder(stream) - rc.start() - }) -} + return navigator.mediaDevices.getUserMedia({ audio: true }).then((audioStream) => { + startTime = new Date().getTime(); + chunks = []; + stream = audioStream; + rc = new MediaRecorder(stream); + rc.start(); + }); +}; let close = () => { - stream.getTracks().forEach((track) => { - track.stop() - }) - rc.stop() -} - + stream.getTracks().forEach((track) => { + track.stop(); + }); + rc.stop(); +}; let upload = () => { - return new Promise((resolve, reject) => { - rc.ondataavailable = (e) => { - chunks.push(e.data) - } - rc.onstop = () => { - if(!chunks[0].size){ - chunks = []; - return; - } - duration = (new Date().getTime() - startTime) / 1000; - const newbolb = new Blob(chunks, { 'type': 'audio/mpeg' }); - const name = new Date().getDate() + '.mp3'; - const file = new File([newbolb], name) - uni.uploadFile({ - url: UNI_APP.BASE_URL + '/file/upload', - header: { - accessToken: uni.getStorageSync("loginInfo").accessToken - }, - file: file, - name: 'file', - success: (res) => { - let r = JSON.parse(res.data); - if (r.code != 200) { - console.log(res) - reject(r.message); - } else { - const data = { - duration: parseInt(duration), - url: r.data - } - resolve(data); - } - }, - fail: (e) => { - reject(e); - } - }) - } - }) -} + return new Promise((resolve, reject) => { + rc.ondataavailable = (e) => { + chunks.push(e.data); + }; + rc.onstop = () => { + if (!chunks[0].size) { + chunks = []; + return; + } + duration = (new Date().getTime() - startTime) / 1000; + const newbolb = new Blob(chunks, { type: 'audio/mpeg' }); + const name = new Date().getDate() + '.mp3'; + const file = new File([newbolb], name); + uni.uploadFile({ + url: CHAT_ENV.BASE_URL + '/file/upload', + header: { + accessToken: uni.getStorageSync('loginInfo').accessToken, + }, + file: file, + name: 'file', + success: (res) => { + let r = JSON.parse(res.data); + if (r.code != 200) { + console.log(res); + reject(r.message); + } else { + const data = { + duration: parseInt(duration), + url: r.data, + }; + resolve(data); + } + }, + fail: (e) => { + reject(e); + }, + }); + }; + }); +}; -export { - checkIsEnable, - start, - close, - upload -} \ No newline at end of file +export { checkIsEnable, start, close, upload }; diff --git a/src/common/request.js b/src/common/request.js index 83f8e429..38c41d86 100644 --- a/src/common/request.js +++ b/src/common/request.js @@ -1,4 +1,4 @@ -import UNI_APP from '@/.env.js'; +import CHAT_ENV from '@/chat-env.js'; // 请求队列 let requestList = []; @@ -13,8 +13,7 @@ const request = (options) => { } return new Promise(function (resolve, reject) { uni.request({ - url: UNI_APP.BASE_URL + options.url, - // url: UNI_APP.BASE_URL + options.url, + url: CHAT_ENV.BASE_URL + options.url, method: options.method || 'GET', header: header, data: options.data || {}, @@ -75,7 +74,7 @@ const reqRefreshToken = (loginInfo) => { return new Promise(function (resolve, reject) { uni.request({ method: 'PUT', - url: UNI_APP.BASE_URL + '/refreshToken', + url: CHAT_ENV.BASE_URL + '/refreshToken', header: { refreshToken: loginInfo.refreshToken, }, diff --git a/src/common/str.js b/src/common/str.js index 3f6de923..e69fb11e 100644 --- a/src/common/str.js +++ b/src/common/str.js @@ -1,14 +1,14 @@ let html2Escape = (strText) => { - return strText.replace(/[<>&"]/g, function(c) { - return { - '<': '<', - '>': '>', - '&': '&', - '"': '"' - } [c]; - }); -} + return strText.replace(/[<>&"]/g, function (c) { + return { + '<': '<', + '>': '>', + '&': '&', + '"': '"', + }[c]; + }); +}; export default { - html2Escape -} \ No newline at end of file + html2Escape, +}; diff --git a/src/common/url.js b/src/common/url.js index c95d8341..ccdf9410 100644 --- a/src/common/url.js +++ b/src/common/url.js @@ -1,23 +1,22 @@ - // 使用正则表达式匹配更广泛的URL格式(此正则由deepseek生成) -const regex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]|\bwww\.[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; - -let containUrl = (content) => { - return regex.test(content) -} +const regex = + /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]|\bwww\.[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi; +let containUrl = (content) => { + return regex.test(content); +}; let replaceURLWithHTMLLinks = (content, color) => { - return content.replace(regex, (url) => { - // 如果URL不以http(s)://开头,则添加http://前缀 - if (!url.startsWith("http")) { - url = "http://" + url; - } - return `${url}`; - }); -} + return content.replace(regex, (url) => { + // 如果URL不以http(s)://开头,则添加http://前缀 + if (!url.startsWith('http')) { + url = 'http://' + url; + } + return `${url}`; + }); +}; export default { - containUrl, - replaceURLWithHTMLLinks -} \ No newline at end of file + containUrl, + replaceURLWithHTMLLinks, +}; diff --git a/src/common/wssocket.js b/src/common/wssocket.js index 5747dc55..44891d4a 100644 --- a/src/common/wssocket.js +++ b/src/common/wssocket.js @@ -1,4 +1,4 @@ -let accessToken = ""; +let accessToken = ''; let messageCallBack = null; let closeCallBack = null; let connectCallBack = null; @@ -8,147 +8,135 @@ let lastConnectTime = new Date(); // 最后一次连接时间 let socketTask = null; let connect = (wsurl, token) => { - accessToken = token; - if (isConnect) { - return; - } - lastConnectTime = new Date(); - socketTask = uni.connectSocket({ - url: wsurl, - success: (res) => {}, - fail: (e) => { - console.log(e); - console.log("WebSocket连接失败,10s后重连"); - setTimeout(() => { - connect(); - }, 10000) - } - }); + accessToken = token; + if (isConnect) { + return; + } + lastConnectTime = new Date(); + socketTask = uni.connectSocket({ + url: wsurl, + success: (res) => {}, + fail: (e) => { + console.log(e); + console.log('WebSocket连接失败,10s后重连'); + setTimeout(() => { + connect(); + }, 10000); + }, + }); - socketTask.onOpen((res) => { - console.log("WebSocket连接成功"); - isConnect = true; - // 发送登录命令 - let loginInfo = { - cmd: 0, - data: { - accessToken: accessToken - } - }; - socketTask.send({ - data: JSON.stringify(loginInfo) - }); - }) + socketTask.onOpen((res) => { + console.log('WebSocket连接成功'); + isConnect = true; + // 发送登录命令 + let loginInfo = { + cmd: 0, + data: { + accessToken: accessToken, + }, + }; + socketTask.send({ + data: JSON.stringify(loginInfo), + }); + }); - socketTask.onMessage((res) => { - let sendInfo = JSON.parse(res.data) - if (sendInfo.cmd == 0) { - heartCheck.start() - connectCallBack && connectCallBack(); - console.log('WebSocket登录成功') - } else if (sendInfo.cmd == 1) { - // 重新开启心跳定时 - heartCheck.reset(); - } else { - // 其他消息转发出去 - console.log("接收到消息", sendInfo); - messageCallBack && messageCallBack(sendInfo.cmd, sendInfo.data) - } - }) + socketTask.onMessage((res) => { + let sendInfo = JSON.parse(res.data); + if (sendInfo.cmd == 0) { + heartCheck.start(); + connectCallBack && connectCallBack(); + console.log('WebSocket登录成功'); + } else if (sendInfo.cmd == 1) { + // 重新开启心跳定时 + heartCheck.reset(); + } else { + // 其他消息转发出去 + console.log('接收到消息', sendInfo); + messageCallBack && messageCallBack(sendInfo.cmd, sendInfo.data); + } + }); - socketTask.onClose((res) => { - console.log('WebSocket连接关闭') - isConnect = false; - closeCallBack && closeCallBack(res); - }) + socketTask.onClose((res) => { + console.log('WebSocket连接关闭'); + isConnect = false; + closeCallBack && closeCallBack(res); + }); - socketTask.onError(e => { - console.log("ws错误:", e) - close(1006); - isConnect = false; - closeCallBack && closeCallBack(e); - }) -} + socketTask.onError((e) => { + console.log('ws错误:', e); + close(1006); + isConnect = false; + closeCallBack && closeCallBack(e); + }); +}; //定义重连函数 let reconnect = (wsurl, accessToken) => { - console.log("尝试重新连接"); - if (isConnect) { - return; - } - // 延迟10秒重连 避免过多次过频繁请求重连 - let timeDiff = new Date().getTime() - lastConnectTime.getTime() - let delay = timeDiff < 10000 ? 10000 - timeDiff : 0; - rec && clearTimeout(rec); - rec = setTimeout(function() { - connect(wsurl, accessToken); - }, delay); + console.log('尝试重新连接'); + if (isConnect) { + return; + } + // 延迟10秒重连 避免过多次过频繁请求重连 + let timeDiff = new Date().getTime() - lastConnectTime.getTime(); + let delay = timeDiff < 10000 ? 10000 - timeDiff : 0; + rec && clearTimeout(rec); + rec = setTimeout(function () { + connect(wsurl, accessToken); + }, delay); }; //设置关闭连接 let close = (code) => { - if (!isConnect) { - return; - } - socketTask.close({ - code: code, - complete: (res) => { - isConnect = false; - console.log("关闭websocket连接"); - }, - fail: (e) => { - console.log("关闭websocket连接失败", e); - } - }); + if (!isConnect) { + return; + } + socketTask.close({ + code: code, + complete: (res) => { + isConnect = false; + console.log('关闭websocket连接'); + }, + fail: (e) => { + console.log('关闭websocket连接失败', e); + }, + }); }; - // 心跳设置 let heartCheck = { - timeout: 20000, //每段时间发送一次心跳包 这里设置为20s - timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象) - start: function() { - if (isConnect) { - console.log('发送WebSocket心跳') - let heartBeat = { - cmd: 1, - data: {} - }; - sendMessage(JSON.stringify(heartBeat)) - } - }, - reset: function() { - clearTimeout(this.timeoutObj); - this.timeoutObj = setTimeout(() => heartCheck.start(), this.timeout); - } + timeout: 20000, //每段时间发送一次心跳包 这里设置为20s + timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象) + start: function () { + if (isConnect) { + console.log('发送WebSocket心跳'); + let heartBeat = { + cmd: 1, + data: {}, + }; + sendMessage(JSON.stringify(heartBeat)); + } + }, + reset: function () { + clearTimeout(this.timeoutObj); + this.timeoutObj = setTimeout(() => heartCheck.start(), this.timeout); + }, }; let sendMessage = (message) => { - socketTask.send({ data: message }) -} + socketTask.send({ data: message }); +}; let onConnect = (callback) => { - connectCallBack = callback; -} - + connectCallBack = callback; +}; let onMessage = (callback) => { - messageCallBack = callback; -} - + messageCallBack = callback; +}; let onClose = (callback) => { - closeCallBack = callback; -} - + closeCallBack = callback; +}; // 将方法暴露出去 -export { - connect, - reconnect, - close, - sendMessage, - onConnect, - onMessage, - onClose -} \ No newline at end of file +export { connect, reconnect, close, sendMessage, onConnect, onMessage, onClose }; diff --git a/src/components/bar/arrow-bar.vue b/src/components/bar/arrow-bar.vue index 6ecf1891..435056ca 100644 --- a/src/components/bar/arrow-bar.vue +++ b/src/components/bar/arrow-bar.vue @@ -1,64 +1,63 @@ \ No newline at end of file + .icon { + margin-left: 40rpx; + } + + .title { + flex: 1; + margin-left: 10rpx; + } + + .arrow { + margin-right: 40rpx; + } + } + diff --git a/src/components/chat-item/chat-item.vue b/src/components/chat-item/chat-item.vue index 94777c44..8e77b29b 100644 --- a/src/components/chat-item/chat-item.vue +++ b/src/components/chat-item/chat-item.vue @@ -14,13 +14,13 @@ {{ atText }} - {{ - chat.sendNickName + ': ' - }} + + {{ chat.sendNickName + ': ' }} + {{ chat.lastContent }} - + @@ -111,8 +111,9 @@ position: relative; padding: 18rpx 20rpx; align-items: center; - background-color: white; + background-color: $im-bg; white-space: nowrap; + border-bottom: 1px solid $im-border; &:hover { background-color: $im-bg-active; @@ -175,7 +176,7 @@ display: flex; font-size: $im-font-size-smaller; color: $im-text-color-lighter; - padding-top: 8rpx; + padding: 8rpx 30rpx 0 0; align-items: center; .chat-at-text { @@ -191,6 +192,7 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + margin-right: 30rpx; } .icon { diff --git a/src/components/chat-record/chat-record.vue b/src/components/chat-record/chat-record.vue index cb390d8e..28685d30 100644 --- a/src/components/chat-record/chat-record.vue +++ b/src/components/chat-record/chat-record.vue @@ -1,243 +1,274 @@ \ No newline at end of file + .red { + color: $im-color-danger !important; + } + } + } + diff --git a/src/components/file-upload/file-upload.vue b/src/components/file-upload/file-upload.vue index c364ffd5..c10852c8 100644 --- a/src/components/file-upload/file-upload.vue +++ b/src/components/file-upload/file-upload.vue @@ -1,122 +1,130 @@ - \ No newline at end of file + diff --git a/src/components/image-upload/image-upload.vue b/src/components/image-upload/image-upload.vue index 74410da8..ba949690 100644 --- a/src/components/image-upload/image-upload.vue +++ b/src/components/image-upload/image-upload.vue @@ -1,100 +1,100 @@ - \ No newline at end of file + diff --git a/src/components/long-press-menu/long-press-menu.vue b/src/components/long-press-menu/long-press-menu.vue index 22b7c8a2..e8bafbb8 100644 --- a/src/components/long-press-menu/long-press-menu.vue +++ b/src/components/long-press-menu/long-press-menu.vue @@ -1,129 +1,145 @@ \ No newline at end of file + .menu-icon { + margin-right: 10rpx; + } + } + } + } + diff --git a/src/im-var.scss b/src/im-var.scss index abd98786..0c923fe8 100644 --- a/src/im-var.scss +++ b/src/im-var.scss @@ -1,18 +1,18 @@ // 颜色 -$im-color-primary: #3e45d7; -$im-color-primary-light-1: mix(#fff, $im-color-primary, 10%); -$im-color-primary-light-2: mix(#fff, $im-color-primary, 20%); -$im-color-primary-light-3: mix(#fff, $im-color-primary, 30%); -$im-color-primary-light-4: mix(#fff, $im-color-primary, 40%); -$im-color-primary-light-5: mix(#fff, $im-color-primary, 50%); -$im-color-primary-light-6: mix(#fff, $im-color-primary, 60%); -$im-color-primary-light-7: mix(#fff, $im-color-primary, 70%); -$im-color-primary-light-8: mix(#fff, $im-color-primary, 80%); -$im-color-primary-light-9: mix(#fff, $im-color-primary, 90%); -$im-color-primary-dark-1: mix(#000, $im-color-primary, 10%); -$im-color-primary-dark-2: mix(#000, $im-color-primary, 20%); -$im-color-primary-dark-3: mix(#000, $im-color-primary, 30%); -$im-color-primary-dark-4: mix(#000, $im-color-primary, 40%); +$im-color-primary: #ffcd32; +$im-color-primary-light-1: mix(#000, $im-color-primary, 10%); +$im-color-primary-light-2: mix(#000, $im-color-primary, 20%); +$im-color-primary-light-3: mix(#000, $im-color-primary, 30%); +$im-color-primary-light-4: mix(#000, $im-color-primary, 40%); +$im-color-primary-light-5: mix(#000, $im-color-primary, 50%); +$im-color-primary-light-6: mix(#000, $im-color-primary, 60%); +$im-color-primary-light-7: mix(#000, $im-color-primary, 70%); +$im-color-primary-light-8: mix(#000, $im-color-primary, 80%); +$im-color-primary-light-9: mix(#000, $im-color-primary, 90%); +$im-color-primary-dark-1: mix(#fff, $im-color-primary, 10%); +$im-color-primary-dark-2: mix(#fff, $im-color-primary, 20%); +$im-color-primary-dark-3: mix(#fff, $im-color-primary, 30%); +$im-color-primary-dark-4: mix(#fff, $im-color-primary, 40%); $im-color-success: #18bc37; $im-color-warning: #f3a73f; @@ -20,16 +20,16 @@ $im-color-danger: #e43d33; $im-color-info: #8f939c; // 文字颜色 -$im-text-color: #000000; -$im-text-color-light: #6a6a6a; -$im-text-color-lighter: #909399; +$im-text-color: #fff; +$im-text-color-light: #6a6a6a; +$im-text-color-lighter: #909399; $im-text-color-lighter-extra: #c7c7c7; // 边框颜色 -$im-border: #F0F0F0; -$im-border-light: #EDEDED; -$im-border-lighter: #DCDCDC; -$im-border-lighter-extra: #B9B9B9; +$im-border: #333; +$im-border-light: #3f3f3f; +$im-border-lighter: #474747; +$im-border-lighter-extra: #595959; // 文字大小 $im-font-size: 30rpx; @@ -41,24 +41,25 @@ $im-font-size-larger: 34rpx; $im-font-size-larger-extra: 36rpx; // 阴影 -$im-box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04); -$im-box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1); -$im-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, .12); -$im-box-shadow-dark: 0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); +$im-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); +$im-box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1); +$im-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12); +$im-box-shadow-dark: 0px 1px 10px 2px + rgba( + $color: #444, + $alpha: 0.01, + ); // 背景 -$im-bg: #f8f9ff; -$im-bg-linear: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%); -$im-bg-active: #f7f8fc; +$im-bg: #222; +$im-bg-linear: linear-gradient(135deg, #222 0%, #333 100%); +$im-bg-active: #333; $im-bg-active-dark: $im-color-primary-light-9; -$im-bg-input: #fafafa; - +$im-bg-input: #333; // 标题 -$im-title-size: 26px; -$im-title-size-1: 22px; +$im-title-size: 26px; +$im-title-size-1: 22px; $im-title-size-2: 18px; -$font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; - -$im-nav-bar-height: 50px; \ No newline at end of file +$im-nav-bar-height: 50px; diff --git a/src/main.scss b/src/main.scss deleted file mode 100644 index b433aa75..00000000 --- a/src/main.scss +++ /dev/null @@ -1,27 +0,0 @@ -page { - font-family: Noto Sans SC, Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -:root, -page { - user-select: none; - background-color: #222222; - color: #ffffff; - font-size: 14px; - height: 100%; - --wot-color-theme: #ffcd32; - --wot-backtop-bg: #ffcd32; - --wot-dark-background: #222; - --wot-dark-background2: #222; - --wot-dark-color: #ffcd32; - --wot-picker-toolbar-title-color: #fff; - // background-image: url(./static/page-bg.png); - // background-repeat: no-repeat; - // background-size: 100% 100%; -} diff --git a/src/main.ts b/src/main.ts index 5a57757f..9a294c06 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,10 @@ // @ts-nocheck +import App from './App.vue'; +import { createSSRApp } from 'vue'; +import { setupPinia } from './sheep/store'; +import 'virtual:uno.css'; + +/** 聊天common模块 */ import request from './common/request'; import emotion from './common/emotion.js'; import url from './common/url.js'; @@ -22,19 +28,14 @@ window.ImageResize = { default: ImageResize }; import * as recorder from './common/recorder-app'; // #endif -import App from './App.vue'; -import { createSSRApp } from 'vue'; -// @ts-ignore -import { setupPinia } from './sheep/store'; -import './main.scss'; -import 'virtual:uno.css'; - -import useChatStore from '@/store/chatStore.js'; -import useFriendStore from '@/store/friendStore.js'; -import useGroupStore from '@/store/groupStore.js'; -import useConfigStore from '@/store/configStore.js'; -import useUserStore from '@/store/userStore.js'; +/** 聊天功能pinia仓库 */ +import useChatStore from '@/chat-store/chatStore.js'; +import useFriendStore from '@/chat-store/friendStore.js'; +import useGroupStore from '@/chat-store/groupStore.js'; +import useConfigStore from '@/chat-store/configStore.js'; +import useUserStore from '@/chat-store/userStore.js'; +/** 聊天页面的导航组件 */ import barGroup from '@/components/bar/bar-group'; import arrowBar from '@/components/bar/arrow-bar'; import btnBar from '@/components/bar/btn-bar'; @@ -45,6 +46,7 @@ export function createApp() { setupPinia(app); + // 聊天common模块挂载为全局属性 app.config.globalProperties.$http = request; app.config.globalProperties.$wsApi = socketApi; app.config.globalProperties.$msgType = messageType; @@ -55,12 +57,13 @@ export function createApp() { app.config.globalProperties.$date = date; app.config.globalProperties.$rc = recorder; + // 聊天页面的导航组件设置为全局组件 app.component('bar-group', barGroup); app.component('arrow-bar', arrowBar); app.component('btn-bar', btnBar); app.component('switch-bar', switchBar); - // 初始化时再挂载store对象 + // $mountStore挂载为全局属性,等app初始化时再挂载chat-store到全局属性,方便页面中直接this使用 app.config.globalProperties.$mountStore = () => { app.config.globalProperties.chatStore = useChatStore(); app.config.globalProperties.friendStore = useFriendStore(); diff --git a/src/manifest.json b/src/manifest.json index c387765d..16de4d14 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -165,22 +165,7 @@ } } }, - "nativePlugins" : { - "wf-uni-wfc-client" : { - "__plugin_info__" : { - "name" : "【官方】野火即时通讯IM插件", - "description" : "野火官方发布移动端即时通讯插件,包括Android和iOS平台,拥有完善的Demo,支持单人、群组和聊天室会话,支持文字、语音、图片等常见消息,服务器和移动端免费使用,让您一步拥有完美的即时通讯软件。", - "platforms" : "Android,iOS", - "url" : "https://ext.dcloud.net.cn/plugin?id=7895", - "android_package_name" : "uni.app.UNIB94390A", - "ios_bundle_id" : "uni.app.UNIB94390A", - "isCloud" : true, - "bought" : 1, - "pid" : "7895", - "parameters" : {} - } - } - } + "nativePlugins" : {} }, "quickapp" : {}, "quickapp-native" : { diff --git a/src/pages.json b/src/pages.json index c34df6da..cbde688a 100644 --- a/src/pages.json +++ b/src/pages.json @@ -5,7 +5,10 @@ "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue", "^su-(.*)": "@/sheep/ui/su-$1/su-$1.vue", "^s-(.*)": "@/sheep/components/s-$1/s-$1.vue", - "^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue" + "^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue", + "^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue", + "^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue", + "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue" } }, "pages": [ @@ -840,10 +843,15 @@ ], "globalStyle": { "navigationBarTextStyle": "black", - "navigationBarTitleText": "交友聊天", + "navigationBarTitleText": "荷塘月色交友聊天", "navigationBarBackgroundColor": "#F8F8F8", "backgroundColor": "#F8F8F8", - "navigationStyle": "custom" + /* #ifndef MP-WEIXIN */ + "navigationStyle": "custom", + /* #endif */ + /* #ifdef MP-WEIXIN */ + "navigationStyle": "default" + /* #endif */ }, "tabBar": { "color": "#fff", diff --git a/src/pages/message/chat-box.vue b/src/pages/message/chat-box.vue index b492622f..ee89edbe 100644 --- a/src/pages/message/chat-box.vue +++ b/src/pages/message/chat-box.vue @@ -1,6 +1,18 @@ \ No newline at end of file + &.right { + right: 30rpx; + } + } + } + } + diff --git a/src/pages/message/chat-private-video.vue b/src/pages/message/chat-private-video.vue index 0677af70..22152fac 100644 --- a/src/pages/message/chat-private-video.vue +++ b/src/pages/message/chat-private-video.vue @@ -1,100 +1,106 @@ \ No newline at end of file + .chat-web-view { + } + diff --git a/src/pages/message/message.vue b/src/pages/message/message.vue index a8df83e6..c1cc31a0 100644 --- a/src/pages/message/message.vue +++ b/src/pages/message/message.vue @@ -1,207 +1,228 @@ \ No newline at end of file + .chat-loading { + display: block; + width: 100%; + height: 120rpx; + background: #222; + color: $im-text-color-lighter; + + .loading-box { + position: relative; + } + } + + .scroll-bar { + flex: 1; + height: 100%; + } + } + diff --git a/src/sheep/components/s-share-modal/canvas-poster/poster/user.js b/src/sheep/components/s-share-modal/canvas-poster/poster/user.js index aa73922e..d0fd15ca 100644 --- a/src/sheep/components/s-share-modal/canvas-poster/poster/user.js +++ b/src/sheep/components/s-share-modal/canvas-poster/poster/user.js @@ -1,6 +1,6 @@ import sheep from '@/sheep'; import { formatImageUrlProtocol, getWxaQrcode } from './index'; -import { measureTextWidth } from '@/utils/textUtils'; // 引入新封装的方法 +import { measureTextWidth } from '@/sheep/util/textUtils'; const user = async (poster) => { const width = poster.width; const userInfo = sheep.$store('user').userInfo; @@ -9,7 +9,9 @@ const user = async (poster) => { return [ { type: 'image', - src: formatImageUrlProtocol(sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.user_bg)), + src: formatImageUrlProtocol( + sheep.$url.cdn(sheep.$store('app').platform.share.posterInfo.user_bg), + ), css: { width, position: 'fixed', @@ -29,7 +31,7 @@ const user = async (poster) => { fontFamily: 'sans-serif', position: 'fixed', top: width * 0.4, - left: (width-widthNickName) / 2, + left: (width - widthNickName) / 2, }, }, { diff --git a/src/utils/textUtils.js b/src/sheep/util/textUtils.js similarity index 97% rename from src/utils/textUtils.js rename to src/sheep/util/textUtils.js index f6231a0d..02eb1da1 100644 --- a/src/utils/textUtils.js +++ b/src/sheep/util/textUtils.js @@ -1,4 +1,3 @@ -// sheep/utils/textUtils.js export function measureTextWidth(text, fontSize = 14, fontFamily = 'sans-serif') { // 钉钉小程序没有 uni.createCanvasContext 方法 if (typeof uni === 'undefined' || typeof uni.createCanvasContext !== 'function') { diff --git a/src/uni_modules/lsj-upload/changelog.md b/src/uni_modules/lsj-upload/changelog.md new file mode 100644 index 00000000..090bca01 --- /dev/null +++ b/src/uni_modules/lsj-upload/changelog.md @@ -0,0 +1,120 @@ +## 2.3.2(2024-06-13) +问题修复:2.3.1版本引起的部分设备不支持findLastIndex问题 +## 2.3.1(2024-05-20) +修复:文件不去重时返回文件列表name与组件内置列表key不一致问题。 +## 2.3.0(2024-05-20) +优化:1:增加属性distinct【选择文件是否去重】、2:对show/hide函数增加uni.$emit事件监听,若页面存在多个上传组件时,可通过uni.$emit控制所有上传组件webview透明层是否显示。 +## 2.2.9(2023-06-01) +优化:将是否多选与count字段解绑(原逻辑是count>1为允许多选),改为新增multiple属性控制是否多选。 +## 2.2.8(2023-06-01) +修复上版本提交时accept测试值未删除导致h5端只能选择图片的问题。 +## 2.2.7(2023-05-06) +应群友建议,当instantly为true时,触发change事件后延迟1000毫秒再自动上传,方便动态修改参数,其实个人还是建议想在change事件动态设置参数的伙伴将instantly设置为false,修改参数后手动调用upload() +## 2.2.6(2023-02-09) +修复多个文件同时选择时返回多次change回调的问题 +## 2.2.5(2022-12-27) +1.修复多选文件时未能正常校验数量的问题; +2.app端与H5端支持单选或多选文件,通过count数量控制,超过1开启多选。 +## 2.2.4(2022-12-27) +1.修复多选文件时未能正常校验数量的问题; +2.app端修复多选只取到第一个文件的问题。 +## 2.2.3(2022-12-06) +修复手动调用show()导致count失效的问题 +## 2.2.2(2022-12-01) +Vue3自行修改兼容 +## 2.2.1(2022-10-19) +修复childId警告提示 +## 2.2.0(2022-10-10) +更新app端webview窗口参数clidId,默认值添加时间戳保证唯一性 +## 2.1.9(2022-07-13) +[修复] app端选择文件后初始化设置的文件列表被清空问题 +## 2.1.8(2022-07-13) +[新增] ref方法初始化文件列表,用于已提交后再次编辑时需带入已上传文件:setFiles(files),可传入数组或Map对象,传入格式请与组件选择返回格式保持一致,且name为必须属性。 +## 2.1.7(2022-07-12) +修复ios端偶现创建webview初始化参数未生效的问题 +## 2.1.6(2022-07-11) +[修复]:修复上个版本更新导致nvue窗口组件不能选择文件的问题; +[新增]: +1.应群友建议(填写禁止格式太多)格式限制formats由原来填写禁止选择的格式改为填写允许被选择的格式; +2.应群友建议(增加上传结束回调事件),上传结束回调事件@uploadEnd +3.如能帮到你请留下你的免费好评,组件使用过程中有问题可以加QQ群交流,至于Map对象怎么使用这类前端基础问题请自行百度 +## 2.1.5(2022-07-01) +app端组件销毁时添加自动销毁webview功能,避免v-if销毁组件的情况控件还能被点击的问题 +## 2.1.4(2022-07-01) +修复小程序端回显问题 +## 2.1.3(2022-06-30) +回调事件返回参数新增path字段(文件临时地址),用于回显 +## 2.1.2(2022-06-16) +修复APP端Tabbar窗口无法选择文件的问题 +## 2.1.1(2022-06-16) +优化: +1.组件优化为允许在v-if中使用; +2.允许option直接在data赋值,不再强制在onRead中初始化; +## 2.1.0(2022-06-13) +h5 pc端更改为单次可多选 +## 2.0.9(2022-06-10) +更新演示内容,部分同学不知道怎么获取服务端返回的数据 +## 2.0.8(2022-06-09) +优化动态更新上传参数函数,具体查看下方说明:动态更新参数演示 +## 2.0.7(2022-06-07) +新增wxFileType属性,用于小程序端选择附件时可选文件类型 +## 2.0.6(2022-06-07) +修复小程序端真机选择文件提示失败的问题 +## 2.0.5(2022-06-02) +优化小程序端调用hide()后未阻止触发文件选择问题 +## 2.0.4(2022-06-01) +优化APP端选择器初始定位 +## 2.0.3(2022-05-31) +修复nvue窗口选择文件报错问题 +## 2.0.2(2022-05-20) +修复ios端opiton设置过早未传入webview导致不自动上传问题 +## 2.0.1(2022-05-19) +修复APP端子窗口点击选择文件不响应问题 +## 2.0.0(2022-05-18) +此次组件更新至2.0版本,与1.0版本使用上略有差异,已使用1.0的同学请自行斟酌是否需要升级! +部分差异: +一、 2.0新增异步触发上传功能; +二、2.0新增文件批量上传功能; +三、2.0优化option,剔除属性,只保留上传接口所需字段,且允许异步更改option的值; +四、组件增加size(文件大小限制)、count(文件个数限制)、formats(文件后缀限制)、accept(文件类型限制)、instantly(是否立即自动上传)、debug(日志打印)等属性; +五、回调事件取消input事件、callback事件,新增change事件和progress事件; +六、ref事件新增upload事件、clear事件; +七、优化组件代码,show和hide函数改为显示隐藏,不再重复开关webview; + +## 1.2.3(2022-03-22) +修复Demo里传入待完善功能[手动上传属性manual=true]导致不自动上传的问题,手动提交上传待下个版本更新 +## 1.2.2(2022-02-21) +修复上版本APP优化导致H5和小程序端不自动初始化的问题,此次更新仅修复此问题。异步提交功能下个版本更新~ +## 1.2.1(2022-01-25) +QQ1群已满,已开放2群:469580165 +## 1.2.0(2021-12-09) +优化APP端页面中DOM重排后每次需要重新定位的问题 +## 1.1.1(2021-12-09) +优化,与上版本使用方式有改变,请检查后确认是否需要更新,create更名为show, close更名为hide,取消初始化时手动create, 传参方式改为props=>option +## 1.1.0(2021-12-09) +新增refresh方法,用于DOM发生重排时重新定位控件(APP端) +## 1.0.9(2021-07-15) +修复上传进度未同步渲染,直接返回100%的BUG +## 1.0.8(2021-07-12) +修复H5端传入height和width未生效的bug +## 1.0.7(2021-07-07) +修复h5和小程序端上传完成callback未返回fileName字段问题 +## 1.0.6(2021-07-07) +修复h5端提示信息debug +## 1.0.5(2021-06-29) +感谢小伙伴找出bug,上传成功回调success未置为true,已修复 +## 1.0.4(2021-06-28) +新增兼容APP,H5,小程序手动关闭控件,关闭后不再弹出文件选择框,需要重新create再次开启 +## 1.0.3(2021-06-28) +close增加条件编译,除app端外不需要close +## 1.0.2(2021-06-28) +1.修复页面滚动位置后再create控件导致控件位置不正确的问题; +2.修复nvue无法create控件; +3.示例项目新增nvue使用案例; +## 1.0.1(2021-06-28) +因为有的朋友不清楚app端切换tab时应该怎么处理webview,现重新上传一版示例项目,需要做tab切换的朋友可以导入示例项目查看 +## 1.0.0(2021-06-25) +此插件为l-file插件中上传功能改版,更新内容为: +1. 按钮内嵌入页面,不再强制固定底部,可跟随页面滚动 +2.无需再单独弹框点击上传,减去中间层 +3.通过slot自定义按钮样式 diff --git a/src/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js b/src/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js new file mode 100644 index 00000000..a86233e3 --- /dev/null +++ b/src/uni_modules/lsj-upload/components/lsj-upload/LsjFile.js @@ -0,0 +1,414 @@ +export class LsjFile { + constructor(data) { + this.dom = null; + // files.type = waiting(等待上传)|| loading(上传中)|| success(成功) || fail(失败) + this.files = new Map(); + this.debug = data.debug || false; + this.id = data.id; + this.width = data.width; + this.height = data.height; + this.option = data.option; + this.instantly = data.instantly; + this.prohibited = data.prohibited; + this.onchange = data.onchange; + this.onprogress = data.onprogress; + this.uploadHandle = this._uploadHandle; + // #ifdef MP-WEIXIN + this.uploadHandle = this._uploadHandleWX; + // #endif + } + + + /** + * 创建File节点 + * @param {string}path webview地址 + */ + create(path) { + if (!this.dom) { + // #ifdef H5 + let dom = document.createElement('input'); + dom.type = 'file' + dom.value = '' + dom.style.height = this.height + dom.style.width = this.width + dom.style.position = 'absolute' + dom.style.top = 0 + dom.style.left = 0 + dom.style.right = 0 + dom.style.bottom = 0 + dom.style.opacity = 0 + dom.style.zIndex = 999 + dom.accept = this.prohibited.accept; + if (this.prohibited.multiple) { + dom.multiple = 'multiple'; + } + dom.onchange = event => { + for (let file of event.target.files) { + if (this.files.size >= this.prohibited.count) { + this.toast(`只允许上传${this.prohibited.count}个文件`); + this.dom.value = ''; + break; + } + this.addFile(file); + } + + this._uploadAfter(); + + this.dom.value = ''; + }; + this.dom = dom; + // #endif + + // #ifdef APP-PLUS + let styles = { + top: '-200px', + left: 0, + width: '1px', + height: '200px', + background: 'transparent' + }; + let extras = { + debug: this.debug, + instantly: this.instantly, + prohibited: this.prohibited, + } + this.dom = plus.webview.create(path, this.id, styles,extras); + this.setData(this.option); + this._overrideUrlLoading(); + // #endif + return this.dom; + } + } + + + /** + * 设置上传参数 + * @param {object|string}name 上传参数,支持a.b 和 a[b] + */ + setData() { + let [name,value = ''] = arguments; + if (typeof name === 'object') { + Object.assign(this.option,name); + } + else { + this._setValue(this.option,name,value); + } + + this.debug&&console.log(JSON.stringify(this.option)); + + // #ifdef APP-PLUS + this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`); + // #endif + } + + /** + * 上传 + * @param {string}name 文件名称 + */ + async upload(name='') { + if (!this.option.url) { + throw Error('未设置上传地址'); + } + + // #ifndef APP-PLUS + if (name && this.files.has(name)) { + await this.uploadHandle(this.files.get(name)); + } + else { + for (let item of this.files.values()) { + if (item.type === 'waiting' || item.type === 'fail') { + await this.uploadHandle(item); + } + } + } + // #endif + + // #ifdef APP-PLUS + this.dom&&this.dom.evalJS(`vm.upload('${name}')`); + // #endif + } + + // 选择文件change + addFile(file,isCallChange) { + + let name = file.name; + this.debug&&console.log('文件名称',name,'大小',file.size); + + if (file) { + // 限制文件格式 + let path = ''; + let suffix = name.substring(name.lastIndexOf(".")+1).toLowerCase(); + let formats = this.prohibited.formats.toLowerCase(); + + // #ifndef MP-WEIXIN + path = URL.createObjectURL(file); + // #endif + // #ifdef MP-WEIXIN + path = file.path; + // #endif + if (formats&&!formats.includes(suffix)) { + this.toast(`不支持上传${suffix.toUpperCase()}格式文件`); + return false; + } + // 限制文件大小 + if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) { + this.toast(`附件大小请勿超过${this.prohibited.size}M`) + return false; + } + + try{ + if (!this.prohibited.distinct) { + let homonymIndex = [...this.files.keys()].findIndex(item=>{ + return (item.substring(0,item.lastIndexOf("("))||item.substring(0,item.lastIndexOf("."))) == name.substring(0,name.lastIndexOf(".")) && + item.substring(item.lastIndexOf(".")+1).toLowerCase() === suffix; + }) + if (homonymIndex > -1) { + name = `${name.substring(0,name.lastIndexOf("."))}(${homonymIndex+1}).${suffix}`; + } + } + }catch(e){ + //TODO handle the exception + } + + this.files.set(name,{file,path,name: name,size: file.size,progress: 0,type: 'waiting'}); + return true; + } + } + + /** + * 移除文件 + * @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件 + */ + clear(name='') { + // #ifdef APP-PLUS + this.dom&&this.dom.evalJS(`vm.clear('${name}')`); + // #endif + + if (!name) { + this.files.clear(); + } + else { + this.files.delete(name); + } + return this.onchange(this.files); + } + + /** + * 提示框 + * @param {string}msg 轻提示内容 + */ + toast(msg) { + uni.showToast({ + title: msg, + icon: 'none' + }); + } + + /** + * 微信小程序选择文件 + * @param {number}count 可选择文件数量 + */ + chooseMessageFile(type,count) { + wx.chooseMessageFile({ + count: count, + type: type, + success: ({ tempFiles }) => { + for (let file of tempFiles) { + this.addFile(file); + } + this._uploadAfter(); + }, + fail: () => { + this.toast(`打开失败`); + } + }) + } + + _copyObject(obj) { + if (typeof obj !== "undefined") { + return JSON.parse(JSON.stringify(obj)); + } else { + return obj; + } + } + + /** + * 自动根据字符串路径设置对象中的值 支持.和[] + * @param {Object} dataObj 数据源 + * @param {String} name 支持a.b 和 a[b] + * @param {String} value 值 + * setValue(dataObj, name, value); + */ + _setValue(dataObj, name, value) { + // 通过正则表达式 查找路径数据 + let dataValue; + if (typeof value === "object") { + dataValue = this._copyObject(value); + } else { + dataValue = value; + } + let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g"); + const patten = name.match(regExp); + // 遍历路径 逐级查找 最后一级用于直接赋值 + for (let i = 0; i < patten.length - 1; i++) { + let keyName = patten[i]; + if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {}; + dataObj = dataObj[keyName]; + } + // 最后一级 + dataObj[patten[patten.length - 1]] = dataValue; + this.debug&&console.log('参数更新后',JSON.stringify(this.option)); + } + + _uploadAfter() { + this.onchange(this.files); + setTimeout(()=>{ + this.instantly&&this.upload(); + },1000) + } + + _overrideUrlLoading() { + this.dom.overrideUrlLoading({ mode: 'reject' }, e => { + let {retype,item,files,end} = this._getRequest( + e.url + ); + let _this = this; + switch (retype) { + case 'updateOption': + this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`); + break + case 'change': + try { + _this.files = new Map([..._this.files,...JSON.parse(unescape(files))]); + } catch (e) { + return console.error('出错了,请检查代码') + } + _this.onchange(_this.files); + break + case 'progress': + try { + item = JSON.parse(unescape(item)); + } catch (e) { + return console.error('出错了,请检查代码') + } + _this._changeFilesItem(item,end); + break + default: + break + } + }) + } + + _getRequest(url) { + let theRequest = new Object() + let index = url.indexOf('?') + if (index != -1) { + let str = url.substring(index + 1) + let strs = str.split('&') + for (let i = 0; i < strs.length; i++) { + theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]) + } + } + return theRequest + } + + _changeFilesItem(item,end=false) { + this.debug&&console.log('onprogress',JSON.stringify(item)); + this.onprogress(item,end); + this.files.set(item.name,item); + } + + _uploadHandle(item) { + item.type = 'loading'; + delete item.responseText; + return new Promise((resolve,reject)=>{ + this.debug&&console.log('option',JSON.stringify(this.option)); + let {url,name,method='POST',header,formData} = this.option; + let form = new FormData(); + for (let keys in formData) { + form.append(keys, formData[keys]) + } + form.append(name, item.file); + let xmlRequest = new XMLHttpRequest(); + xmlRequest.open(method, url, true); + for (let keys in header) { + xmlRequest.setRequestHeader(keys, header[keys]) + } + + xmlRequest.upload.addEventListener( + 'progress', + event => { + if (event.lengthComputable) { + let progress = Math.ceil((event.loaded * 100) / event.total) + if (progress <= 100) { + item.progress = progress; + this._changeFilesItem(item); + } + } + }, + false + ); + + xmlRequest.ontimeout = () => { + console.error('请求超时') + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + + xmlRequest.onreadystatechange = ev => { + if (xmlRequest.readyState == 4) { + if (xmlRequest.status == 200) { + this.debug&&console.log('上传完成:' + xmlRequest.responseText) + item['responseText'] = xmlRequest.responseText; + item.type = 'success'; + this._changeFilesItem(item,true); + return resolve(true); + } else if (xmlRequest.status == 0) { + console.error('status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求') + } + console.error('--ERROR--:status = ' + xmlRequest.status) + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + } + xmlRequest.send(form) + }); + } + + _uploadHandleWX(item) { + item.type = 'loading'; + delete item.responseText; + return new Promise((resolve,reject)=>{ + this.debug&&console.log('option',JSON.stringify(this.option)); + let form = {filePath: item.file.path,...this.option }; + form['fail'] = ({ errMsg = '' }) => { + console.error('--ERROR--:' + errMsg) + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + form['success'] = res => { + if (res.statusCode == 200) { + this.debug&&console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data) + item['responseText'] = res.data; + item.type = 'success'; + this._changeFilesItem(item,true); + return resolve(true); + } + item.type = 'fail'; + this._changeFilesItem(item,true); + return resolve(false); + } + + let xmlRequest = uni.uploadFile(form); + xmlRequest.onProgressUpdate(({ progress = 0 }) => { + if (progress <= 100) { + item.progress = progress; + this._changeFilesItem(item); + } + }) + }); + } +} \ No newline at end of file diff --git a/src/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue b/src/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue new file mode 100644 index 00000000..46ac2969 --- /dev/null +++ b/src/uni_modules/lsj-upload/components/lsj-upload/lsj-upload.vue @@ -0,0 +1,338 @@ + + + + + diff --git a/src/uni_modules/lsj-upload/hybrid/html/js/vue.min.js b/src/uni_modules/lsj-upload/hybrid/html/js/vue.min.js new file mode 100644 index 00000000..97ac4cf9 --- /dev/null +++ b/src/uni_modules/lsj-upload/hybrid/html/js/vue.min.js @@ -0,0 +1,8 @@ +/*! + * Vue.js v2.3.0 + * (c) 2014-2017 Evan You + * Released under the MIT License. + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(e){return void 0===e||null===e}function t(e){return void 0!==e&&null!==e}function n(e){return!0===e}function r(e){return"string"==typeof e||"number"==typeof e}function i(e){return null!==e&&"object"==typeof e}function o(e){return"[object Object]"===Ai.call(e)}function a(e){return"[object RegExp]"===Ai.call(e)}function s(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function c(e){var t=parseFloat(e);return isNaN(t)?e:t}function u(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}function f(e,t){return Si.call(e,t)}function p(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function d(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function v(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function h(e,t){for(var n in t)e[n]=t[n];return e}function m(e){for(var t={},n=0;n=0&&$o[n].id>e.id;)n--;$o.splice(Math.max(n,Ao)+1,0,e)}else $o.push(e);Co||(Co=!0,ro($e))}}function Ae(e){To.clear(),Oe(e,To)}function Oe(e,t){var n,r,o=Array.isArray(e);if((o||i(e))&&Object.isExtensible(e)){if(e.__ob__){var a=e.__ob__.dep.id;if(t.has(a))return;t.add(a)}if(o)for(n=e.length;n--;)Oe(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)Oe(e[r[n]],t)}}function Se(e,t,n){Eo.get=function(){return this[t][n]},Eo.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Eo)}function Te(e){e._watchers=[];var t=e.$options;t.props&&Ee(e,t.props),t.methods&&Me(e,t.methods),t.data?je(e):E(e._data={},!0),t.computed&&Le(e,t.computed),t.watch&&Pe(e,t.watch)}function Ee(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[],o=!e.$parent;lo.shouldConvert=o;for(var a in t)!function(o){i.push(o);var a=U(o,t,n,e);j(r,o,a),o in e||Se(e,"_props",o)}(a);lo.shouldConvert=!0}function je(e){var t=e.$options.data;t=e._data="function"==typeof t?Ne(t,e):t||{},o(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,i=n.length;i--;)r&&f(r,n[i])||$(n[i])||Se(e,"_data",n[i]);E(t,!0)}function Ne(e,t){try{return e.call(t)}catch(e){return C(e,t,"data()"),{}}}function Le(e,t){var n=e._computedWatchers=Object.create(null);for(var r in t){var i=t[r],o="function"==typeof i?i:i.get;n[r]=new So(e,o,g,jo),r in e||Ie(e,r,i)}}function Ie(e,t,n){"function"==typeof n?(Eo.get=De(t),Eo.set=g):(Eo.get=n.get?!1!==n.cache?De(t):n.get:g,Eo.set=n.set?n.set:g),Object.defineProperty(e,t,Eo)}function De(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),oo.target&&t.depend(),t.value}}function Me(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?g:d(t[n],e)}function Pe(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i=0||n.indexOf(e[i])<0)&&r.push(e[i]);return r}return e}function pt(e){this._init(e)}function dt(e){e.use=function(e){if(!e.installed){var t=v(arguments,1);return t.unshift(this),"function"==typeof e.install?e.install.apply(e,t):"function"==typeof e&&e.apply(null,t),e.installed=!0,this}}}function vt(e){e.mixin=function(e){this.options=B(this.options,e)}}function ht(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=B(n.options,e),a.super=n,a.options.props&&mt(a),a.options.computed&>(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Di.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=h({},a.options),i[r]=a,a}}function mt(e){var t=e.options.props;for(var n in t)Se(e.prototype,"_props",n)}function gt(e){var t=e.options.computed;for(var n in t)Ie(e.prototype,n,t[n])}function yt(e){Di.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&o(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function _t(e){return e&&(e.Ctor.options.name||e.tag)}function bt(e,t){return"string"==typeof e?e.split(",").indexOf(t)>-1:!!a(e)&&e.test(t)}function $t(e,t,n){for(var r in e){var i=e[r];if(i){var o=_t(i.componentOptions);o&&!n(o)&&(i!==t&&xt(i),e[r]=null)}}}function xt(e){e&&e.componentInstance.$destroy()}function wt(e){for(var n=e.data,r=e,i=e;t(i.componentInstance);)i=i.componentInstance._vnode,i.data&&(n=Ct(i.data,n));for(;t(r=r.parent);)r.data&&(n=Ct(n,r.data));return kt(n)}function Ct(e,n){return{staticClass:At(e.staticClass,n.staticClass),class:t(e.class)?[e.class,n.class]:n.class}}function kt(e){var n=e.class,r=e.staticClass;return t(r)||t(n)?At(r,Ot(n)):""}function At(e,t){return e?t?e+" "+t:e:t||""}function Ot(n){if(e(n))return"";if("string"==typeof n)return n;var r="";if(Array.isArray(n)){for(var o,a=0,s=n.length;a-1?ua[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:ua[e]=/HTMLUnknownElement/.test(t.toString())}function Et(e){if("string"==typeof e){var t=document.querySelector(e);return t||document.createElement("div")}return e}function jt(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function Nt(e,t){return document.createElementNS(ia[e],t)}function Lt(e){return document.createTextNode(e)}function It(e){return document.createComment(e)}function Dt(e,t,n){e.insertBefore(t,n)}function Mt(e,t){e.removeChild(t)}function Pt(e,t){e.appendChild(t)}function Rt(e){return e.parentNode}function Ft(e){return e.nextSibling}function Bt(e){return e.tagName}function Ht(e,t){e.textContent=t}function Ut(e,t,n){e.setAttribute(t,n)}function Vt(e,t){var n=e.data.ref;if(n){var r=e.context,i=e.componentInstance||e.elm,o=r.$refs;t?Array.isArray(o[n])?l(o[n],i):o[n]===i&&(o[n]=void 0):e.data.refInFor?Array.isArray(o[n])&&o[n].indexOf(i)<0?o[n].push(i):o[n]=[i]:o[n]=i}}function zt(e,n){return e.key===n.key&&e.tag===n.tag&&e.isComment===n.isComment&&t(e.data)===t(n.data)&&Jt(e,n)}function Jt(e,n){if("input"!==e.tag)return!0;var r;return(t(r=e.data)&&t(r=r.attrs)&&r.type)===(t(r=n.data)&&t(r=r.attrs)&&r.type)}function Kt(e,n,r){var i,o,a={};for(i=n;i<=r;++i)o=e[i].key,t(o)&&(a[o]=i);return a}function qt(e,t){(e.data.directives||t.data.directives)&&Wt(e,t)}function Wt(e,t){var n,r,i,o=e===pa,a=t===pa,s=Zt(e.data.directives,e.context),c=Zt(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,Yt(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(Yt(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n=0&&" "===(m=e.charAt(h));h--);m&&_a.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=e.slice(0,i).trim()):t();if(void 0===o?o=e.slice(0,i).trim():0!==v&&t(),a)for(i=0;i=Bo}function gn(e){return 34===e||39===e}function yn(e){var t=1;for(zo=Vo;!mn();)if(e=hn(),gn(e))_n(e);else if(91===e&&t++,93===e&&t--,0===t){Jo=Vo;break}}function _n(e){for(var t=e;!mn()&&(e=hn())!==t;);}function bn(e,t,n){Ko=n;var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if("select"===o)wn(e,r,i);else if("input"===o&&"checkbox"===a)$n(e,r,i);else if("input"===o&&"radio"===a)xn(e,r,i);else if("input"===o||"textarea"===o)Cn(e,r,i);else if(!Pi.isReservedTag(o))return pn(e,r,i),!1;return!0}function $n(e,t,n){var r=n&&n.number,i=ln(e,"value")||"null",o=ln(e,"true-value")||"true",a=ln(e,"false-value")||"false";an(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),un(e,$a,"var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$c){$$i<0&&("+t+"=$$a.concat($$v))}else{$$i>-1&&("+t+"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}}else{"+dn(t,"$$c")+"}",null,!0)}function xn(e,t,n){var r=n&&n.number,i=ln(e,"value")||"null";i=r?"_n("+i+")":i,an(e,"checked","_q("+t+","+i+")"),un(e,$a,dn(t,i),null,!0)}function wn(e,t,n){var r=n&&n.number,i='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",o="var $$selectedVal = "+i+";";o=o+" "+dn(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),un(e,"change",o,null,!0)}function Cn(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?ba:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=dn(t,l);c&&(f="if($event.target.composing)return;"+f),an(e,"value","("+t+")"),un(e,u,f,null,!0),(s||a||"number"===r)&&un(e,"blur","$forceUpdate()")}function kn(e){var n;t(e[ba])&&(n=zi?"change":"input",e[n]=[].concat(e[ba],e[n]||[]),delete e[ba]),t(e[$a])&&(n=Zi?"click":"change",e[n]=[].concat(e[$a],e[n]||[]),delete e[$a])}function An(e,t,n,r,i){if(n){var o=t,a=qo;t=function(n){null!==(1===arguments.length?o(n):o.apply(null,arguments))&&On(e,t,r,a)}}qo.addEventListener(e,t,Gi?{capture:r,passive:i}:r)}function On(e,t,n,r){(r||qo).removeEventListener(e,t,n)}function Sn(t,n){if(!e(t.data.on)||!e(n.data.on)){var r=n.data.on||{},i=t.data.on||{};qo=n.elm,kn(r),G(r,i,An,On,n.context)}}function Tn(n,r){if(!e(n.data.domProps)||!e(r.data.domProps)){var i,o,a=r.elm,s=n.data.domProps||{},c=r.data.domProps||{};t(c.__ob__)&&(c=r.data.domProps=h({},c));for(i in s)e(c[i])&&(a[i]="");for(i in c)if(o=c[i],"textContent"!==i&&"innerHTML"!==i||(r.children&&(r.children.length=0),o!==s[i]))if("value"===i){a._value=o;var u=null==o?"":String(o);En(a,r,u)&&(a.value=u)}else a[i]=o}}function En(e,t,n){return!e.composing&&("option"===t.tag||jn(e,n)||Nn(e,n))}function jn(e,t){return document.activeElement!==e&&e.value!==t}function Nn(e,n){var r=e.value,i=e._vModifiers;return t(i)&&i.number||"number"===e.type?c(r)!==c(n):t(i)&&i.trim?r.trim()!==n.trim():r!==n}function Ln(e){var t=In(e.style);return e.staticStyle?h(e.staticStyle,t):t}function In(e){return Array.isArray(e)?m(e):"string"==typeof e?Ca(e):e}function Dn(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)i=i.componentInstance._vnode,i.data&&(n=Ln(i.data))&&h(r,n);(n=Ln(e.data))&&h(r,n);for(var o=e;o=o.parent;)o.data&&(n=Ln(o.data))&&h(r,n);return r}function Mn(n,r){var i=r.data,o=n.data;if(!(e(i.staticStyle)&&e(i.style)&&e(o.staticStyle)&&e(o.style))){var a,s,c=r.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,p=In(r.data.style)||{};r.data.normalizedStyle=t(p.__ob__)?h({},p):p;var d=Dn(r,!0);for(s in f)e(d[s])&&Oa(c,s,"");for(s in d)(a=d[s])!==f[s]&&Oa(c,s,null==a?"":a)}}function Pn(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function Rn(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(/\s+/).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t);else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");e.setAttribute("class",n.trim())}}function Fn(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&h(t,ja(e.name||"v")),h(t,e),t}return"string"==typeof e?ja(e):void 0}}function Bn(e){Fa(function(){Fa(e)})}function Hn(e,t){(e._transitionClasses||(e._transitionClasses=[])).push(t),Pn(e,t)}function Un(e,t){e._transitionClasses&&l(e._transitionClasses,t),Rn(e,t)}function Vn(e,t,n){var r=zn(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===La?Ma:Ra,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=La,l=a,f=o.length):t===Ia?u>0&&(n=Ia,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?La:Ia:null,f=n?n===La?o.length:c.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===La&&Ba.test(r[Da+"Property"])}}function Jn(e,t){for(;e.length1}function Yn(e,t){!0!==t.data.show&&qn(t)}function Qn(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s-1,a.selected!==o&&(a.selected=o);else if(y(er(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Xn(e,t){for(var n=0,r=t.length;n=0&&a[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(var c=a.length-1;c>=i;c--)t.end&&t.end(a[c].tag,n,r);a.length=i,o=i&&a[i-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,r):"p"===s&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var i,o,a=[],s=t.expectHTML,c=t.isUnaryTag||Ni,u=t.canBeLeftOpenTag||Ni,l=0;e;){if(i=e,o&&Ns(o)){var f=o.toLowerCase(),p=Ls[f]||(Ls[f]=new RegExp("([\\s\\S]*?)(]*>)","i")),d=0,v=e.replace(p,function(e,n,r){return d=r.length,Ns(f)||"noscript"===f||(n=n.replace(//g,"$1").replace(//g,"$1")),t.chars&&t.chars(n),""});l+=e.length-v.length,e=v,r(f,l-d,l)}else{var h=e.indexOf("<");if(0===h){if(fs.test(e)){var m=e.indexOf("--\x3e");if(m>=0){n(m+3);continue}}if(ps.test(e)){var g=e.indexOf("]>");if(g>=0){n(g+2);continue}}var y=e.match(ls);if(y){n(y[0].length);continue}var _=e.match(us);if(_){var b=l;n(_[0].length),r(_[1],b,l);continue}var $=function(){var t=e.match(ss);if(t){var r={tagName:t[1],attrs:[],start:l};n(t[0].length);for(var i,o;!(i=e.match(cs))&&(o=e.match(os));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=l,r}}();if($){!function(e){var n=e.tagName,i=e.unarySlash;s&&("p"===o&&rs(n)&&r(o),u(n)&&o===n&&r(n));for(var l=c(n)||"html"===n&&"head"===o||!!i,f=e.attrs.length,p=new Array(f),d=0;d=0){for(w=e.slice(h);!(us.test(w)||ss.test(w)||fs.test(w)||ps.test(w)||(C=w.indexOf("<",1))<0);)h+=C,w=e.slice(h);x=e.substring(0,h),n(h)}h<0&&(x=e,e=""),t.chars&&x&&t.chars(x)}if(e===i){t.chars&&t.chars(e);break}}r()}function mr(e,t){var n=t?Rs(t):Ps;if(n.test(e)){for(var r,i,o=[],a=n.lastIndex=0;r=n.exec(e);){i=r.index,i>a&&o.push(JSON.stringify(e.slice(a,i)));var s=tn(r[1].trim());o.push("_s("+s+")"),a=i+r[0].length}return a0,Ki=Vi&&Vi.indexOf("edge/")>0,qi=Vi&&Vi.indexOf("android")>0,Wi=Vi&&/iphone|ipad|ipod|ios/.test(Vi),Zi=Vi&&/chrome\/\d+/.test(Vi)&&!Ki,Gi=!1;if(Ui)try{var Yi={};Object.defineProperty(Yi,"passive",{get:function(){Gi=!0}}),window.addEventListener("test-passive",null,Yi)}catch(e){}var Qi,Xi,eo=function(){return void 0===Qi&&(Qi=!Ui&&"undefined"!=typeof global&&"server"===global.process.env.VUE_ENV),Qi},to=Ui&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,no="undefined"!=typeof Symbol&&k(Symbol)&&"undefined"!=typeof Reflect&&k(Reflect.ownKeys),ro=function(){function e(){r=!1;var e=n.slice(0);n.length=0;for(var t=0;t1?v(n):n;for(var r=v(arguments,1),i=0,o=n.length;i1&&(t[n[0].trim()]=n[1].trim())}}),t}),ka=/^--/,Aa=/\s*!important$/,Oa=function(e,t,n){if(ka.test(t))e.style.setProperty(t,n);else if(Aa.test(n))e.style.setProperty(t,n.replace(Aa,""),"important");else{var r=Ta(t);if(Array.isArray(n))for(var i=0,o=n.length;iv?(f=e(i[g+1])?null:i[g+1].elm,y(n,f,i,d,g,o)):d>g&&b(n,r,p,v)}function w(r,i,o,a){if(r!==i){if(n(i.isStatic)&&n(r.isStatic)&&i.key===r.key&&(n(i.isCloned)||n(i.isOnce)))return i.elm=r.elm,void(i.componentInstance=r.componentInstance);var s,c=i.data;t(c)&&t(s=c.hook)&&t(s=s.prepatch)&&s(r,i);var u=i.elm=r.elm,l=r.children,f=i.children;if(t(c)&&h(i)){for(s=0;s',n.innerHTML.indexOf(t)>0}("\n"," "),ts=u("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),ns=u("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),rs=u("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),is=[/"([^"]*)"+/.source,/'([^']*)'+/.source,/([^\s"'=<>`]+)/.source],os=new RegExp("^\\s*"+/([^\s"'<>\/=]+)/.source+"(?:\\s*("+/(?:=)/.source+")\\s*(?:"+is.join("|")+"))?"),as="[a-zA-Z_][\\w\\-\\.]*",ss=new RegExp("^<((?:"+as+"\\:)?"+as+")"),cs=/^\s*(\/?)>/,us=new RegExp("^<\\/((?:"+as+"\\:)?"+as+")[^>]*>"),ls=/^]+>/i,fs=/^ + :value="value" + @input="e => $emit('input', e)" + + + :modelValue="modelValue" + @update:modelValue="e => $emit('update:modelValue', e)" + + :type="type" + :fixed="fixed" + :disabled="disabled" + :disabledColor="disabledColor" + :clearable="clearable" + :password="password" + :maxlength="maxlength" + :placeholder="placeholder" + :placeholderClass="placeholderClass" + :placeholderStyle="placeholderStyle" + :showWordLimit="showWordLimit" + :confirmType="confirmType" + :confirmHold="confirmHold" + :holdKeyboard="holdKeyboard" + :focus="focus" + :autoBlur="autoBlur" + :disableDefaultPadding="disableDefaultPadding" + :cursor="cursor" + :cursorSpacing="cursorSpacing" + :selectionStart="selectionStart" + :selectionEnd="selectionEnd" + :adjustPosition="adjustPosition" + :inputAlign="inputAlign" + :fontSize="fontSize" + :color="color" + :prefixIcon="prefixIcon" + :suffixIcon="suffixIcon" + :suffixIconStyle="suffixIconStyle" + :prefixIconStyle="prefixIconStyle" + :border="border" + :readonly="readonly" + :shape="shape" + :customStyle="customStyle" + :formatter="formatter" + :ignoreCompositionEvent="ignoreCompositionEvent" + > + + + + + + + + + + + + \ No newline at end of file diff --git a/src/uni_modules/uview-plus/components/u--text/u--text.vue b/src/uni_modules/uview-plus/components/u--text/u--text.vue new file mode 100644 index 00000000..9cdcf7b6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u--text/u--text.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/uni_modules/uview-plus/components/u--textarea/u--textarea.vue b/src/uni_modules/uview-plus/components/u--textarea/u--textarea.vue new file mode 100644 index 00000000..becd23db --- /dev/null +++ b/src/uni_modules/uview-plus/components/u--textarea/u--textarea.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/uni_modules/uview-plus/components/u-action-sheet/props.js b/src/uni_modules/uview-plus/components/u-action-sheet/props.js new file mode 100644 index 00000000..2f365f0a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-action-sheet/props.js @@ -0,0 +1,57 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 操作菜单是否展示 (默认false) + show: { + type: Boolean, + default: () => defProps.actionSheet.show + }, + // 标题 + title: { + type: String, + default: () => defProps.actionSheet.title + }, + // 选项上方的描述信息 + description: { + type: String, + default: () => defProps.actionSheet.description + }, + // 数据 + actions: { + type: Array, + default: () => defProps.actionSheet.actions + }, + // 取消按钮的文字,不为空时显示按钮 + cancelText: { + type: String, + default: () => defProps.actionSheet.cancelText + }, + // 点击某个菜单项时是否关闭弹窗 + closeOnClickAction: { + type: Boolean, + default: () => defProps.actionSheet.closeOnClickAction + }, + // 处理底部安全区(默认true) + safeAreaInsetBottom: { + type: Boolean, + default: () => defProps.actionSheet.safeAreaInsetBottom + }, + // 小程序的打开方式 + openType: { + type: String, + default: () => defProps.actionSheet.openType + }, + // 点击遮罩是否允许关闭 (默认true) + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.actionSheet.closeOnClickOverlay + }, + // 圆角值 + round: { + type: [Boolean, String, Number], + default: () => defProps.actionSheet.round + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue b/src/uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue new file mode 100644 index 00000000..3c283400 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue @@ -0,0 +1,281 @@ + + + + + + diff --git a/src/uni_modules/uview-plus/components/u-album/props.js b/src/uni_modules/uview-plus/components/u-album/props.js new file mode 100644 index 00000000..eb0f1818 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-album/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 图片地址,Array|Array形式 + urls: { + type: Array, + default: () => defProps.album.urls + }, + // 指定从数组的对象元素中读取哪个属性作为图片地址 + keyName: { + type: String, + default: () => defProps.album.keyName + }, + // 单图时,图片长边的长度 + singleSize: { + type: [String, Number], + default: () => defProps.album.singleSize + }, + // 多图时,图片边长 + multipleSize: { + type: [String, Number], + default: () => defProps.album.multipleSize + }, + // 多图时,图片水平和垂直之间的间隔 + space: { + type: [String, Number], + default: () => defProps.album.space + }, + // 单图时,图片缩放裁剪的模式 + singleMode: { + type: String, + default: () => defProps.album.singleMode + }, + // 多图时,图片缩放裁剪的模式 + multipleMode: { + type: String, + default: () => defProps.album.multipleMode + }, + // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量 + maxCount: { + type: [String, Number], + default: () => defProps.album.maxCount + }, + // 是否可以预览图片 + previewFullImage: { + type: Boolean, + default: () => defProps.album.previewFullImage + }, + // 每行展示图片数量,如设置,singleSize和multipleSize将会无效 + rowCount: { + type: [String, Number], + default: () => defProps.album.rowCount + }, + // 超出maxCount时是否显示查看更多的提示 + showMore: { + type: Boolean, + default: () => defProps.album.showMore + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-album/u-album.vue b/src/uni_modules/uview-plus/components/u-album/u-album.vue new file mode 100644 index 00000000..49040194 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-album/u-album.vue @@ -0,0 +1,264 @@ + + + + + \ No newline at end of file diff --git a/src/uni_modules/uview-plus/components/u-alert/props.js b/src/uni_modules/uview-plus/components/u-alert/props.js new file mode 100644 index 00000000..9f150b5a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-alert/props.js @@ -0,0 +1,46 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 显示文字 + title: { + type: String, + default: () => defProps.alert.title + }, + // 主题,success/warning/info/error + type: { + type: String, + default: () => defProps.alert.type + }, + // 辅助性文字 + description: { + type: String, + default: () => defProps.alert.description + }, + // 是否可关闭 + closable: { + type: Boolean, + default: () => defProps.alert.closable + }, + // 是否显示图标 + showIcon: { + type: Boolean, + default: () => defProps.alert.showIcon + }, + // 浅或深色调,light-浅色,dark-深色 + effect: { + type: String, + default: () => defProps.alert.effect + }, + // 文字是否居中 + center: { + type: Boolean, + default: () => defProps.alert.center + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.alert.fontSize + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-alert/u-alert.vue b/src/uni_modules/uview-plus/components/u-alert/u-alert.vue new file mode 100644 index 00000000..dea66b17 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-alert/u-alert.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-avatar-group/props.js b/src/uni_modules/uview-plus/components/u-avatar-group/props.js new file mode 100644 index 00000000..96ed8719 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-avatar-group/props.js @@ -0,0 +1,54 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 头像图片组 + urls: { + type: Array, + default: () => defProps.avatarGroup.urls + }, + // 最多展示的头像数量 + maxCount: { + type: [String, Number], + default: () => defProps.avatarGroup.maxCount + }, + // 头像形状 + shape: { + type: String, + default: () => defProps.avatarGroup.shape + }, + // 图片裁剪模式 + mode: { + type: String, + default: () => defProps.avatarGroup.mode + }, + // 超出maxCount时是否显示查看更多的提示 + showMore: { + type: Boolean, + default: () => defProps.avatarGroup.showMore + }, + // 头像大小 + size: { + type: [String, Number], + default: () => defProps.avatarGroup.size + }, + // 指定从数组的对象元素中读取哪个属性作为图片地址 + keyName: { + type: String, + default: () => defProps.avatarGroup.keyName + }, + // 头像之间的遮挡比例 + gap: { + type: [String, Number], + validator(value) { + return value >= 0 && value <= 1 + }, + default: () => defProps.avatarGroup.gap + }, + // 需额外显示的值 + extraValue: { + type: [Number, String], + default: () => defProps.avatarGroup.extraValue + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue b/src/uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue new file mode 100644 index 00000000..fdfeaad0 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-avatar/props.js b/src/uni_modules/uview-plus/components/u-avatar/props.js new file mode 100644 index 00000000..8fa15ac3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-avatar/props.js @@ -0,0 +1,81 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +import test from '../../libs/function/test'; +export const props = defineMixin({ + props: { + // 头像图片路径(不能为相对路径) + src: { + type: String, + default: () => defProps.avatar.src + }, + // 头像形状,circle-圆形,square-方形 + shape: { + type: String, + default: () => defProps.avatar.shape + }, + // 头像尺寸 + size: { + type: [String, Number], + default: () => defProps.avatar.size + }, + // 裁剪模式 + mode: { + type: String, + default: () => defProps.avatar.mode + }, + // 显示的文字 + text: { + type: String, + default: () => defProps.avatar.text + }, + // 背景色 + bgColor: { + type: String, + default: () => defProps.avatar.bgColor + }, + // 文字颜色 + color: { + type: String, + default: () => defProps.avatar.color + }, + // 文字大小 + fontSize: { + type: [String, Number], + default: () => defProps.avatar.fontSize + }, + // 显示的图标 + icon: { + type: String, + default: () => defProps.avatar.icon + }, + // 显示小程序头像,只对百度,微信,QQ小程序有效 + mpAvatar: { + type: Boolean, + default: () => defProps.avatar.mpAvatar + }, + // 是否使用随机背景色 + randomBgColor: { + type: Boolean, + default: () => defProps.avatar.randomBgColor + }, + // 加载失败的默认头像(组件有内置默认图片) + defaultUrl: { + type: String, + default: () => defProps.avatar.defaultUrl + }, + // 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间 + colorIndex: { + type: [String, Number], + // 校验参数规则,索引在0-19之间 + validator(n) { + return test.range(n, [0, 19]) || n === '' + }, + default: () => defProps.avatar.colorIndex + }, + // 组件标识符 + name: { + type: String, + default: () => defProps.avatar.name + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-avatar/u-avatar.vue b/src/uni_modules/uview-plus/components/u-avatar/u-avatar.vue new file mode 100644 index 00000000..71c0b220 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-avatar/u-avatar.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-back-top/props.js b/src/uni_modules/uview-plus/components/u-back-top/props.js new file mode 100644 index 00000000..b7146417 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-back-top/props.js @@ -0,0 +1,56 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 返回顶部的形状,circle-圆形,square-方形 + mode: { + type: String, + default: () => defProps.backtop.mode + }, + // 自定义图标 + icon: { + type: String, + default: () => defProps.backtop.icon + }, + // 提示文字 + text: { + type: String, + default: () => defProps.backtop.text + }, + // 返回顶部滚动时间 + duration: { + type: [String, Number], + default: () => defProps.backtop.duration + }, + // 滚动距离 + scrollTop: { + type: [String, Number], + default: () => defProps.backtop.scrollTop + }, + // 距离顶部多少距离显示,单位px + top: { + type: [String, Number], + default: () => defProps.backtop.top + }, + // 返回顶部按钮到底部的距离,单位px + bottom: { + type: [String, Number], + default: () => defProps.backtop.bottom + }, + // 返回顶部按钮到右边的距离,单位px + right: { + type: [String, Number], + default: () => defProps.backtop.right + }, + // 层级 + zIndex: { + type: [String, Number], + default: () => defProps.backtop.zIndex + }, + // 图标的样式,对象形式 + iconStyle: { + type: Object, + default: () => defProps.backtop.iconStyle + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-back-top/u-back-top.vue b/src/uni_modules/uview-plus/components/u-back-top/u-back-top.vue new file mode 100644 index 00000000..fcdb045f --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-back-top/u-back-top.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-badge/props.js b/src/uni_modules/uview-plus/components/u-badge/props.js new file mode 100644 index 00000000..5ed924b1 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-badge/props.js @@ -0,0 +1,79 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否显示圆点 + isDot: { + type: Boolean, + default: () => defProps.badge.isDot + }, + // 显示的内容 + value: { + type: [Number, String], + default: () => defProps.badge.value + }, + // 显示的内容 + modelValue: { + type: [Number, String], + default: () => defProps.badge.modelValue + }, + // 是否显示 + show: { + type: Boolean, + default: () => defProps.badge.show + }, + // 最大值,超过最大值会显示 '{max}+' + max: { + type: [Number, String], + default: () => defProps.badge.max + }, + // 主题类型,error|warning|success|primary + type: { + type: String, + default: () => defProps.badge.type + }, + // 当数值为 0 时,是否展示 Badge + showZero: { + type: Boolean, + default: () => defProps.badge.showZero + }, + // 背景颜色,优先级比type高,如设置,type参数会失效 + bgColor: { + type: [String, null], + default: () => defProps.badge.bgColor + }, + // 字体颜色 + color: { + type: [String, null], + default: () => defProps.badge.color + }, + // 徽标形状,circle-四角均为圆角,horn-左下角为直角 + shape: { + type: String, + default: () => defProps.badge.shape + }, + // 设置数字的显示方式,overflow|ellipsis|limit + // overflow会根据max字段判断,超出显示`${max}+` + // ellipsis会根据max判断,超出显示`${max}...` + // limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数 + numberType: { + type: String, + default: () => defProps.badge.numberType + }, + // 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效 + offset: { + type: Array, + default: () => defProps.badge.offset + }, + // 是否反转背景和字体颜色 + inverted: { + type: Boolean, + default: () => defProps.badge.inverted + }, + // 是否绝对定位 + absolute: { + type: Boolean, + default: () => defProps.badge.absolute + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-badge/u-badge.vue b/src/uni_modules/uview-plus/components/u-badge/u-badge.vue new file mode 100644 index 00000000..ecc843fe --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-badge/u-badge.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-button/nvue.scss b/src/uni_modules/uview-plus/components/u-button/nvue.scss new file mode 100644 index 00000000..490db7d9 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-button/nvue.scss @@ -0,0 +1,46 @@ +$u-button-active-opacity:0.75 !default; +$u-button-loading-text-margin-left:4px !default; +$u-button-text-color: #FFFFFF !default; +$u-button-text-plain-error-color:$u-error !default; +$u-button-text-plain-warning-color:$u-warning !default; +$u-button-text-plain-success-color:$u-success !default; +$u-button-text-plain-info-color:$u-info !default; +$u-button-text-plain-primary-color:$u-primary !default; +.u-button { + &--active { + opacity: $u-button-active-opacity; + } + + &--active--plain { + background-color: rgb(217, 217, 217); + } + + &__loading-text { + margin-left:$u-button-loading-text-margin-left; + } + + &__text, + &__loading-text { + color:$u-button-text-color; + } + + &__text--plain--error { + color:$u-button-text-plain-error-color; + } + + &__text--plain--warning { + color:$u-button-text-plain-warning-color; + } + + &__text--plain--success{ + color:$u-button-text-plain-success-color; + } + + &__text--plain--info { + color:$u-button-text-plain-info-color; + } + + &__text--plain--primary { + color:$u-button-text-plain-primary-color; + } +} \ No newline at end of file diff --git a/src/uni_modules/uview-plus/components/u-button/props.js b/src/uni_modules/uview-plus/components/u-button/props.js new file mode 100644 index 00000000..d01f0ab2 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-button/props.js @@ -0,0 +1,154 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否细边框 + hairline: { + type: Boolean, + default: () => defProps.button.hairline + }, + // 按钮的预置样式,info,primary,error,warning,success + type: { + type: String, + default: () => defProps.button.type + }, + // 按钮尺寸,large,normal,small,mini + size: { + type: String, + default: () => defProps.button.size + }, + // 按钮形状,circle(两边为半圆),square(带圆角) + shape: { + type: String, + default: () => defProps.button.shape + }, + // 按钮是否镂空 + plain: { + type: Boolean, + default: () => defProps.button.plain + }, + // 是否禁止状态 + disabled: { + type: Boolean, + default: () => defProps.button.disabled + }, + // 是否加载中 + loading: { + type: Boolean, + default: () => defProps.button.loading + }, + // 加载中提示文字 + loadingText: { + type: [String, Number], + default: () => defProps.button.loadingText + }, + // 加载状态图标类型 + loadingMode: { + type: String, + default: () => defProps.button.loadingMode + }, + // 加载图标大小 + loadingSize: { + type: [String, Number], + default: () => defProps.button.loadingSize + }, + // 开放能力,具体请看uniapp稳定关于button组件部分说明 + // https://uniapp.dcloud.io/component/button + openType: { + type: String, + default: () => defProps.button.openType + }, + // 用于
组件,点击分别会触发 组件的 submit/reset 事件 + // 取值为submit(提交表单),reset(重置表单) + formType: { + type: String, + default: () => defProps.button.formType + }, + // 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 + // 只微信小程序、QQ小程序有效 + appParameter: { + type: String, + default: () => defProps.button.appParameter + }, + // 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效 + hoverStopPropagation: { + type: Boolean, + default: () => defProps.button.hoverStopPropagation + }, + // 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效 + lang: { + type: String, + default: () => defProps.button.lang + }, + // 会话来源,open-type="contact"时有效。只微信小程序有效 + sessionFrom: { + type: String, + default: () => defProps.button.sessionFrom + }, + // 会话内消息卡片标题,open-type="contact"时有效 + // 默认当前标题,只微信小程序有效 + sendMessageTitle: { + type: String, + default: () => defProps.button.sendMessageTitle + }, + // 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 + // 默认当前分享路径,只微信小程序有效 + sendMessagePath: { + type: String, + default: () => defProps.button.sendMessagePath + }, + // 会话内消息卡片图片,open-type="contact"时有效 + // 默认当前页面截图,只微信小程序有效 + sendMessageImg: { + type: String, + default: () => defProps.button.sendMessageImg + }, + // 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示, + // 用户点击后可以快速发送小程序消息,open-type="contact"时有效 + showMessageCard: { + type: Boolean, + default: () => defProps.button.showMessageCard + }, + // 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取 + dataName: { + type: String, + default: () => defProps.button.dataName + }, + // 节流,一定时间内只能触发一次 + throttleTime: { + type: [String, Number], + default: () => defProps.button.throttleTime + }, + // 按住后多久出现点击态,单位毫秒 + hoverStartTime: { + type: [String, Number], + default: () => defProps.button.hoverStartTime + }, + // 手指松开后点击态保留时间,单位毫秒 + hoverStayTime: { + type: [String, Number], + default: () => defProps.button.hoverStayTime + }, + // 按钮文字,之所以通过props传入,是因为slot传入的话 + // nvue中无法控制文字的样式 + text: { + type: [String, Number], + default: () => defProps.button.text + }, + // 按钮图标 + icon: { + type: String, + default: () => defProps.button.icon + }, + // 按钮图标 + iconColor: { + type: String, + default: () => defProps.button.icon + }, + // 按钮颜色,支持传入linear-gradient渐变色 + color: { + type: String, + default: () => defProps.button.color + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-button/u-button.vue b/src/uni_modules/uview-plus/components/u-button/u-button.vue new file mode 100644 index 00000000..77f55682 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-button/u-button.vue @@ -0,0 +1,503 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-button/vue.scss b/src/uni_modules/uview-plus/components/u-button/vue.scss new file mode 100644 index 00000000..ceb6cea6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-button/vue.scss @@ -0,0 +1,81 @@ +// nvue下hover-class无效 +$u-button-before-top:50% !default; +$u-button-before-left:50% !default; +$u-button-before-width:100% !default; +$u-button-before-height:100% !default; +$u-button-before-transform:translate(-50%, -50%) !default; +$u-button-before-opacity:0 !default; +$u-button-before-background-color:#000 !default; +$u-button-before-border-color:#000 !default; +$u-button-active-before-opacity:.15 !default; +$u-button-icon-margin-left:4px !default; +$u-button-plain-u-button-info-color:$u-info; +$u-button-plain-u-button-success-color:$u-success; +$u-button-plain-u-button-error-color:$u-error; +$u-button-plain-u-button-warning-color:$u-error; + +.u-button { + width: 100%; + white-space: nowrap; + + &__text { + white-space: nowrap; + line-height: 1; + } + + &:before { + position: absolute; + top:$u-button-before-top; + left:$u-button-before-left; + width:$u-button-before-width; + height:$u-button-before-height; + border: inherit; + border-radius: inherit; + transform:$u-button-before-transform; + opacity:$u-button-before-opacity; + content: " "; + background-color:$u-button-before-background-color; + border-color:$u-button-before-border-color; + } + + &--active { + &:before { + opacity: .15 + } + } + + &__icon+&__text:not(:empty), + &__loading-text { + margin-left:$u-button-icon-margin-left; + } + + &--plain { + &.u-button--primary { + color: $u-primary; + } + } + + &--plain { + &.u-button--info { + color:$u-button-plain-u-button-info-color; + } + } + + &--plain { + &.u-button--success { + color:$u-button-plain-u-button-success-color; + } + } + + &--plain { + &.u-button--error { + color:$u-button-plain-u-button-error-color; + } + } + + &--plain { + &.u-button--warning { + color:$u-button-plain-u-button-warning-color; + } + } +} diff --git a/src/uni_modules/uview-plus/components/u-calendar/header.vue b/src/uni_modules/uview-plus/components/u-calendar/header.vue new file mode 100644 index 00000000..ccfe18b1 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-calendar/header.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-calendar/month.vue b/src/uni_modules/uview-plus/components/u-calendar/month.vue new file mode 100644 index 00000000..60623886 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-calendar/month.vue @@ -0,0 +1,585 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-calendar/props.js b/src/uni_modules/uview-plus/components/u-calendar/props.js new file mode 100644 index 00000000..df990fd6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-calendar/props.js @@ -0,0 +1,147 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 日历顶部标题 + title: { + type: String, + default: () => defProps.calendar.title + }, + // 是否显示标题 + showTitle: { + type: Boolean, + default: () => defProps.calendar.showTitle + }, + // 是否显示副标题 + showSubtitle: { + type: Boolean, + default: () => defProps.calendar.showSubtitle + }, + // 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 + mode: { + type: String, + default: () => defProps.calendar.mode + }, + // mode=range时,第一个日期底部的提示文字 + startText: { + type: String, + default: () => defProps.calendar.startText + }, + // mode=range时,最后一个日期底部的提示文字 + endText: { + type: String, + default: () => defProps.calendar.endText + }, + // 自定义列表 + customList: { + type: Array, + default: () => defProps.calendar.customList + }, + // 主题色,对底部按钮和选中日期有效 + color: { + type: String, + default: () => defProps.calendar.color + }, + // 最小的可选日期 + minDate: { + type: [String, Number], + default: () => defProps.calendar.minDate + }, + // 最大可选日期 + maxDate: { + type: [String, Number], + default: () => defProps.calendar.maxDate + }, + // 默认选中的日期,mode为multiple或range是必须为数组格式 + defaultDate: { + type: [Array, String, Date, null], + default: () => defProps.calendar.defaultDate + }, + // mode=multiple时,最多可选多少个日期 + maxCount: { + type: [String, Number], + default: () => defProps.calendar.maxCount + }, + // 日期行高 + rowHeight: { + type: [String, Number], + default: () => defProps.calendar.rowHeight + }, + // 日期格式化函数 + formatter: { + type: [Function, null], + default: () => defProps.calendar.formatter + }, + // 是否显示农历 + showLunar: { + type: Boolean, + default: () => defProps.calendar.showLunar + }, + // 是否显示月份背景色 + showMark: { + type: Boolean, + default: () => defProps.calendar.showMark + }, + // 确定按钮的文字 + confirmText: { + type: String, + default: () => defProps.calendar.confirmText + }, + // 确认按钮处于禁用状态时的文字 + confirmDisabledText: { + type: String, + default: () => defProps.calendar.confirmDisabledText + }, + // 是否显示日历弹窗 + show: { + type: Boolean, + default: () => defProps.calendar.show + }, + // 是否允许点击遮罩关闭日历 + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.calendar.closeOnClickOverlay + }, + // 是否为只读状态,只读状态下禁止选择日期 + readonly: { + type: Boolean, + default: () => defProps.calendar.readonly + }, + // 是否展示确认按钮 + showConfirm: { + type: Boolean, + default: () => defProps.calendar.showConfirm + }, + // 日期区间最多可选天数,默认无限制,mode = range时有效 + maxRange: { + type: [Number, String], + default: () => defProps.calendar.maxRange + }, + // 范围选择超过最多可选天数时的提示文案,mode = range时有效 + rangePrompt: { + type: String, + default: () => defProps.calendar.rangePrompt + }, + // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 + showRangePrompt: { + type: Boolean, + default: () => defProps.calendar.showRangePrompt + }, + // 是否允许日期范围的起止时间为同一天,mode = range时有效 + allowSameDay: { + type: Boolean, + default: () => defProps.calendar.allowSameDay + }, + // 圆角值 + round: { + type: [Boolean, String, Number], + default: () => defProps.calendar.round + }, + // 最多展示月份数量 + monthNum: { + type: [Number, String], + default: 3 + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-calendar/u-calendar.vue b/src/uni_modules/uview-plus/components/u-calendar/u-calendar.vue new file mode 100644 index 00000000..c8f77ff6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-calendar/u-calendar.vue @@ -0,0 +1,409 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-calendar/util.js b/src/uni_modules/uview-plus/components/u-calendar/util.js new file mode 100644 index 00000000..18762c18 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-calendar/util.js @@ -0,0 +1,86 @@ +import dayjs from 'dayjs/esm/index' +export default { + methods: { + // 设置月份数据 + setMonth() { + // 月初是周几 + const day = dayjs(this.date).date(1).day() + const start = day == 0 ? 6 : day - 1 + + // 本月天数 + const days = dayjs(this.date).endOf('month').format('D') + + // 上个月天数 + const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') + + // 日期数据 + const arr = [] + // 清空表格 + this.month = [] + + // 添加上月数据 + arr.push( + ...new Array(start).fill(1).map((e, i) => { + const day = prevDays - start + i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加本月数据 + arr.push( + ...new Array(days - 0).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + date: dayjs(this.date).date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加下个月 + arr.push( + ...new Array(42 - days - start).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 分割数组 + for (let n = 0; n < arr.length; n += 7) { + this.month.push( + arr.slice(n, n + 7).map((e, i) => { + e.index = i + n + + // 自定义信息 + const custom = this.customList.find((c) => c.date == e.date) + + // 农历 + if (this.lunar) { + const { + IDayCn, + IMonthCn + } = this.getLunar(e.date) + e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn + } + + return { + ...e, + ...custom + } + }) + ) + } + } + } +} diff --git a/src/uni_modules/uview-plus/components/u-car-keyboard/props.js b/src/uni_modules/uview-plus/components/u-car-keyboard/props.js new file mode 100644 index 00000000..7cca0ae5 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-car-keyboard/props.js @@ -0,0 +1,17 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: false + }, + // 输入一个中文后,是否自动切换到英文 + autoChange: { + type: Boolean, + default: false + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue b/src/uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue new file mode 100644 index 00000000..347885e9 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue @@ -0,0 +1,315 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-cell-group/props.js b/src/uni_modules/uview-plus/components/u-cell-group/props.js new file mode 100644 index 00000000..59c2012e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-cell-group/props.js @@ -0,0 +1,16 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 分组标题 + title: { + type: String, + default: () => defProps.cellGroup.title + }, + // 是否显示外边框 + border: { + type: Boolean, + default: () => defProps.cellGroup.border + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue b/src/uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue new file mode 100644 index 00000000..40ed2ddd --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue @@ -0,0 +1,67 @@ + + + + + + diff --git a/src/uni_modules/uview-plus/components/u-cell/props.js b/src/uni_modules/uview-plus/components/u-cell/props.js new file mode 100644 index 00000000..73f52106 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-cell/props.js @@ -0,0 +1,112 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 标题 + title: { + type: [String, Number], + default: () => defProps.cell.title + }, + // 标题下方的描述信息 + label: { + type: [String, Number], + default: () => defProps.cell.label + }, + // 右侧的内容 + value: { + type: [String, Number], + default: () => defProps.cell.value + }, + // 左侧图标名称,或者图片链接(本地文件建议使用绝对地址) + icon: { + type: String, + default: () => defProps.cell.icon + }, + // 是否禁用cell + disabled: { + type: Boolean, + default: () => defProps.cell.disabled + }, + // 是否显示下边框 + border: { + type: Boolean, + default: () => defProps.cell.border + }, + // 内容是否垂直居中(主要是针对右侧的value部分) + center: { + type: Boolean, + default: () => defProps.cell.center + }, + // 点击后跳转的URL地址 + url: { + type: String, + default: () => defProps.cell.url + }, + // 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 + linkType: { + type: String, + default: () => defProps.cell.linkType + }, + // 是否开启点击反馈(表现为点击时加上灰色背景) + clickable: { + type: Boolean, + default: () => defProps.cell.clickable + }, + // 是否展示右侧箭头并开启点击反馈 + isLink: { + type: Boolean, + default: () => defProps.cell.isLink + }, + // 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) + required: { + type: Boolean, + default: () => defProps.cell.required + }, + // 右侧的图标箭头 + rightIcon: { + type: String, + default: () => defProps.cell.rightIcon + }, + // 右侧箭头的方向,可选值为:left,up,down + arrowDirection: { + type: String, + default: () => defProps.cell.arrowDirection + }, + // 左侧图标样式 + iconStyle: { + type: [Object, String], + default: () => { + return defProps.cell.iconStyle + } + }, + // 右侧箭头图标的样式 + rightIconStyle: { + type: [Object, String], + default: () => { + return defProps.cell.rightIconStyle + } + }, + // 标题的样式 + titleStyle: { + type: [Object, String], + default: () => { + return defProps.cell.titleStyle + } + }, + // 单位元的大小,可选值为large + size: { + type: String, + default: () => defProps.cell.size + }, + // 点击cell是否阻止事件传播 + stop: { + type: Boolean, + default: () => defProps.cell.stop + }, + // 标识符,cell被点击时返回 + name: { + type: [Number, String], + default: () => defProps.cell.name + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-cell/u-cell.vue b/src/uni_modules/uview-plus/components/u-cell/u-cell.vue new file mode 100644 index 00000000..66f48be5 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-cell/u-cell.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-checkbox-group/props.js b/src/uni_modules/uview-plus/components/u-checkbox-group/props.js new file mode 100644 index 00000000..222d184b --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-checkbox-group/props.js @@ -0,0 +1,93 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 标识符 + name: { + type: String, + default: () => defProps.checkboxGroup.name + }, + // #ifdef VUE3 + // 绑定的值 + modelValue: { + type: Array, + default: () => defProps.checkboxGroup.value + }, + // #endif + // #ifdef VUE2 + // 绑定的值 + value: { + type: Array, + default: () => defProps.checkboxGroup.value + }, + // #endif + // 形状,circle-圆形,square-方形 + shape: { + type: String, + default: () => defProps.checkboxGroup.shape + }, + // 是否禁用全部checkbox + disabled: { + type: Boolean, + default: () => defProps.checkboxGroup.disabled + }, + + // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 + activeColor: { + type: String, + default: () => defProps.checkboxGroup.activeColor + }, + // 未选中的颜色 + inactiveColor: { + type: String, + default: () => defProps.checkboxGroup.inactiveColor + }, + + // 整个组件的尺寸,默认px + size: { + type: [String, Number], + default: () => defProps.checkboxGroup.size + }, + // 布局方式,row-横向,column-纵向 + placement: { + type: String, + default: () => defProps.checkboxGroup.placement + }, + // label的字体大小,px单位 + labelSize: { + type: [String, Number], + default: () => defProps.checkboxGroup.labelSize + }, + // label的字体颜色 + labelColor: { + type: [String], + default: () => defProps.checkboxGroup.labelColor + }, + // 是否禁止点击文本操作 + labelDisabled: { + type: Boolean, + default: () => defProps.checkboxGroup.labelDisabled + }, + // 图标颜色 + iconColor: { + type: String, + default: () => defProps.checkboxGroup.iconColor + }, + // 图标的大小,单位px + iconSize: { + type: [String, Number], + default: () => defProps.checkboxGroup.iconSize + }, + // 勾选图标的对齐方式,left-左边,right-右边 + iconPlacement: { + type: String, + default: () => defProps.checkboxGroup.iconPlacement + }, + // 竖向配列时,是否显示下划线 + borderBottom: { + type: Boolean, + default: () => defProps.checkboxGroup.borderBottom + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue b/src/uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue new file mode 100644 index 00000000..0640d858 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-checkbox/props.js b/src/uni_modules/uview-plus/components/u-checkbox/props.js new file mode 100644 index 00000000..66d8150d --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-checkbox/props.js @@ -0,0 +1,76 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // checkbox的名称 + name: { + type: [String, Number, Boolean], + default: () => defProps.checkbox.name + }, + // 形状,square为方形,circle为圆型 + shape: { + type: String, + default: () => defProps.checkbox.shape + }, + // 整体的大小 + size: { + type: [String, Number], + default: () => defProps.checkbox.size + }, + // 是否默认选中 + checked: { + type: Boolean, + default: () => defProps.checkbox.checked + }, + // 是否禁用 + disabled: { + type: [String, Boolean], + default: () => defProps.checkbox.disabled + }, + // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 + activeColor: { + type: String, + default: () => defProps.checkbox.activeColor + }, + // 未选中的颜色 + inactiveColor: { + type: String, + default: () => defProps.checkbox.inactiveColor + }, + // 图标的大小,单位px + iconSize: { + type: [String, Number], + default: () => defProps.checkbox.iconSize + }, + // 图标颜色 + iconColor: { + type: String, + default: () => defProps.checkbox.iconColor + }, + // label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 + label: { + type: [String, Number], + default: () => defProps.checkbox.label + }, + // label的字体大小,px单位 + labelSize: { + type: [String, Number], + default: () => defProps.checkbox.labelSize + }, + // label的颜色 + labelColor: { + type: String, + default: () => defProps.checkbox.labelColor + }, + // 是否禁止点击提示语选中复选框 + labelDisabled: { + type: [String, Boolean], + default: () => defProps.checkbox.labelDisabled + }, + // 是否独立使用 + usedAlone: { + type: [Boolean], + default: () => false + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue b/src/uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue new file mode 100644 index 00000000..0abee51c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue @@ -0,0 +1,376 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-circle-progress/props.js b/src/uni_modules/uview-plus/components/u-circle-progress/props.js new file mode 100644 index 00000000..ff1eeaa7 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-circle-progress/props.js @@ -0,0 +1,10 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + percentage: { + type: [String, Number], + default: () => defProps.circleProgress.percentage + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue b/src/uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue new file mode 100644 index 00000000..6dd5c93c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-code-input/props.js b/src/uni_modules/uview-plus/components/u-code-input/props.js new file mode 100644 index 00000000..0a4b1e81 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-code-input/props.js @@ -0,0 +1,90 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 键盘弹起时,是否自动上推页面 + adjustPosition: { + type: Boolean, + default: () => defProps.codeInput.adjustPosition + }, + // 最大输入长度 + maxlength: { + type: [String, Number], + default: () => defProps.codeInput.maxlength + }, + // 是否用圆点填充 + dot: { + type: Boolean, + default: () => defProps.codeInput.dot + }, + // 显示模式,box-盒子模式,line-底部横线模式 + mode: { + type: String, + default: () => defProps.codeInput.mode + }, + // 是否细边框 + hairline: { + type: Boolean, + default: () => defProps.codeInput.hairline + }, + // 字符间的距离 + space: { + type: [String, Number], + default: () => defProps.codeInput.space + }, + // #ifdef VUE3 + // 预置值 + modelValue: { + type: [String, Number], + default: () => defProps.codeInput.value + }, + // #endif + // #ifdef VUE2 + // 预置值 + value: { + type: [String, Number], + default: () => defProps.codeInput.value + }, + // #endif + // 是否自动获取焦点 + focus: { + type: Boolean, + default: () => defProps.codeInput.focus + }, + // 字体是否加粗 + bold: { + type: Boolean, + default: () => defProps.codeInput.bold + }, + // 字体颜色 + color: { + type: String, + default: () => defProps.codeInput.color + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.codeInput.fontSize + }, + // 输入框的大小,宽等于高 + size: { + type: [String, Number], + default: () => defProps.codeInput.size + }, + // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true + disabledKeyboard: { + type: Boolean, + default: () => defProps.codeInput.disabledKeyboard + }, + // 边框和线条颜色 + borderColor: { + type: String, + default: () => defProps.codeInput.borderColor + }, + // 是否禁止输入"."符号 + disabledDot: { + type: Boolean, + default: () => defProps.codeInput.disabledDot + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-code-input/u-code-input.vue b/src/uni_modules/uview-plus/components/u-code-input/u-code-input.vue new file mode 100644 index 00000000..9504ddad --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-code-input/u-code-input.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-code/props.js b/src/uni_modules/uview-plus/components/u-code/props.js new file mode 100644 index 00000000..60977b57 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-code/props.js @@ -0,0 +1,36 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 倒计时总秒数 + seconds: { + type: [String, Number], + default: () => defProps.code.seconds + }, + // 尚未开始时提示 + startText: { + type: String, + default: () => defProps.code.startText + }, + // 正在倒计时中的提示 + changeText: { + type: String, + default: () => defProps.code.changeText + }, + // 倒计时结束时的提示 + endText: { + type: String, + default: () => defProps.code.endText + }, + // 是否在H5刷新或各端返回再进入时继续倒计时 + keepRunning: { + type: Boolean, + default: () => defProps.code.keepRunning + }, + // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了 + uniqueKey: { + type: String, + default: () => defProps.code.uniqueKey + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-code/u-code.vue b/src/uni_modules/uview-plus/components/u-code/u-code.vue new file mode 100644 index 00000000..c0fc992a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-code/u-code.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-col/props.js b/src/uni_modules/uview-plus/components/u-col/props.js new file mode 100644 index 00000000..b28decb6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-col/props.js @@ -0,0 +1,31 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 占父容器宽度的多少等分,总分为12份 + span: { + type: [String, Number], + default: () => defProps.col.span + }, + // 指定栅格左侧的间隔数(总12栏) + offset: { + type: [String, Number], + default: () => defProps.col.offset + }, + // 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`) + justify: { + type: String, + default: () => defProps.col.justify + }, + // 垂直对齐方式,可选值为top、center、bottom、stretch + align: { + type: String, + default: () => defProps.col.align + }, + // 文字对齐方式 + textAlign: { + type: String, + default: () => defProps.col.textAlign + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-col/u-col.vue b/src/uni_modules/uview-plus/components/u-col/u-col.vue new file mode 100644 index 00000000..57a12d6e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-col/u-col.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-collapse-item/props.js b/src/uni_modules/uview-plus/components/u-collapse-item/props.js new file mode 100644 index 00000000..fdc923b5 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-collapse-item/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 标题 + title: { + type: String, + default: () => defProps.collapseItem.title + }, + // 标题右侧内容 + value: { + type: String, + default: () => defProps.collapseItem.value + }, + // 标题下方的描述信息 + label: { + type: String, + default: () => defProps.collapseItem.label + }, + // 是否禁用折叠面板 + disabled: { + type: Boolean, + default: () => defProps.collapseItem.disabled + }, + // 是否展示右侧箭头并开启点击反馈 + isLink: { + type: Boolean, + default: () => defProps.collapseItem.isLink + }, + // 是否开启点击反馈 + clickable: { + type: Boolean, + default: () => defProps.collapseItem.clickable + }, + // 是否显示内边框 + border: { + type: Boolean, + default: () => defProps.collapseItem.border + }, + // 标题的对齐方式 + align: { + type: String, + default: () => defProps.collapseItem.align + }, + // 唯一标识符 + name: { + type: [String, Number], + default: () => defProps.collapseItem.name + }, + // 标题左侧图片,可为绝对路径的图片或内置图标 + icon: { + type: String, + default: () => defProps.collapseItem.icon + }, + // 面板展开收起的过渡时间,单位ms + duration: { + type: Number, + default: () => defProps.collapseItem.duration + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue b/src/uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue new file mode 100644 index 00000000..7fa4b69b --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue @@ -0,0 +1,240 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-collapse/props.js b/src/uni_modules/uview-plus/components/u-collapse/props.js new file mode 100644 index 00000000..77126033 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-collapse/props.js @@ -0,0 +1,21 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 当前展开面板的name,非手风琴模式:[],手风琴模式:string | number + value: { + type: [String, Number, Array, null], + default: () => defProps.collapse.value + }, + // 是否手风琴模式 + accordion: { + type: Boolean, + default: () => defProps.collapse.accordion + }, + // 是否显示外边框 + border: { + type: Boolean, + default: () => defProps.collapse.border + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-collapse/u-collapse.vue b/src/uni_modules/uview-plus/components/u-collapse/u-collapse.vue new file mode 100644 index 00000000..f7ec7f7e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-collapse/u-collapse.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-column-notice/props.js b/src/uni_modules/uview-plus/components/u-column-notice/props.js new file mode 100644 index 00000000..ae1a3356 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-column-notice/props.js @@ -0,0 +1,57 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 显示的内容,字符串 + text: { + type: [Array], + default: () => defProps.columnNotice.text + }, + // 是否显示左侧的音量图标 + icon: { + type: String, + default: () => defProps.columnNotice.icon + }, + // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 + mode: { + type: String, + default: () => defProps.columnNotice.mode + }, + // 文字颜色,各图标也会使用文字颜色 + color: { + type: String, + default: () => defProps.columnNotice.color + }, + // 背景颜色 + bgColor: { + type: String, + default: () => defProps.columnNotice.bgColor + }, + // 字体大小,单位px + fontSize: { + type: [String, Number], + default: () => defProps.columnNotice.fontSize + }, + // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 + speed: { + type: [String, Number], + default: () => defProps.columnNotice.speed + }, + // direction = row时,是否使用步进形式滚动 + step: { + type: Boolean, + default: () => defProps.columnNotice.step + }, + // 滚动一个周期的时间长,单位ms + duration: { + type: [String, Number], + default: () => defProps.columnNotice.duration + }, + // 是否禁止用手滑动切换 + // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 + disableTouch: { + type: Boolean, + default: () => defProps.columnNotice.disableTouch + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-column-notice/u-column-notice.vue b/src/uni_modules/uview-plus/components/u-column-notice/u-column-notice.vue new file mode 100644 index 00000000..5e2507f8 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-column-notice/u-column-notice.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-copy/u-copy.vue b/src/uni_modules/uview-plus/components/u-copy/u-copy.vue new file mode 100644 index 00000000..7e63ded6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-copy/u-copy.vue @@ -0,0 +1,70 @@ + + + + diff --git a/src/uni_modules/uview-plus/components/u-count-down/props.js b/src/uni_modules/uview-plus/components/u-count-down/props.js new file mode 100644 index 00000000..6dbf1c21 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-count-down/props.js @@ -0,0 +1,26 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 倒计时时长,单位ms + time: { + type: [String, Number], + default: () => defProps.countDown.time + }, + // 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 + format: { + type: String, + default: () => defProps.countDown.format + }, + // 是否自动开始倒计时 + autoStart: { + type: Boolean, + default: () => defProps.countDown.autoStart + }, + // 是否展示毫秒倒计时 + millisecond: { + type: Boolean, + default: () => defProps.countDown.millisecond + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-count-down/u-count-down.vue b/src/uni_modules/uview-plus/components/u-count-down/u-count-down.vue new file mode 100644 index 00000000..5720757a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-count-down/u-count-down.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-count-down/utils.js b/src/uni_modules/uview-plus/components/u-count-down/utils.js new file mode 100644 index 00000000..8c750050 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-count-down/utils.js @@ -0,0 +1,62 @@ +// 补0,如1 -> 01 +function padZero(num, targetLength = 2) { + let str = `${num}` + while (str.length < targetLength) { + str = `0${str}` + } + return str +} +const SECOND = 1000 +const MINUTE = 60 * SECOND +const HOUR = 60 * MINUTE +const DAY = 24 * HOUR +export function parseTimeData(time) { + const days = Math.floor(time / DAY) + const hours = Math.floor((time % DAY) / HOUR) + const minutes = Math.floor((time % HOUR) / MINUTE) + const seconds = Math.floor((time % MINUTE) / SECOND) + const milliseconds = Math.floor(time % SECOND) + return { + days, + hours, + minutes, + seconds, + milliseconds + } +} +export function parseFormat(format, timeData) { + let { + days, + hours, + minutes, + seconds, + milliseconds + } = timeData + // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去 + if (format.indexOf('DD') === -1) { + hours += days * 24 + } else { + // 对天补0 + format = format.replace('DD', padZero(days)) + } + // 其他同理于DD的格式化处理方式 + if (format.indexOf('HH') === -1) { + minutes += hours * 60 + } else { + format = format.replace('HH', padZero(hours)) + } + if (format.indexOf('mm') === -1) { + seconds += minutes * 60 + } else { + format = format.replace('mm', padZero(minutes)) + } + if (format.indexOf('ss') === -1) { + milliseconds += seconds * 1000 + } else { + format = format.replace('ss', padZero(seconds)) + } + return format.replace('SSS', padZero(milliseconds, 3)) +} +export function isSameSecond(time1, time2) { + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000) +} diff --git a/src/uni_modules/uview-plus/components/u-count-to/props.js b/src/uni_modules/uview-plus/components/u-count-to/props.js new file mode 100644 index 00000000..0b97c1f1 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-count-to/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 开始的数值,默认从0增长到某一个数 + startVal: { + type: [String, Number], + default: () => defProps.countTo.startVal + }, + // 要滚动的目标数值,必须 + endVal: { + type: [String, Number], + default: () => defProps.countTo.endVal + }, + // 滚动到目标数值的动画持续时间,单位为毫秒(ms) + duration: { + type: [String, Number], + default: () => defProps.countTo.duration + }, + // 设置数值后是否自动开始滚动 + autoplay: { + type: Boolean, + default: () => defProps.countTo.autoplay + }, + // 要显示的小数位数 + decimals: { + type: [String, Number], + default: () => defProps.countTo.decimals + }, + // 是否在即将到达目标数值的时候,使用缓慢滚动的效果 + useEasing: { + type: Boolean, + default: () => defProps.countTo.useEasing + }, + // 十进制分割 + decimal: { + type: [String, Number], + default: () => defProps.countTo.decimal + }, + // 字体颜色 + color: { + type: String, + default: () => defProps.countTo.color + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.countTo.fontSize + }, + // 是否加粗字体 + bold: { + type: Boolean, + default: () => defProps.countTo.bold + }, + // 千位分隔符,类似金额的分割(¥23,321.05中的",") + separator: { + type: String, + default: () => defProps.countTo.separator + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-count-to/u-count-to.vue b/src/uni_modules/uview-plus/components/u-count-to/u-count-to.vue new file mode 100644 index 00000000..83ab13d6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-count-to/u-count-to.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-datetime-picker/props.js b/src/uni_modules/uview-plus/components/u-datetime-picker/props.js new file mode 100644 index 00000000..97c6e3a4 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-datetime-picker/props.js @@ -0,0 +1,145 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否显示input + hasInput: { + type: Boolean, + default: () => false + }, + placeholder: { + type: String, + default: () => '请选择' + }, + format: { + type: String, + default: () => '' + }, + // 是否打开组件 + show: { + type: Boolean, + default: () => defProps.datetimePicker.show + }, + // 弹出的方向,可选值为 top bottom right left center + popupMode: { + type: String, + default: () => defProps.picker.popupMode + }, + // 是否展示顶部的操作栏 + showToolbar: { + type: Boolean, + default: () => defProps.datetimePicker.showToolbar + }, + // #ifdef VUE2 + // 绑定值 + value: { + type: [String, Number], + default: () => defProps.datetimePicker.value + }, + // #endif + // #ifdef VUE3 + // 绑定值 + modelValue: { + type: [String, Number], + default: () => defProps.datetimePicker.value + }, + // #endif + // 顶部标题 + title: { + type: String, + default: () => defProps.datetimePicker.title + }, + // 展示格式,mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择 + mode: { + type: String, + default: () => defProps.datetimePicker.mode + }, + // 可选的最大时间 + maxDate: { + type: Number, + // 最大默认值为后10年 + default: () => defProps.datetimePicker.maxDate + }, + // 可选的最小时间 + minDate: { + type: Number, + // 最小默认值为前10年 + default: () => defProps.datetimePicker.minDate + }, + // 可选的最小小时,仅mode=time有效 + minHour: { + type: Number, + default: () => defProps.datetimePicker.minHour + }, + // 可选的最大小时,仅mode=time有效 + maxHour: { + type: Number, + default: () => defProps.datetimePicker.maxHour + }, + // 可选的最小分钟,仅mode=time有效 + minMinute: { + type: Number, + default: () => defProps.datetimePicker.minMinute + }, + // 可选的最大分钟,仅mode=time有效 + maxMinute: { + type: Number, + default: () => defProps.datetimePicker.maxMinute + }, + // 选项过滤函数 + filter: { + type: [Function, null], + default: () => defProps.datetimePicker.filter + }, + // 选项格式化函数 + formatter: { + type: [Function, null], + default: () => defProps.datetimePicker.formatter + }, + // 是否显示加载中状态 + loading: { + type: Boolean, + default: () => defProps.datetimePicker.loading + }, + // 各列中,单个选项的高度 + itemHeight: { + type: [String, Number], + default: () => defProps.datetimePicker.itemHeight + }, + // 取消按钮的文字 + cancelText: { + type: String, + default: () => defProps.datetimePicker.cancelText + }, + // 确认按钮的文字 + confirmText: { + type: String, + default: () => defProps.datetimePicker.confirmText + }, + // 取消按钮的颜色 + cancelColor: { + type: String, + default: () => defProps.datetimePicker.cancelColor + }, + // 确认按钮的颜色 + confirmColor: { + type: String, + default: () => defProps.datetimePicker.confirmColor + }, + // 每列中可见选项的数量 + visibleItemCount: { + type: [String, Number], + default: () => defProps.datetimePicker.visibleItemCount + }, + // 是否允许点击遮罩关闭选择器 + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.datetimePicker.closeOnClickOverlay + }, + // 各列的默认索引 + defaultIndex: { + type: Array, + default: () => defProps.datetimePicker.defaultIndex + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-datetime-picker/u-datetime-picker.vue b/src/uni_modules/uview-plus/components/u-datetime-picker/u-datetime-picker.vue new file mode 100644 index 00000000..ca33e86e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-datetime-picker/u-datetime-picker.vue @@ -0,0 +1,455 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-divider/props.js b/src/uni_modules/uview-plus/components/u-divider/props.js new file mode 100644 index 00000000..ec3fd8f6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-divider/props.js @@ -0,0 +1,46 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否虚线 + dashed: { + type: Boolean, + default: () => defProps.divider.dashed + }, + // 是否细线 + hairline: { + type: Boolean, + default: () => defProps.divider.hairline + }, + // 是否以点替代文字,优先于text字段起作用 + dot: { + type: Boolean, + default: () => defProps.divider.dot + }, + // 内容文本的位置,left-左边,center-中间,right-右边 + textPosition: { + type: String, + default: () => defProps.divider.textPosition + }, + // 文本内容 + text: { + type: [String, Number], + default: () => defProps.divider.text + }, + // 文本大小 + textSize: { + type: [String, Number], + default: () => defProps.divider.textSize + }, + // 文本颜色 + textColor: { + type: String, + default: () => defProps.divider.textColor + }, + // 线条颜色 + lineColor: { + type: String, + default: () => defProps.divider.lineColor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-divider/u-divider.vue b/src/uni_modules/uview-plus/components/u-divider/u-divider.vue new file mode 100644 index 00000000..47dbf008 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-divider/u-divider.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-dropdown-item/props.js b/src/uni_modules/uview-plus/components/u-dropdown-item/props.js new file mode 100644 index 00000000..e5e02656 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-dropdown-item/props.js @@ -0,0 +1,47 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // #ifdef VUE3 + // 当前选中项的value值 + modelValue: { + type: [Number, String, Array], + default: '' + }, + // #endif + // #ifdef VUE2 + // 当前选中项的value值 + value: { + type: [Number, String, Array], + default: '' + }, + // #endif + // 菜单项标题 + title: { + type: [String, Number], + default: '' + }, + // 选项数据,如果传入了默认slot,此参数无效 + options: { + type: Array, + default() { + return [] + } + }, + // 是否禁用此菜单项 + disabled: { + type: Boolean, + default: false + }, + // 下拉弹窗的高度 + height: { + type: [Number, String], + default: 'auto' + }, + // 点击遮罩是否可以收起弹窗 + closeOnClickOverlay: { + type: Boolean, + default: true + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-dropdown-item/u-dropdown-item.vue b/src/uni_modules/uview-plus/components/u-dropdown-item/u-dropdown-item.vue new file mode 100644 index 00000000..ec15a068 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-dropdown-item/u-dropdown-item.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-dropdown/props.js b/src/uni_modules/uview-plus/components/u-dropdown/props.js new file mode 100644 index 00000000..4614b966 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-dropdown/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 菜单标题和选项的激活态颜色 + activeColor: { + type: String, + default: '#2979ff' + }, + // 菜单标题和选项的未激活态颜色 + inactiveColor: { + type: String, + default: '#606266' + }, + // 点击遮罩是否关闭菜单 + closeOnClickMask: { + type: Boolean, + default: true + }, + // 点击当前激活项标题是否关闭菜单 + closeOnClickSelf: { + type: Boolean, + default: true + }, + // 过渡时间 + duration: { + type: [Number, String], + default: 300 + }, + // 标题菜单的高度 + height: { + type: [Number, String], + default: 40 + }, + // 是否显示下边框 + borderBottom: { + type: Boolean, + default: false + }, + // 标题的字体大小 + titleSize: { + type: [Number, String], + default: 14 + }, + // 下拉出来的内容部分的圆角值 + borderRadius: { + type: [Number, String], + default: 0 + }, + // 菜单右侧的icon图标 + menuIcon: { + type: String, + default: 'arrow-down' + }, + // 菜单右侧图标的大小 + menuIconSize: { + type: [Number, String], + default: 14 + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-dropdown/u-dropdown.vue b/src/uni_modules/uview-plus/components/u-dropdown/u-dropdown.vue new file mode 100644 index 00000000..46479a37 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-dropdown/u-dropdown.vue @@ -0,0 +1,254 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-empty/props.js b/src/uni_modules/uview-plus/components/u-empty/props.js new file mode 100644 index 00000000..40edd11c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-empty/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 内置图标名称,或图片路径,建议绝对路径 + icon: { + type: String, + default: () => defProps.empty.icon + }, + // 提示文字 + text: { + type: String, + default: () => defProps.empty.text + }, + // 文字颜色 + textColor: { + type: String, + default: () => defProps.empty.textColor + }, + // 文字大小 + textSize: { + type: [String, Number], + default: () => defProps.empty.textSize + }, + // 图标的颜色 + iconColor: { + type: String, + default: () => defProps.empty.iconColor + }, + // 图标的大小 + iconSize: { + type: [String, Number], + default: () => defProps.empty.iconSize + }, + // 选择预置的图标类型 + mode: { + type: String, + default: () => defProps.empty.mode + }, + // 图标宽度,单位px + width: { + type: [String, Number], + default: () => defProps.empty.width + }, + // 图标高度,单位px + height: { + type: [String, Number], + default: () => defProps.empty.height + }, + // 是否显示组件 + show: { + type: Boolean, + default: () => defProps.empty.show + }, + // 组件距离上一个元素之间的距离,默认px单位 + marginTop: { + type: [String, Number], + default: () => defProps.empty.marginTop + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-empty/u-empty.vue b/src/uni_modules/uview-plus/components/u-empty/u-empty.vue new file mode 100644 index 00000000..f83677f2 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-empty/u-empty.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-form-item/props.js b/src/uni_modules/uview-plus/components/u-form-item/props.js new file mode 100644 index 00000000..9402d37e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-form-item/props.js @@ -0,0 +1,55 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // input的label提示语 + label: { + type: String, + default: () => defProps.formItem.label + }, + // 绑定的值 + prop: { + type: String, + default: () => defProps.formItem.prop + }, + // 绑定的规则 + rule: { + type: String, + default: () => defProps.formItem.rule + }, + // 是否显示表单域的下划线边框 + borderBottom: { + type: [String, Boolean], + default: () => defProps.formItem.borderBottom + }, + // label的位置,left-左边,top-上边 + labelPosition: { + type: String, + default: () => defProps.formItem.labelPosition + }, + // label的宽度,单位px + labelWidth: { + type: [String, Number], + default: () => defProps.formItem.labelWidth + }, + // 右侧图标 + rightIcon: { + type: String, + default: () => defProps.formItem.rightIcon + }, + // 左侧图标 + leftIcon: { + type: String, + default: () => defProps.formItem.leftIcon + }, + // 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置 + required: { + type: Boolean, + default: () => defProps.formItem.required + }, + leftIconStyle: { + type: [String, Object], + default: () => defProps.formItem.leftIconStyle, + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-form-item/u-form-item.vue b/src/uni_modules/uview-plus/components/u-form-item/u-form-item.vue new file mode 100644 index 00000000..1151814c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-form-item/u-form-item.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-form/props.js b/src/uni_modules/uview-plus/components/u-form/props.js new file mode 100644 index 00000000..b80d6231 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-form/props.js @@ -0,0 +1,47 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 当前form的需要验证字段的集合 + model: { + type: Object, + default: () => defProps.form.model + }, + // 验证规则 + rules: { + type: [Object, Function, Array], + default: () => defProps.form.rules + }, + // 有错误时的提示方式,message-提示信息,toast-进行toast提示 + // border-bottom-下边框呈现红色,none-无提示 + errorType: { + type: String, + default: () => defProps.form.errorType + }, + // 是否显示表单域的下划线边框 + borderBottom: { + type: Boolean, + default: () => defProps.form.borderBottom + }, + // label的位置,left-左边,top-上边 + labelPosition: { + type: String, + default: () => defProps.form.labelPosition + }, + // label的宽度,单位px + labelWidth: { + type: [String, Number], + default: () => defProps.form.labelWidth + }, + // lable字体的对齐方式 + labelAlign: { + type: String, + default: () => defProps.form.labelAlign + }, + // lable的样式,对象形式 + labelStyle: { + type: Object, + default: () => defProps.form.labelStyle + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-form/u-form.vue b/src/uni_modules/uview-plus/components/u-form/u-form.vue new file mode 100644 index 00000000..373d1ff2 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-form/u-form.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-gap/props.js b/src/uni_modules/uview-plus/components/u-gap/props.js new file mode 100644 index 00000000..77b1d7ca --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-gap/props.js @@ -0,0 +1,26 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 背景颜色(默认transparent) + bgColor: { + type: String, + default: () => defProps.gap.bgColor + }, + // 分割槽高度,单位px(默认30) + height: { + type: [String, Number], + default: () => defProps.gap.height + }, + // 与上一个组件的距离 + marginTop: { + type: [String, Number], + default: () => defProps.gap.marginTop + }, + // 与下一个组件的距离 + marginBottom: { + type: [String, Number], + default: () => defProps.gap.marginBottom + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-gap/u-gap.vue b/src/uni_modules/uview-plus/components/u-gap/u-gap.vue new file mode 100644 index 00000000..36863a57 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-gap/u-gap.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-grid-item/props.js b/src/uni_modules/uview-plus/components/u-grid-item/props.js new file mode 100644 index 00000000..55f957c6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-grid-item/props.js @@ -0,0 +1,16 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 宫格的name + name: { + type: [String, Number, null], + default: () => defProps.gridItem.name + }, + // 背景颜色 + bgColor: { + type: String, + default: () => defProps.gridItem.bgColor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-grid-item/u-grid-item.vue b/src/uni_modules/uview-plus/components/u-grid-item/u-grid-item.vue new file mode 100644 index 00000000..89197aaa --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-grid-item/u-grid-item.vue @@ -0,0 +1,232 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-grid/props.js b/src/uni_modules/uview-plus/components/u-grid/props.js new file mode 100644 index 00000000..3d998447 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-grid/props.js @@ -0,0 +1,21 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 分成几列 + col: { + type: [String, Number], + default: () => defProps.grid.col + }, + // 是否显示边框 + border: { + type: Boolean, + default: () => defProps.grid.border + }, + // 宫格对齐方式,表现为数量少的时候,靠左,居中,还是靠右 + align: { + type: String, + default: () => defProps.grid.align + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-grid/u-grid.vue b/src/uni_modules/uview-plus/components/u-grid/u-grid.vue new file mode 100644 index 00000000..a650504f --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-grid/u-grid.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-icon/icons.js b/src/uni_modules/uview-plus/components/u-icon/icons.js new file mode 100644 index 00000000..f4d0fe29 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-icon/icons.js @@ -0,0 +1,214 @@ +export default { + 'uicon-level': '\ue693', + 'uicon-column-line': '\ue68e', + 'uicon-checkbox-mark': '\ue807', + 'uicon-folder': '\ue7f5', + 'uicon-movie': '\ue7f6', + 'uicon-star-fill': '\ue669', + 'uicon-star': '\ue65f', + 'uicon-phone-fill': '\ue64f', + 'uicon-phone': '\ue622', + 'uicon-apple-fill': '\ue881', + 'uicon-chrome-circle-fill': '\ue885', + 'uicon-backspace': '\ue67b', + 'uicon-attach': '\ue632', + 'uicon-cut': '\ue948', + 'uicon-empty-car': '\ue602', + 'uicon-empty-coupon': '\ue682', + 'uicon-empty-address': '\ue646', + 'uicon-empty-favor': '\ue67c', + 'uicon-empty-permission': '\ue686', + 'uicon-empty-news': '\ue687', + 'uicon-empty-search': '\ue664', + 'uicon-github-circle-fill': '\ue887', + 'uicon-rmb': '\ue608', + 'uicon-person-delete-fill': '\ue66a', + 'uicon-reload': '\ue788', + 'uicon-order': '\ue68f', + 'uicon-server-man': '\ue6bc', + 'uicon-search': '\ue62a', + 'uicon-fingerprint': '\ue955', + 'uicon-more-dot-fill': '\ue630', + 'uicon-scan': '\ue662', + 'uicon-share-square': '\ue60b', + 'uicon-map': '\ue61d', + 'uicon-map-fill': '\ue64e', + 'uicon-tags': '\ue629', + 'uicon-tags-fill': '\ue651', + 'uicon-bookmark-fill': '\ue63b', + 'uicon-bookmark': '\ue60a', + 'uicon-eye': '\ue613', + 'uicon-eye-fill': '\ue641', + 'uicon-mic': '\ue64a', + 'uicon-mic-off': '\ue649', + 'uicon-calendar': '\ue66e', + 'uicon-calendar-fill': '\ue634', + 'uicon-trash': '\ue623', + 'uicon-trash-fill': '\ue658', + 'uicon-play-left': '\ue66d', + 'uicon-play-right': '\ue610', + 'uicon-minus': '\ue618', + 'uicon-plus': '\ue62d', + 'uicon-info': '\ue653', + 'uicon-info-circle': '\ue7d2', + 'uicon-info-circle-fill': '\ue64b', + 'uicon-question': '\ue715', + 'uicon-error': '\ue6d3', + 'uicon-close': '\ue685', + 'uicon-checkmark': '\ue6a8', + 'uicon-android-circle-fill': '\ue67e', + 'uicon-android-fill': '\ue67d', + 'uicon-ie': '\ue87b', + 'uicon-IE-circle-fill': '\ue889', + 'uicon-google': '\ue87a', + 'uicon-google-circle-fill': '\ue88a', + 'uicon-setting-fill': '\ue872', + 'uicon-setting': '\ue61f', + 'uicon-minus-square-fill': '\ue855', + 'uicon-plus-square-fill': '\ue856', + 'uicon-heart': '\ue7df', + 'uicon-heart-fill': '\ue851', + 'uicon-camera': '\ue7d7', + 'uicon-camera-fill': '\ue870', + 'uicon-more-circle': '\ue63e', + 'uicon-more-circle-fill': '\ue645', + 'uicon-chat': '\ue620', + 'uicon-chat-fill': '\ue61e', + 'uicon-bag-fill': '\ue617', + 'uicon-bag': '\ue619', + 'uicon-error-circle-fill': '\ue62c', + 'uicon-error-circle': '\ue624', + 'uicon-close-circle': '\ue63f', + 'uicon-close-circle-fill': '\ue637', + 'uicon-checkmark-circle': '\ue63d', + 'uicon-checkmark-circle-fill': '\ue635', + 'uicon-question-circle-fill': '\ue666', + 'uicon-question-circle': '\ue625', + 'uicon-share': '\ue631', + 'uicon-share-fill': '\ue65e', + 'uicon-shopping-cart': '\ue621', + 'uicon-shopping-cart-fill': '\ue65d', + 'uicon-bell': '\ue609', + 'uicon-bell-fill': '\ue640', + 'uicon-list': '\ue650', + 'uicon-list-dot': '\ue616', + 'uicon-zhihu': '\ue6ba', + 'uicon-zhihu-circle-fill': '\ue709', + 'uicon-zhifubao': '\ue6b9', + 'uicon-zhifubao-circle-fill': '\ue6b8', + 'uicon-weixin-circle-fill': '\ue6b1', + 'uicon-weixin-fill': '\ue6b2', + 'uicon-twitter-circle-fill': '\ue6ab', + 'uicon-twitter': '\ue6aa', + 'uicon-taobao-circle-fill': '\ue6a7', + 'uicon-taobao': '\ue6a6', + 'uicon-weibo-circle-fill': '\ue6a5', + 'uicon-weibo': '\ue6a4', + 'uicon-qq-fill': '\ue6a1', + 'uicon-qq-circle-fill': '\ue6a0', + 'uicon-moments-circel-fill': '\ue69a', + 'uicon-moments': '\ue69b', + 'uicon-qzone': '\ue695', + 'uicon-qzone-circle-fill': '\ue696', + 'uicon-baidu-circle-fill': '\ue680', + 'uicon-baidu': '\ue681', + 'uicon-facebook-circle-fill': '\ue68a', + 'uicon-facebook': '\ue689', + 'uicon-car': '\ue60c', + 'uicon-car-fill': '\ue636', + 'uicon-warning-fill': '\ue64d', + 'uicon-warning': '\ue694', + 'uicon-clock-fill': '\ue638', + 'uicon-clock': '\ue60f', + 'uicon-edit-pen': '\ue612', + 'uicon-edit-pen-fill': '\ue66b', + 'uicon-email': '\ue611', + 'uicon-email-fill': '\ue642', + 'uicon-minus-circle': '\ue61b', + 'uicon-minus-circle-fill': '\ue652', + 'uicon-plus-circle': '\ue62e', + 'uicon-plus-circle-fill': '\ue661', + 'uicon-file-text': '\ue663', + 'uicon-file-text-fill': '\ue665', + 'uicon-pushpin': '\ue7e3', + 'uicon-pushpin-fill': '\ue86e', + 'uicon-grid': '\ue673', + 'uicon-grid-fill': '\ue678', + 'uicon-play-circle': '\ue647', + 'uicon-play-circle-fill': '\ue655', + 'uicon-pause-circle-fill': '\ue654', + 'uicon-pause': '\ue8fa', + 'uicon-pause-circle': '\ue643', + 'uicon-eye-off': '\ue648', + 'uicon-eye-off-outline': '\ue62b', + 'uicon-gift-fill': '\ue65c', + 'uicon-gift': '\ue65b', + 'uicon-rmb-circle-fill': '\ue657', + 'uicon-rmb-circle': '\ue677', + 'uicon-kefu-ermai': '\ue656', + 'uicon-server-fill': '\ue751', + 'uicon-coupon-fill': '\ue8c4', + 'uicon-coupon': '\ue8ae', + 'uicon-integral': '\ue704', + 'uicon-integral-fill': '\ue703', + 'uicon-home-fill': '\ue964', + 'uicon-home': '\ue965', + 'uicon-hourglass-half-fill': '\ue966', + 'uicon-hourglass': '\ue967', + 'uicon-account': '\ue628', + 'uicon-plus-people-fill': '\ue626', + 'uicon-minus-people-fill': '\ue615', + 'uicon-account-fill': '\ue614', + 'uicon-thumb-down-fill': '\ue726', + 'uicon-thumb-down': '\ue727', + 'uicon-thumb-up': '\ue733', + 'uicon-thumb-up-fill': '\ue72f', + 'uicon-lock-fill': '\ue979', + 'uicon-lock-open': '\ue973', + 'uicon-lock-opened-fill': '\ue974', + 'uicon-lock': '\ue97a', + 'uicon-red-packet-fill': '\ue690', + 'uicon-photo-fill': '\ue98b', + 'uicon-photo': '\ue98d', + 'uicon-volume-off-fill': '\ue659', + 'uicon-volume-off': '\ue644', + 'uicon-volume-fill': '\ue670', + 'uicon-volume': '\ue633', + 'uicon-red-packet': '\ue691', + 'uicon-download': '\ue63c', + 'uicon-arrow-up-fill': '\ue6b0', + 'uicon-arrow-down-fill': '\ue600', + 'uicon-play-left-fill': '\ue675', + 'uicon-play-right-fill': '\ue676', + 'uicon-rewind-left-fill': '\ue679', + 'uicon-rewind-right-fill': '\ue67a', + 'uicon-arrow-downward': '\ue604', + 'uicon-arrow-leftward': '\ue601', + 'uicon-arrow-rightward': '\ue603', + 'uicon-arrow-upward': '\ue607', + 'uicon-arrow-down': '\ue60d', + 'uicon-arrow-right': '\ue605', + 'uicon-arrow-left': '\ue60e', + 'uicon-arrow-up': '\ue606', + 'uicon-skip-back-left': '\ue674', + 'uicon-skip-forward-right': '\ue672', + 'uicon-rewind-right': '\ue66f', + 'uicon-rewind-left': '\ue671', + 'uicon-arrow-right-double': '\ue68d', + 'uicon-arrow-left-double': '\ue68c', + 'uicon-wifi-off': '\ue668', + 'uicon-wifi': '\ue667', + 'uicon-empty-data': '\ue62f', + 'uicon-empty-history': '\ue684', + 'uicon-empty-list': '\ue68b', + 'uicon-empty-page': '\ue627', + 'uicon-empty-order': '\ue639', + 'uicon-man': '\ue697', + 'uicon-woman': '\ue69c', + 'uicon-man-add': '\ue61c', + 'uicon-man-add-fill': '\ue64c', + 'uicon-man-delete': '\ue61a', + 'uicon-man-delete-fill': '\ue66a', + 'uicon-zh': '\ue70a', + 'uicon-en': '\ue692' +} diff --git a/src/uni_modules/uview-plus/components/u-icon/props.js b/src/uni_modules/uview-plus/components/u-icon/props.js new file mode 100644 index 00000000..d5bdfdb3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-icon/props.js @@ -0,0 +1,91 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 图标类名 + name: { + type: String, + default: () => defProps.icon.name + }, + // 图标颜色,可接受主题色 + color: { + type: String, + default: () => defProps.icon.color + }, + // 字体大小,单位px + size: { + type: [String, Number], + default: () => defProps.icon.size + }, + // 是否显示粗体 + bold: { + type: Boolean, + default: () => defProps.icon.bold + }, + // 点击图标的时候传递事件出去的index(用于区分点击了哪一个) + index: { + type: [String, Number], + default: () => defProps.icon.index + }, + // 触摸图标时的类名 + hoverClass: { + type: String, + default: () => defProps.icon.hoverClass + }, + // 自定义扩展前缀,方便用户扩展自己的图标库 + customPrefix: { + type: String, + default: () => defProps.icon.customPrefix + }, + // 图标右边或者下面的文字 + label: { + type: [String, Number], + default: () => defProps.icon.label + }, + // label的位置,只能右边或者下边 + labelPos: { + type: String, + default: () => defProps.icon.labelPos + }, + // label的大小 + labelSize: { + type: [String, Number], + default: () => defProps.icon.labelSize + }, + // label的颜色 + labelColor: { + type: String, + default: () => defProps.icon.labelColor + }, + // label与图标的距离 + space: { + type: [String, Number], + default: () => defProps.icon.space + }, + // 图片的mode + imgMode: { + type: String, + default: () => defProps.icon.imgMode + }, + // 用于显示图片小图标时,图片的宽度 + width: { + type: [String, Number], + default: () => defProps.icon.width + }, + // 用于显示图片小图标时,图片的高度 + height: { + type: [String, Number], + default: () => defProps.icon.height + }, + // 用于解决某些情况下,让图标垂直居中的用途 + top: { + type: [String, Number], + default: () => defProps.icon.top + }, + // 是否阻止事件传播 + stop: { + type: Boolean, + default: () => defProps.icon.stop + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-icon/u-icon.vue b/src/uni_modules/uview-plus/components/u-icon/u-icon.vue new file mode 100644 index 00000000..ce3b52a1 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-icon/u-icon.vue @@ -0,0 +1,242 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-image/props.js b/src/uni_modules/uview-plus/components/u-image/props.js new file mode 100644 index 00000000..71bc6dbb --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-image/props.js @@ -0,0 +1,86 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 图片地址 + src: { + type: String, + default: () => defProps.image.src + }, + // 裁剪模式 + mode: { + type: String, + default: () => defProps.image.mode + }, + // 宽度,单位任意 + width: { + type: [String, Number], + default: () => defProps.image.width + }, + // 高度,单位任意 + height: { + type: [String, Number], + default: () => defProps.image.height + }, + // 图片形状,circle-圆形,square-方形 + shape: { + type: String, + default: () => defProps.image.shape + }, + // 圆角,单位任意 + radius: { + type: [String, Number], + default: () => defProps.image.radius + }, + // 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序 + lazyLoad: { + type: Boolean, + default: () => defProps.image.lazyLoad + }, + // 开启长按图片显示识别微信小程序码菜单 + showMenuByLongpress: { + type: Boolean, + default: () => defProps.image.showMenuByLongpress + }, + // 加载中的图标,或者小图片 + loadingIcon: { + type: String, + default: () => defProps.image.loadingIcon + }, + // 加载失败的图标,或者小图片 + errorIcon: { + type: String, + default: () => defProps.image.errorIcon + }, + // 是否显示加载中的图标或者自定义的slot + showLoading: { + type: Boolean, + default: () => defProps.image.showLoading + }, + // 是否显示加载错误的图标或者自定义的slot + showError: { + type: Boolean, + default: () => defProps.image.showError + }, + // 是否需要淡入效果 + fade: { + type: Boolean, + default: () => defProps.image.fade + }, + // 只支持网络资源,只对微信小程序有效 + webp: { + type: Boolean, + default: () => defProps.image.webp + }, + // 过渡时间,单位ms + duration: { + type: [String, Number], + default: () => defProps.image.duration + }, + // 背景颜色,用于深色页面加载图片时,为了和背景色融合 + bgColor: { + type: String, + default: () => defProps.image.bgColor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-image/u-image.vue b/src/uni_modules/uview-plus/components/u-image/u-image.vue new file mode 100644 index 00000000..63936f6c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-image/u-image.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-index-anchor/props.js b/src/uni_modules/uview-plus/components/u-index-anchor/props.js new file mode 100644 index 00000000..f07e407a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-anchor/props.js @@ -0,0 +1,31 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 列表锚点文本内容 + text: { + type: [String, Number], + default: () => defProps.indexAnchor.text + }, + // 列表锚点文字颜色 + color: { + type: String, + default: () => defProps.indexAnchor.color + }, + // 列表锚点文字大小,单位默认px + size: { + type: [String, Number], + default: () => defProps.indexAnchor.size + }, + // 列表锚点背景颜色 + bgColor: { + type: String, + default: () => defProps.indexAnchor.bgColor + }, + // 列表锚点高度,单位默认px + height: { + type: [String, Number], + default: () => defProps.indexAnchor.height + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-index-anchor/u-index-anchor.vue b/src/uni_modules/uview-plus/components/u-index-anchor/u-index-anchor.vue new file mode 100644 index 00000000..91c43e9e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-anchor/u-index-anchor.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-index-item/props.js b/src/uni_modules/uview-plus/components/u-index-item/props.js new file mode 100644 index 00000000..3461f1ef --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-item/props.js @@ -0,0 +1,8 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + + } +}) diff --git a/src/uni_modules/uview-plus/components/u-index-item/u-index-item.vue b/src/uni_modules/uview-plus/components/u-index-item/u-index-item.vue new file mode 100644 index 00000000..13cc30f9 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-item/u-index-item.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-index-list/props.js b/src/uni_modules/uview-plus/components/u-index-list/props.js new file mode 100644 index 00000000..9acd678b --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-list/props.js @@ -0,0 +1,31 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 右边锚点非激活的颜色 + inactiveColor: { + type: String, + default: () => defProps.indexList.inactiveColor + }, + // 右边锚点激活的颜色 + activeColor: { + type: String, + default: () => defProps.indexList.activeColor + }, + // 索引字符列表,数组形式 + indexList: { + type: Array, + default: () => defProps.indexList.indexList + }, + // 是否开启锚点自动吸顶 + sticky: { + type: Boolean, + default: () => defProps.indexList.sticky + }, + // 自定义导航栏的高度 + customNavHeight: { + type: [String, Number], + default: () => defProps.indexList.customNavHeight + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-index-list/u-index-list.vue b/src/uni_modules/uview-plus/components/u-index-list/u-index-list.vue new file mode 100644 index 00000000..c55eafb9 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-index-list/u-index-list.vue @@ -0,0 +1,447 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-input/props.js b/src/uni_modules/uview-plus/components/u-input/props.js new file mode 100644 index 00000000..e5e343e3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-input/props.js @@ -0,0 +1,198 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // #ifdef VUE3 + // 绑定的值 + modelValue: { + type: [String, Number], + default: () => defProps.input.value + }, + // #endif + // #ifdef VUE2 + // 绑定的值 + value: { + type: [String, Number], + default: () => defProps.input.value + }, + // #endif + // number-数字输入键盘,app-vue下可以输入浮点数,app-nvue和小程序平台下只能输入整数 + // idcard-身份证输入键盘,微信、支付宝、百度、QQ小程序 + // digit-带小数点的数字键盘,App的nvue页面、微信、支付宝、百度、头条、QQ小程序 + // text-文本输入键盘 + type: { + type: String, + default: () => defProps.input.type + }, + // 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true, + // 兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序 + fixed: { + type: Boolean, + default: () => defProps.input.fixed + }, + // 是否禁用输入框 + disabled: { + type: Boolean, + default: () => defProps.input.disabled + }, + // 禁用状态时的背景色 + disabledColor: { + type: String, + default: () => defProps.input.disabledColor + }, + // 是否显示清除控件 + clearable: { + type: Boolean, + default: () => defProps.input.clearable + }, + // 是否密码类型 + password: { + type: Boolean, + default: () => defProps.input.password + }, + // 最大输入长度,设置为 -1 的时候不限制最大长度 + maxlength: { + type: [String, Number], + default: () => defProps.input.maxlength + }, + // 输入框为空时的占位符 + placeholder: { + type: String, + default: () => defProps.input.placeholder + }, + // 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写/deep/ + placeholderClass: { + type: String, + default: () => defProps.input.placeholderClass + }, + // 指定placeholder的样式 + placeholderStyle: { + type: [String, Object], + default: () => defProps.input.placeholderStyle + }, + // 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效 + showWordLimit: { + type: Boolean, + default: () => defProps.input.showWordLimit + }, + // 设置右下角按钮的文字,有效值:send|search|next|go|done,兼容性详见uni-app文档 + // https://uniapp.dcloud.io/component/input + // https://uniapp.dcloud.io/component/textarea + confirmType: { + type: String, + default: () => defProps.input.confirmType + }, + // 点击键盘右下角按钮时是否保持键盘不收起,H5无效 + confirmHold: { + type: Boolean, + default: () => defProps.input.confirmHold + }, + // focus时,点击页面的时候不收起键盘,微信小程序有效 + holdKeyboard: { + type: Boolean, + default: () => defProps.input.holdKeyboard + }, + // 自动获取焦点 + // 在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点 + focus: { + type: Boolean, + default: () => defProps.input.focus + }, + // 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效 + autoBlur: { + type: Boolean, + default: () => defProps.input.autoBlur + }, + // 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效 + disableDefaultPadding: { + type: Boolean, + default: () => defProps.input.disableDefaultPadding + }, + // 指定focus时光标的位置 + cursor: { + type: [String, Number], + default: () => defProps.input.cursor + }, + // 输入框聚焦时底部与键盘的距离 + cursorSpacing: { + type: [String, Number], + default: () => defProps.input.cursorSpacing + }, + // 光标起始位置,自动聚集时有效,需与selection-end搭配使用 + selectionStart: { + type: [String, Number], + default: () => defProps.input.selectionStart + }, + // 光标结束位置,自动聚集时有效,需与selection-start搭配使用 + selectionEnd: { + type: [String, Number], + default: () => defProps.input.selectionEnd + }, + // 键盘弹起时,是否自动上推页面 + adjustPosition: { + type: Boolean, + default: () => defProps.input.adjustPosition + }, + // 输入框内容对齐方式,可选值为:left|center|right + inputAlign: { + type: String, + default: () => defProps.input.inputAlign + }, + // 输入框字体的大小 + fontSize: { + type: [String, Number], + default: () => defProps.input.fontSize + }, + // 输入框字体颜色 + color: { + type: String, + default: () => defProps.input.color + }, + // 输入框前置图标 + prefixIcon: { + type: String, + default: () => defProps.input.prefixIcon + }, + // 前置图标样式,对象或字符串 + prefixIconStyle: { + type: [String, Object], + default: () => defProps.input.prefixIconStyle + }, + // 输入框后置图标 + suffixIcon: { + type: String, + default: () => defProps.input.suffixIcon + }, + // 后置图标样式,对象或字符串 + suffixIconStyle: { + type: [String, Object], + default: () => defProps.input.suffixIconStyle + }, + // 边框类型,surround-四周边框,bottom-底部边框,none-无边框 + border: { + type: String, + default: () => defProps.input.border + }, + // 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会 + readonly: { + type: Boolean, + default: () => defProps.input.readonly + }, + // 输入框形状,circle-圆形,square-方形 + shape: { + type: String, + default: () => defProps.input.shape + }, + // 用于处理或者过滤输入框内容的方法 + formatter: { + type: [Function, null], + default: () => defProps.input.formatter + }, + // 是否忽略组件内对文本合成系统事件的处理 + ignoreCompositionEvent: { + type: Boolean, + default: true + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-input/u-input.vue b/src/uni_modules/uview-plus/components/u-input/u-input.vue new file mode 100644 index 00000000..c4c18dca --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-input/u-input.vue @@ -0,0 +1,386 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-keyboard/props.js b/src/uni_modules/uview-plus/components/u-keyboard/props.js new file mode 100644 index 00000000..8c5d8ae0 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-keyboard/props.js @@ -0,0 +1,86 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 键盘的类型,number-数字键盘,card-身份证键盘,car-车牌号键盘 + mode: { + type: String, + default: () => defProps.keyboard.mode + }, + // 是否显示键盘的"."符号 + dotDisabled: { + type: Boolean, + default: () => defProps.keyboard.dotDisabled + }, + // 是否显示顶部工具条 + tooltip: { + type: Boolean, + default: () => defProps.keyboard.tooltip + }, + // 是否显示工具条中间的提示 + showTips: { + type: Boolean, + default: () => defProps.keyboard.showTips + }, + // 工具条中间的提示文字 + tips: { + type: String, + default: () => defProps.keyboard.tips + }, + // 是否显示工具条左边的"取消"按钮 + showCancel: { + type: Boolean, + default: () => defProps.keyboard.showCancel + }, + // 是否显示工具条右边的"完成"按钮 + showConfirm: { + type: Boolean, + default: () => defProps.keyboard.showConfirm + }, + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: () => defProps.keyboard.random + }, + // 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距 + safeAreaInsetBottom: { + type: Boolean, + default: () => defProps.keyboard.safeAreaInsetBottom + }, + // 是否允许通过点击遮罩关闭键盘 + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.keyboard.closeOnClickOverlay + }, + // 控制键盘的弹出与收起 + show: { + type: Boolean, + default: () => defProps.keyboard.show + }, + // 是否显示遮罩,某些时候数字键盘时,用户希望看到自己的数值,所以可能不想要遮罩 + overlay: { + type: Boolean, + default: () => defProps.keyboard.overlay + }, + // z-index值 + zIndex: { + type: [String, Number], + default: () => defProps.keyboard.zIndex + }, + // 取消按钮的文字 + cancelText: { + type: String, + default: () => defProps.keyboard.cancelText + }, + // 确认按钮的文字 + confirmText: { + type: String, + default: () => defProps.keyboard.confirmText + }, + // 输入一个中文后,是否自动切换到英文 + autoChange: { + type: Boolean, + default: () => defProps.keyboard.autoChange + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-keyboard/u-keyboard.vue b/src/uni_modules/uview-plus/components/u-keyboard/u-keyboard.vue new file mode 100644 index 00000000..868f0c5c --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-keyboard/u-keyboard.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-lazy-load/u-lazy-load.vue b/src/uni_modules/uview-plus/components/u-lazy-load/u-lazy-load.vue new file mode 100644 index 00000000..76187812 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-lazy-load/u-lazy-load.vue @@ -0,0 +1,251 @@ + + + + + \ No newline at end of file diff --git a/src/uni_modules/uview-plus/components/u-line-progress/props.js b/src/uni_modules/uview-plus/components/u-line-progress/props.js new file mode 100644 index 00000000..3e03e61d --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-line-progress/props.js @@ -0,0 +1,30 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 激活部分的颜色 + activeColor: { + type: String, + default: () => defProps.lineProgress.activeColor + }, + inactiveColor: { + type: String, + default: () => defProps.lineProgress.color + }, + // 进度百分比,数值 + percentage: { + type: [String, Number], + default: () => defProps.lineProgress.inactiveColor + }, + // 是否在进度条内部显示百分比的值 + showText: { + type: Boolean, + default: () => defProps.lineProgress.showText + }, + // 进度条的高度,单位px + height: { + type: [String, Number], + default: () => defProps.lineProgress.height + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-line-progress/u-line-progress.vue b/src/uni_modules/uview-plus/components/u-line-progress/u-line-progress.vue new file mode 100644 index 00000000..577f877f --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-line-progress/u-line-progress.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-line/props.js b/src/uni_modules/uview-plus/components/u-line/props.js new file mode 100644 index 00000000..6428d3fb --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-line/props.js @@ -0,0 +1,35 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + color: { + type: String, + default: () => defProps.line.color + }, + // 长度,竖向时表现为高度,横向时表现为长度,可以为百分比,带px单位的值等 + length: { + type: [String, Number], + default: () => defProps.line.length + }, + // 线条方向,col-竖向,row-横向 + direction: { + type: String, + default: () => defProps.line.direction + }, + // 是否显示细边框 + hairline: { + type: Boolean, + default: () => defProps.line.hairline + }, + // 线条与上下左右元素的间距,字符串形式,如"30px"、"20px 30px" + margin: { + type: [String, Number], + default: () => defProps.line.margin + }, + // 是否虚线,true-虚线,false-实线 + dashed: { + type: Boolean, + default: () => defProps.line.dashed + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-line/u-line.vue b/src/uni_modules/uview-plus/components/u-line/u-line.vue new file mode 100644 index 00000000..4acc0a01 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-line/u-line.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-link/props.js b/src/uni_modules/uview-plus/components/u-link/props.js new file mode 100644 index 00000000..d96d824e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-link/props.js @@ -0,0 +1,41 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 文字颜色 + color: { + type: String, + default: () => defProps.link.color + }, + // 字体大小,单位px + fontSize: { + type: [String, Number], + default: () => defProps.link.fontSize + }, + // 是否显示下划线 + underLine: { + type: Boolean, + default: () => defProps.link.underLine + }, + // 要跳转的链接 + href: { + type: String, + default: () => defProps.link.href + }, + // 小程序中复制到粘贴板的提示语 + mpTips: { + type: String, + default: () => defProps.link.mpTips + }, + // 下划线颜色 + lineColor: { + type: String, + default: () => defProps.link.lineColor + }, + // 超链接的问题,不使用slot形式传入,是因为nvue下无法修改颜色 + text: { + type: String, + default: () => defProps.link.text + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-link/u-link.vue b/src/uni_modules/uview-plus/components/u-link/u-link.vue new file mode 100644 index 00000000..51038939 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-link/u-link.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-list-item/props.js b/src/uni_modules/uview-plus/components/u-list-item/props.js new file mode 100644 index 00000000..edaa4dc7 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-list-item/props.js @@ -0,0 +1,11 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 用于滚动到指定item + anchor: { + type: [String, Number], + default: () => defProps.listItem.anchor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-list-item/u-list-item.vue b/src/uni_modules/uview-plus/components/u-list-item/u-list-item.vue new file mode 100644 index 00000000..ae30b080 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-list-item/u-list-item.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-list/props.js b/src/uni_modules/uview-plus/components/u-list/props.js new file mode 100644 index 00000000..9fca8294 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-list/props.js @@ -0,0 +1,101 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 控制是否出现滚动条,仅nvue有效 + showScrollbar: { + type: Boolean, + default: () => defProps.list.showScrollbar + }, + // 距底部多少时触发scrolltolower事件 + lowerThreshold: { + type: [String, Number], + default: () => defProps.list.lowerThreshold + }, + // 距顶部多少时触发scrolltoupper事件,非nvue有效 + upperThreshold: { + type: [String, Number], + default: () => defProps.list.upperThreshold + }, + // 设置竖向滚动条位置 + scrollTop: { + type: [String, Number], + default: () => defProps.list.scrollTop + }, + // 控制 onscroll 事件触发的频率,仅nvue有效 + offsetAccuracy: { + type: [String, Number], + default: () => defProps.list.offsetAccuracy + }, + // 启用 flexbox 布局。开启后,当前节点声明了display: flex就会成为flex container,并作用于其孩子节点,仅微信小程序有效 + enableFlex: { + type: Boolean, + default: () => defProps.list.enableFlex + }, + // 是否按分页模式显示List,默认值false + pagingEnabled: { + type: Boolean, + default: () => defProps.list.pagingEnabled + }, + // 是否允许List滚动 + scrollable: { + type: Boolean, + default: () => defProps.list.scrollable + }, + // 值应为某子元素id(id不能以数字开头) + scrollIntoView: { + type: String, + default: () => defProps.list.scrollIntoView + }, + // 在设置滚动条位置时使用动画过渡 + scrollWithAnimation: { + type: Boolean, + default: () => defProps.list.scrollWithAnimation + }, + // iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只对微信小程序有效 + enableBackToTop: { + type: Boolean, + default: () => defProps.list.enableBackToTop + }, + // 列表的高度 + height: { + type: [String, Number], + default: () => defProps.list.height + }, + // 列表宽度 + width: { + type: [String, Number], + default: () => defProps.list.width + }, + // 列表前后预渲染的屏数,1代表一个屏幕的高度,1.5代表1个半屏幕高度 + preLoadScreen: { + type: [String, Number], + default: () => defProps.list.preLoadScreen + }, + // 开启自定义下拉刷新 + refresherEnabled: { + type: Boolean, + default: () => false + }, + // 设置自定义下拉刷新阈值 + refresherThreshold: { + type: Number, + default: () => 45 + }, + // 设置自定义下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式 + refresherDefaultStyle: { + type: String, + default: () => 'black' + }, + // 设置自定义下拉刷新区域背景颜色 + refresherBackground: { + type: String, + default: () => '#FFF' + }, + // 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 + refresherTriggered: { + type: Boolean, + default: () => false + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-list/u-list.vue b/src/uni_modules/uview-plus/components/u-list/u-list.vue new file mode 100644 index 00000000..1473b3e6 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-list/u-list.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-loading-icon/props.js b/src/uni_modules/uview-plus/components/u-loading-icon/props.js new file mode 100644 index 00000000..6a6abf95 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loading-icon/props.js @@ -0,0 +1,61 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否显示组件 + show: { + type: Boolean, + default: () => defProps.loadingIcon.show + }, + // 颜色 + color: { + type: String, + default: () => defProps.loadingIcon.color + }, + // 提示文字颜色 + textColor: { + type: String, + default: () => defProps.loadingIcon.textColor + }, + // 文字和图标是否垂直排列 + vertical: { + type: Boolean, + default: () => defProps.loadingIcon.vertical + }, + // 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形 + mode: { + type: String, + default: () => defProps.loadingIcon.mode + }, + // 图标大小,单位默认px + size: { + type: [String, Number], + default: () => defProps.loadingIcon.size + }, + // 文字大小 + textSize: { + type: [String, Number], + default: () => defProps.loadingIcon.textSize + }, + // 文字内容 + text: { + type: [String, Number], + default: () => defProps.loadingIcon.text + }, + // 动画模式 + timingFunction: { + type: String, + default: () => defProps.loadingIcon.timingFunction + }, + // 动画执行周期时间 + duration: { + type: [String, Number], + default: () => defProps.loadingIcon.duration + }, + // mode=circle时的暗边颜色 + inactiveColor: { + type: String, + default: () => defProps.loadingIcon.inactiveColor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-loading-icon/u-loading-icon.vue b/src/uni_modules/uview-plus/components/u-loading-icon/u-loading-icon.vue new file mode 100644 index 00000000..f00f777a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loading-icon/u-loading-icon.vue @@ -0,0 +1,347 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-loading-page/props.js b/src/uni_modules/uview-plus/components/u-loading-page/props.js new file mode 100644 index 00000000..3a0ab3f3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loading-page/props.js @@ -0,0 +1,52 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 提示内容 + loadingText: { + type: [String, Number], + default: () => defProps.loadingPage.loadingText + }, + // 文字上方用于替换loading动画的图片 + image: { + type: String, + default: () => defProps.loadingPage.image + }, + // 加载动画的模式,circle-圆形,spinner-花朵形,semicircle-半圆形 + loadingMode: { + type: String, + default: () => defProps.loadingPage.loadingMode + }, + // 是否加载中 + loading: { + type: Boolean, + default: () => defProps.loadingPage.loading + }, + // 背景色 + bgColor: { + type: String, + default: () => defProps.loadingPage.bgColor + }, + // 文字颜色 + color: { + type: String, + default: () => defProps.loadingPage.color + }, + // 文字大小 + fontSize: { + type: [String, Number], + default: () => defProps.loadingPage.fontSize + }, + // 图标大小 + iconSize: { + type: [String, Number], + default: () => defProps.loadingPage.fontSize + }, + // 加载中图标的颜色,只能rgb或者十六进制颜色值 + loadingColor: { + type: String, + default: () => defProps.loadingPage.loadingColor + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-loading-page/u-loading-page.vue b/src/uni_modules/uview-plus/components/u-loading-page/u-loading-page.vue new file mode 100644 index 00000000..302304db --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loading-page/u-loading-page.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-loadmore/props.js b/src/uni_modules/uview-plus/components/u-loadmore/props.js new file mode 100644 index 00000000..fb78e39d --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loadmore/props.js @@ -0,0 +1,96 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 组件状态,loadmore-加载前的状态,loading-加载中的状态,nomore-没有更多的状态 + status: { + type: String, + default: () => defProps.loadmore.status + }, + // 组件背景色 + bgColor: { + type: String, + default: () => defProps.loadmore.bgColor + }, + // 是否显示加载中的图标 + icon: { + type: Boolean, + default: () => defProps.loadmore.icon + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.loadmore.fontSize + }, + // 图标大小 + iconSize: { + type: [String, Number], + default: () => defProps.loadmore.iconSize + }, + // 字体颜色 + color: { + type: String, + default: () => defProps.loadmore.color + }, + // 加载中状态的图标,spinner-花朵状图标,circle-圆圈状,semicircle-半圆 + loadingIcon: { + type: String, + default: () => defProps.loadmore.loadingIcon + }, + // 加载前的提示语 + loadmoreText: { + type: String, + default: () => defProps.loadmore.loadmoreText + }, + // 加载中提示语 + loadingText: { + type: String, + default: () => defProps.loadmore.loadingText + }, + // 没有更多的提示语 + nomoreText: { + type: String, + default: () => defProps.loadmore.nomoreText + }, + // 在“没有更多”状态下,是否显示粗点 + isDot: { + type: Boolean, + default: () => defProps.loadmore.isDot + }, + // 加载中图标的颜色 + iconColor: { + type: String, + default: () => defProps.loadmore.iconColor + }, + // 上边距 + marginTop: { + type: [String, Number], + default: () => defProps.loadmore.marginTop + }, + // 下边距 + marginBottom: { + type: [String, Number], + default: () => defProps.loadmore.marginBottom + }, + // 高度,单位px + height: { + type: [String, Number], + default: () => defProps.loadmore.height + }, + // 是否显示左边分割线 + line: { + type: Boolean, + default: () => defProps.loadmore.line + }, + // 线条颜色 + lineColor: { + type: String, + default: () => defProps.loadmore.lineColor + }, + // 是否虚线,true-虚线,false-实线 + dashed: { + type: Boolean, + default: () => defProps.loadmore.dashed + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-loadmore/u-loadmore.vue b/src/uni_modules/uview-plus/components/u-loadmore/u-loadmore.vue new file mode 100644 index 00000000..62c99c00 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-loadmore/u-loadmore.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-message-input/u-message-input.vue b/src/uni_modules/uview-plus/components/u-message-input/u-message-input.vue new file mode 100644 index 00000000..0da5f1c3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-message-input/u-message-input.vue @@ -0,0 +1,318 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-modal/props.js b/src/uni_modules/uview-plus/components/u-modal/props.js new file mode 100644 index 00000000..22dbdfd1 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-modal/props.js @@ -0,0 +1,86 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否展示modal + show: { + type: Boolean, + default: () => defProps.modal.show + }, + // 标题 + title: { + type: [String], + default: () => defProps.modal.title + }, + // 弹窗内容 + content: { + type: String, + default: () => defProps.modal.content + }, + // 确认文案 + confirmText: { + type: String, + default: () => defProps.modal.confirmText + }, + // 取消文案 + cancelText: { + type: String, + default: () => defProps.modal.cancelText + }, + // 是否显示确认按钮 + showConfirmButton: { + type: Boolean, + default: () => defProps.modal.showConfirmButton + }, + // 是否显示取消按钮 + showCancelButton: { + type: Boolean, + default: () => defProps.modal.showCancelButton + }, + // 确认按钮颜色 + confirmColor: { + type: String, + default: () => defProps.modal.confirmColor + }, + // 取消文字颜色 + cancelColor: { + type: String, + default: () => defProps.modal.cancelColor + }, + // 对调确认和取消的位置 + buttonReverse: { + type: Boolean, + default: () => defProps.modal.buttonReverse + }, + // 是否开启缩放效果 + zoom: { + type: Boolean, + default: () => defProps.modal.zoom + }, + // 是否异步关闭,只对确定按钮有效 + asyncClose: { + type: Boolean, + default: () => defProps.modal.asyncClose + }, + // 是否允许点击遮罩关闭modal + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.modal.closeOnClickOverlay + }, + // 给一个负的margin-top,往上偏移,避免和键盘重合的情况 + negativeTop: { + type: [String, Number], + default: () => defProps.modal.negativeTop + }, + // modal宽度,不支持百分比,可以数值,px,rpx单位 + width: { + type: [String, Number], + default: () => defProps.modal.width + }, + // 确认按钮的样式,circle-圆形,square-方形,如设置,将不会显示取消按钮 + confirmButtonShape: { + type: String, + default: () => defProps.modal.confirmButtonShape + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-modal/u-modal.vue b/src/uni_modules/uview-plus/components/u-modal/u-modal.vue new file mode 100644 index 00000000..f9ab38fe --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-modal/u-modal.vue @@ -0,0 +1,234 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-navbar/props.js b/src/uni_modules/uview-plus/components/u-navbar/props.js new file mode 100644 index 00000000..2f20b02a --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-navbar/props.js @@ -0,0 +1,87 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' + +export const props = defineMixin({ + props: { + // 是否开启顶部安全区适配 + safeAreaInsetTop: { + type: Boolean, + default: () => defProps.navbar.safeAreaInsetTop + }, + // 固定在顶部时,是否生成一个等高元素,以防止塌陷 + placeholder: { + type: Boolean, + default: () => defProps.navbar.placeholder + }, + // 是否固定在顶部 + fixed: { + type: Boolean, + default: () => defProps.navbar.fixed + }, + // 是否显示下边框 + border: { + type: Boolean, + default: () => defProps.navbar.border + }, + // 左边的图标 + leftIcon: { + type: String, + default: () => defProps.navbar.leftIcon + }, + // 左边的提示文字 + leftText: { + type: String, + default: () => defProps.navbar.leftText + }, + // 左右的提示文字 + rightText: { + type: String, + default: () => defProps.navbar.rightText + }, + // 右边的图标 + rightIcon: { + type: String, + default: () => defProps.navbar.rightIcon + }, + // 标题 + title: { + type: [String, Number], + default: () => defProps.navbar.title + }, + // 背景颜色 + bgColor: { + type: String, + default: () => defProps.navbar.bgColor + }, + // 标题的宽度 + titleWidth: { + type: [String, Number], + default: () => defProps.navbar.titleWidth + }, + // 导航栏高度 + height: { + type: [String, Number], + default: () => defProps.navbar.height + }, + // 左侧返回图标的大小 + leftIconSize: { + type: [String, Number], + default: () => defProps.navbar.leftIconSize + }, + // 左侧返回图标的颜色 + leftIconColor: { + type: String, + default: () => defProps.navbar.leftIconColor + }, + // 点击左侧区域(返回图标),是否自动返回上一页 + autoBack: { + type: Boolean, + default: () => defProps.navbar.autoBack + }, + // 标题的样式,对象或字符串 + titleStyle: { + type: [String, Object], + default: () => defProps.navbar.titleStyle + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-navbar/u-navbar.vue b/src/uni_modules/uview-plus/components/u-navbar/u-navbar.vue new file mode 100644 index 00000000..6d6cdbad --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-navbar/u-navbar.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-no-network/props.js b/src/uni_modules/uview-plus/components/u-no-network/props.js new file mode 100644 index 00000000..1091cf53 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-no-network/props.js @@ -0,0 +1,21 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 页面文字提示 + tips: { + type: String, + default: () => defProps.noNetwork.tips + }, + // 一个z-index值,用于设置没有网络这个组件的层次,因为页面可能会有其他定位的元素层级过高,导致此组件被覆盖 + zIndex: { + type: [String, Number], + default: () => defProps.noNetwork.zIndex + }, + // image 没有网络的图片提示 + image: { + type: String, + default: () => defProps.noNetwork.image + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-no-network/u-no-network.vue b/src/uni_modules/uview-plus/components/u-no-network/u-no-network.vue new file mode 100644 index 00000000..54539a52 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-no-network/u-no-network.vue @@ -0,0 +1,223 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-notice-bar/props.js b/src/uni_modules/uview-plus/components/u-notice-bar/props.js new file mode 100644 index 00000000..cc2a53fe --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-notice-bar/props.js @@ -0,0 +1,72 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 显示的内容,数组 + text: { + type: [Array, String], + default: () => defProps.noticeBar.text + }, + // 通告滚动模式,row-横向滚动,column-竖向滚动 + direction: { + type: String, + default: () => defProps.noticeBar.direction + }, + // direction = row时,是否使用步进形式滚动 + step: { + type: Boolean, + default: () => defProps.noticeBar.step + }, + // 是否显示左侧的音量图标 + icon: { + type: String, + default: () => defProps.noticeBar.icon + }, + // 通告模式,link-显示右箭头,closable-显示右侧关闭图标 + mode: { + type: String, + default: () => defProps.noticeBar.mode + }, + // 文字颜色,各图标也会使用文字颜色 + color: { + type: String, + default: () => defProps.noticeBar.color + }, + // 背景颜色 + bgColor: { + type: String, + default: () => defProps.noticeBar.bgColor + }, + // 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度 + speed: { + type: [String, Number], + default: () => defProps.noticeBar.speed + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.noticeBar.fontSize + }, + // 滚动一个周期的时间长,单位ms + duration: { + type: [String, Number], + default: () => defProps.noticeBar.duration + }, + // 是否禁止用手滑动切换 + // 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序 + disableTouch: { + type: Boolean, + default: () => defProps.noticeBar.disableTouch + }, + // 跳转的页面路径 + url: { + type: String, + default: () => defProps.noticeBar.url + }, + // 页面跳转的类型 + linkType: { + type: String, + default: () => defProps.noticeBar.linkType + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-notice-bar/u-notice-bar.vue b/src/uni_modules/uview-plus/components/u-notice-bar/u-notice-bar.vue new file mode 100644 index 00000000..548d07f5 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-notice-bar/u-notice-bar.vue @@ -0,0 +1,105 @@ + + + + diff --git a/src/uni_modules/uview-plus/components/u-notify/props.js b/src/uni_modules/uview-plus/components/u-notify/props.js new file mode 100644 index 00000000..fdb01b47 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-notify/props.js @@ -0,0 +1,51 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 到顶部的距离 + top: { + type: [String, Number], + default: () => defProps.notify.top + }, + // 是否展示组件 + // show: { + // type: Boolean, + // default: () => defProps.notify.show + // }, + // type主题,primary,success,warning,error + type: { + type: String, + default: () => defProps.notify.type + }, + // 字体颜色 + color: { + type: String, + default: () => defProps.notify.color + }, + // 背景颜色 + bgColor: { + type: String, + default: () => defProps.notify.bgColor + }, + // 展示的文字内容 + message: { + type: String, + default: () => defProps.notify.message + }, + // 展示时长,为0时不消失,单位ms + duration: { + type: [String, Number], + default: () => defProps.notify.duration + }, + // 字体大小 + fontSize: { + type: [String, Number], + default: () => defProps.notify.fontSize + }, + // 是否留出顶部安全距离(状态栏高度) + safeAreaInsetTop: { + type: Boolean, + default: () => defProps.notify.safeAreaInsetTop + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-notify/u-notify.vue b/src/uni_modules/uview-plus/components/u-notify/u-notify.vue new file mode 100644 index 00000000..adab25aa --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-notify/u-notify.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-number-box/props.js b/src/uni_modules/uview-plus/components/u-number-box/props.js new file mode 100644 index 00000000..1c5564e4 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-number-box/props.js @@ -0,0 +1,120 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 步进器标识符,在change回调返回 + name: { + type: [String, Number], + default: () => defProps.numberBox.name + }, + // #ifdef VUE2 + // 用于双向绑定的值,初始化时设置设为默认min值(最小值) + value: { + type: [String, Number], + default: () => defProps.numberBox.value + }, + // #endif + // #ifdef VUE3 + // 用于双向绑定的值,初始化时设置设为默认min值(最小值) + modelValue: { + type: [String, Number], + default: () => defProps.numberBox.value + }, + // #endif + // 最小值 + min: { + type: [String, Number], + default: () => defProps.numberBox.min + }, + // 最大值 + max: { + type: [String, Number], + default: () => defProps.numberBox.max + }, + // 加减的步长,可为小数 + step: { + type: [String, Number], + default: () => defProps.numberBox.step + }, + // 是否只允许输入整数 + integer: { + type: Boolean, + default: () => defProps.numberBox.integer + }, + // 是否禁用,包括输入框,加减按钮 + disabled: { + type: Boolean, + default: () => defProps.numberBox.disabled + }, + // 是否禁用输入框 + disabledInput: { + type: Boolean, + default: () => defProps.numberBox.disabledInput + }, + // 是否开启异步变更,开启后需要手动控制输入值 + asyncChange: { + type: Boolean, + default: () => defProps.numberBox.asyncChange + }, + // 输入框宽度,单位为px + inputWidth: { + type: [String, Number], + default: () => defProps.numberBox.inputWidth + }, + // 是否显示减少按钮 + showMinus: { + type: Boolean, + default: () => defProps.numberBox.showMinus + }, + // 是否显示增加按钮 + showPlus: { + type: Boolean, + default: () => defProps.numberBox.showPlus + }, + // 显示的小数位数 + decimalLength: { + type: [String, Number, null], + default: () => defProps.numberBox.decimalLength + }, + // 是否开启长按加减手势 + longPress: { + type: Boolean, + default: () => defProps.numberBox.longPress + }, + // 输入框文字和加减按钮图标的颜色 + color: { + type: String, + default: () => defProps.numberBox.color + }, + // 按钮大小,宽高等于此值,单位px,输入框高度和此值保持一致 + buttonSize: { + type: [String, Number], + default: () => defProps.numberBox.buttonSize + }, + // 输入框和按钮的背景颜色 + bgColor: { + type: String, + default: () => defProps.numberBox.bgColor + }, + // 指定光标于键盘的距离,避免键盘遮挡输入框,单位px + cursorSpacing: { + type: [String, Number], + default: () => defProps.numberBox.cursorSpacing + }, + // 是否禁用增加按钮 + disablePlus: { + type: Boolean, + default: () => defProps.numberBox.disablePlus + }, + // 是否禁用减少按钮 + disableMinus: { + type: Boolean, + default: () => defProps.numberBox.disableMinus + }, + // 加减按钮图标的样式 + iconStyle: { + type: [Object, String], + default: () => defProps.numberBox.iconStyle + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-number-box/u-number-box.vue b/src/uni_modules/uview-plus/components/u-number-box/u-number-box.vue new file mode 100644 index 00000000..2371bbc3 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-number-box/u-number-box.vue @@ -0,0 +1,465 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-number-keyboard/props.js b/src/uni_modules/uview-plus/components/u-number-keyboard/props.js new file mode 100644 index 00000000..d8538586 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-number-keyboard/props.js @@ -0,0 +1,21 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 键盘的类型,number-数字键盘,card-身份证键盘 + mode: { + type: String, + default: () => defProps.numberKeyboard.value + }, + // 是否显示键盘的"."符号 + dotDisabled: { + type: Boolean, + default: () => defProps.numberKeyboard.dotDisabled + }, + // 是否打乱键盘按键的顺序 + random: { + type: Boolean, + default: () => defProps.numberKeyboard.random + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-number-keyboard/u-number-keyboard.vue b/src/uni_modules/uview-plus/components/u-number-keyboard/u-number-keyboard.vue new file mode 100644 index 00000000..a978fd0e --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-number-keyboard/u-number-keyboard.vue @@ -0,0 +1,198 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-overlay/props.js b/src/uni_modules/uview-plus/components/u-overlay/props.js new file mode 100644 index 00000000..39f16f32 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-overlay/props.js @@ -0,0 +1,26 @@ +import { defineMixin } from '../../libs/vue' +import defProps from '../../libs/config/props.js' +export const props = defineMixin({ + props: { + // 是否显示遮罩 + show: { + type: Boolean, + default: () => defProps.overlay.show + }, + // 层级z-index + zIndex: { + type: [String, Number], + default: () => defProps.overlay.zIndex + }, + // 遮罩的过渡时间,单位为ms + duration: { + type: [String, Number], + default: () => defProps.overlay.duration + }, + // 不透明度值,当做rgba的第四个参数 + opacity: { + type: [String, Number], + default: () => defProps.overlay.opacity + } + } +}) diff --git a/src/uni_modules/uview-plus/components/u-overlay/u-overlay.vue b/src/uni_modules/uview-plus/components/u-overlay/u-overlay.vue new file mode 100644 index 00000000..d8047509 --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-overlay/u-overlay.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/uni_modules/uview-plus/components/u-parse/node/node.vue b/src/uni_modules/uview-plus/components/u-parse/node/node.vue new file mode 100644 index 00000000..06035dea --- /dev/null +++ b/src/uni_modules/uview-plus/components/u-parse/node/node.vue @@ -0,0 +1,576 @@ +