commit d7802b25f26d7363020be2154338cb2949f61371 Author: zhangzhen Date: Tue Feb 10 09:56:08 2026 +0800 1.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49910bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +node_modules +out/ +logs/ +run/ +.idea/ +package-lock.json +data/ +.vscode/launch.json +unpackage/ +pnpm-lock.yaml diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..29998cf --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,10 @@ +{ + "version" : "1.0", + "configurations" : [ + { + "customPlaygroundType" : "local", + "playground" : "custom", + "type" : "uni-app:app-android" + } + ] +} diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..1c0d825 --- /dev/null +++ b/App.vue @@ -0,0 +1,86 @@ + + + diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..572f599 --- /dev/null +++ b/api/index.js @@ -0,0 +1,49 @@ +import request from '@/utils/request' + +// 时间 +export const time = (param) => { + return request.get('/cabinetapi/now', param) +} + +// 内镜列表 +export const endoscopelist = (param) => { + return request.get('/cabinetapi/endoscopelist', param) +} + +// 用户列表 +export const userlist = (param) => { + return request.get('/cabinetapi/userlist', param) +} + +// 提交基础设置 +export const deviceinfo = (param) => { + return request.get('/cabinetapi/deviceinfo', param) +} + +// 获取运行参数 +export const parameterlist = (param) => { + return request.get('/cabinetapi/parameterlist', param) +} + +// 提交本机运行参数 +export const parametersubmit = (param) => { + return request.get('/cabinetapi/parametersubmit', param) +} + +// 内镜存入 +export const endoscopeinware = (param) => { + return request.get('/cabinetapi/endoscopeinware', param) +} + + // 内镜取出 +export const endoscopeoutware = (param) => { + return request.get('/cabinetapi/endoscopeoutware', param) +} + + // 提交日志 +export const logsync = (param) => { + return request.get('/cabinetapi/logsync', param) +} + + + diff --git a/assets/autorun.png b/assets/autorun.png new file mode 100644 index 0000000..4a53108 Binary files /dev/null and b/assets/autorun.png differ diff --git a/assets/bg.png b/assets/bg.png new file mode 100644 index 0000000..3dac528 Binary files /dev/null and b/assets/bg.png differ diff --git a/assets/clean.png b/assets/clean.png new file mode 100644 index 0000000..2a7db9f Binary files /dev/null and b/assets/clean.png differ diff --git a/assets/door.png b/assets/door.png new file mode 100644 index 0000000..221b9a1 Binary files /dev/null and b/assets/door.png differ diff --git a/assets/global.css b/assets/global.css new file mode 100644 index 0000000..7a0cc53 --- /dev/null +++ b/assets/global.css @@ -0,0 +1,43 @@ +html, body { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + user-select: none; +} +#app { + font-family: Avenir, Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-align: center; + height: 100%; + width: 100%; + background: radial-gradient(82% 82% at 50% 63%, #4A506D 0%, rgba(0, 0, 0, 0) 100%), #05081D; + /* color: #fff; */ +} + + + +.ant-modal .ant-modal-content, +.ant-modal .ant-modal-header{ + border-radius: 30px; + background-color: #777D90; + border-color: #777D90; + color: #fff; +} +.ant-modal .ant-modal-close-x{ + color: #fff; + font-size: 20px; +} + +.btn-group { + position: relative; + display: inline-flex; +} + +.ant-btn:hover, +.ant-btn:focus, +.ant-btn:active{ + color: inherit; + border-color: inherit; +} diff --git a/assets/layout.css b/assets/layout.css new file mode 100644 index 0000000..85c7646 --- /dev/null +++ b/assets/layout.css @@ -0,0 +1,125 @@ + +.ant-layout { + display: flex; + flex: auto; + flex-direction: column; + /* fix firefox can't set height smaller than content on flex item */ + min-height: 0; + background: #f0f2f5; +} +.ant-layout, +.ant-layout * { + box-sizing: border-box; +} +.ant-layout.ant-layout-has-sider { + flex-direction: row; +} +.ant-layout.ant-layout-has-sider > .ant-layout, +.ant-layout.ant-layout-has-sider > .ant-layout-content { + width: 0; +} +.ant-layout-header, +.ant-layout-footer { + flex: 0 0 auto; +} +.ant-layout-header { + height: 64px; + padding: 0 50px; + color: rgba(0, 0, 0, 0.85); + line-height: 64px; + background: #001529; +} +.ant-layout-footer { + padding: 24px 50px; + color: rgba(0, 0, 0, 0.85); + font-size: 14px; + background: #f0f2f5; +} +.ant-layout-content { + flex: auto; + /* fix firefox can't set height smaller than content on flex item */ + min-height: 0; +} +.ant-layout-sider { + position: relative; + /* fix firefox can't set width smaller than content on flex item */ + min-width: 0; + background: #001529; + transition: all 0.2s; +} +.ant-layout-sider-children { + height: 100%; + margin-top: -0.1px; + padding-top: 0.1px; +} +.ant-layout-sider-children .ant-menu.ant-menu-inline-collapsed { + width: auto; +} +.ant-layout-sider-has-trigger { + padding-bottom: 48px; +} +.ant-layout-sider-right { + order: 1; +} +.ant-layout-sider-trigger { + position: fixed; + bottom: 0; + z-index: 1; + height: 48px; + color: #fff; + line-height: 48px; + text-align: center; + background: #002140; + cursor: pointer; + transition: all 0.2s; +} +.ant-layout-sider-zero-width > * { + overflow: hidden; +} +.ant-layout-sider-zero-width-trigger { + position: absolute; + top: 64px; + right: -36px; + z-index: 1; + width: 36px; + height: 42px; + color: #fff; + font-size: 18px; + line-height: 42px; + text-align: center; + background: #001529; + border-radius: 0 2px 2px 0; + cursor: pointer; + transition: background 0.3s ease; +} +.ant-layout-sider-zero-width-trigger::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: transparent; + transition: all 0.3s; + content: ''; +} +.ant-layout-sider-zero-width-trigger:hover::after { + background: rgba(255, 255, 255, 0.1); +} +.ant-layout-sider-zero-width-trigger-right { + left: -36px; + border-radius: 2px 0 0 2px; +} +.ant-layout-sider-light { + background: #fff; +} +.ant-layout-sider-light .ant-layout-sider-trigger { + color: rgba(0, 0, 0, 0.85); + background: #fff; +} +.ant-layout-sider-light .ant-layout-sider-zero-width-trigger { + color: rgba(0, 0, 0, 0.85); + background: #fff; +} +.ant-layout-rtl { + direction: rtl; +} diff --git a/assets/light.png b/assets/light.png new file mode 100644 index 0000000..a54695e Binary files /dev/null and b/assets/light.png differ diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..95dc60b Binary files /dev/null and b/assets/logo.png differ diff --git a/assets/nowifi.png b/assets/nowifi.png new file mode 100644 index 0000000..0fe7459 Binary files /dev/null and b/assets/nowifi.png differ diff --git a/assets/wifi.png b/assets/wifi.png new file mode 100644 index 0000000..74dbaee Binary files /dev/null and b/assets/wifi.png differ diff --git a/assets/xiaodu.png b/assets/xiaodu.png new file mode 100644 index 0000000..14adc5b Binary files /dev/null and b/assets/xiaodu.png differ diff --git a/assets/zhenkong.png b/assets/zhenkong.png new file mode 100644 index 0000000..bf805fa Binary files /dev/null and b/assets/zhenkong.png differ diff --git a/components/HeadTitle.vue b/components/HeadTitle.vue new file mode 100644 index 0000000..9af3a05 --- /dev/null +++ b/components/HeadTitle.vue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/components/InputModal.vue b/components/InputModal.vue new file mode 100644 index 0000000..68f0371 --- /dev/null +++ b/components/InputModal.vue @@ -0,0 +1,118 @@ + + + + + \ No newline at end of file diff --git a/components/InputNum.vue b/components/InputNum.vue new file mode 100644 index 0000000..f23075d --- /dev/null +++ b/components/InputNum.vue @@ -0,0 +1,105 @@ + + + + + \ No newline at end of file diff --git a/components/InputNumDrawer.vue b/components/InputNumDrawer.vue new file mode 100644 index 0000000..301b972 --- /dev/null +++ b/components/InputNumDrawer.vue @@ -0,0 +1,116 @@ + + + + + \ No newline at end of file diff --git a/components/InputNumPop.vue b/components/InputNumPop.vue new file mode 100644 index 0000000..e44d659 --- /dev/null +++ b/components/InputNumPop.vue @@ -0,0 +1,126 @@ + + + + + \ No newline at end of file diff --git a/components/Notice.vue b/components/Notice.vue new file mode 100644 index 0000000..2e2c67d --- /dev/null +++ b/components/Notice.vue @@ -0,0 +1,64 @@ + + + + + \ No newline at end of file diff --git a/components/PageFooter.vue b/components/PageFooter.vue new file mode 100644 index 0000000..1b96257 --- /dev/null +++ b/components/PageFooter.vue @@ -0,0 +1,109 @@ + + + + + \ No newline at end of file diff --git a/components/PageHeader.vue b/components/PageHeader.vue new file mode 100644 index 0000000..2cce06b --- /dev/null +++ b/components/PageHeader.vue @@ -0,0 +1,133 @@ + + + + + \ No newline at end of file diff --git a/components/global/index.js b/components/global/index.js new file mode 100644 index 0000000..a5fc33b --- /dev/null +++ b/components/global/index.js @@ -0,0 +1,10 @@ +const modules = import.meta.globEager('./*.vue') +const map = {} +Object.keys(modules).forEach(file => { + const modulesName = file.replace('./', '').replace('.vue', '') + map[modulesName] = modules[file].default +}) +const globalComponents = { + ...map, +} +export default globalComponents diff --git a/components/xuan-switch/xuan-switch.vue b/components/xuan-switch/xuan-switch.vue new file mode 100644 index 0000000..9a873a3 --- /dev/null +++ b/components/xuan-switch/xuan-switch.vue @@ -0,0 +1,195 @@ + + + + + diff --git a/db/sqlite.js b/db/sqlite.js new file mode 100644 index 0000000..9a0bc6f --- /dev/null +++ b/db/sqlite.js @@ -0,0 +1,425 @@ +const dbName = "sqlite" +// "user", "log" + +export const openDb = () => { + //如果数据库存在则打开,不存在则创建。 + return new Promise((resolve, reject) => { + plus.sqlite.openDatabase({ + name: dbName, //数据库名称 + path: `_doc/${dbName}.db`, //数据库地址 + success(e) { + resolve(e); + }, + fail(e) { + reject(e); + } + }) + }) +} +// 查询所有数据表名 +export const getTable = () => { + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: dbName, + sql: "select * FROM sqlite_master where type='table'", + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} +// 查询表数据总条数 +export const getCount = (tabName) => { + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: dbName, + sql: "select count(*) as num from " + tabName, + success(e) { + resolve(e); + }, + fail(e) { + reject(e); + } + }) + }) +} + +// 查询表是否存在 +export const isTable = (tabName) => { + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: dbName, + sql: `select count(*) as isTable FROM sqlite_master where type='table' and name='${tabName}'`, + success(e) { + console.log(e) + resolve(e[0].isTable ? true : false); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} +/** + * 修改数据 + * @param {String} tabName 表名 + * @param {Object} setData 修改数据 + * @param {String} setName 查询字段名 + * @param {String} setVal 查询字段值 +*/ +export const updateSQL = (tabName, setData, setName, setVal) => { + if (JSON.stringify(setData) !== '{}') { + let dataKeys = Object.keys(setData) + let setStr = '' + dataKeys.forEach((item, index) => { + console.log(setData[item]) + setStr += ( + `${item} = ${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? "," : ""}`) + }) + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `update ${tabName} set ${setStr} where ${setName} = "${setVal}"`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) + } else { + return new Promise((resolve, reject) => { + reject("错误") + }); + } +} + +//删除数据库数据 +export const deleteInformationType = (tabName,setData) => { + if (JSON.stringify(setData) !== '{}') { + let dataKeys = Object.keys(setData) + let setStr = '' + dataKeys.forEach((item, index) => { + console.log(setData[item]) + setStr += ( + `${item}=${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? " and " : ""}`) + }) + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `delete from ${tabName} where ${setStr}`, + success(e) { + resolve(e); + }, + fail(e) { + reject(e); + } + }) + }) + } else { + return new Promise((resolve, reject) => { + reject("错误") + }); + } +} + +//关闭数据库 +export const closeSQL = (name) => { + return new Promise((resolve, reject) => { + plus.sqlite.closeDatabase({ + name: 'pop', + success(e) { + resolve(e); + }, + fail(e) { + reject(e); + } + }) + }) +} + +//监听数据库是否开启 +export const isOpen = () => { + let open = plus.sqlite.isOpenDatabase({ + name: dbName, + path: `_doc/${dbName}.db`, + }) + return open; +} + +// 创建用户表 +export const addUserTable = () => { + const tabName = 'user' + // tabName不能用数字作为表格名的开头 + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `create table if not exists ${tabName}("id" INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255) NOT NULL, ic VARCHAR(255) NOT NULL, number CHAR(50), type CHAR(50) )`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} +// 创建日志表 +export const addLogTable = () => { + const tabName = 'log' + // tabName不能用数字作为表格名的开头 + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `create table if not exists ${tabName}("id" INTEGER PRIMARY KEY AUTOINCREMENT,"name" VARCHAR(255) NOT NULL,action VARCHAR(255) NOT NULL, create_time datetime DEFAULT (datetime('now', 'localtime')))`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} + +// 创建内镜存储表 +export const addScopeTable = () => { + const tabName = 'scope' + // tabName不能用数字作为表格名的开头 + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `create table if not exists ${tabName}("key" INTEGER NOT NULL,"ic" CHAR(50) , "rfid" CHAR(50), "name" VARCHAR(255), time datetime DEFAULT (datetime('now', 'localtime')))`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} + +// 创建内镜存储表 +export const addEndoTable = () => { + const tabName = 'endo' + // tabName不能用数字作为表格名的开头 + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `create table if not exists ${tabName}("id" INTEGER PRIMARY KEY AUTOINCREMENT,"endoscope_id" CHAR(255), "name" CHAR(50), "brand" CHAR(50),"model" CHAR(50), "type" CHAR(50), "rfid" CHAR(50) ,"ic" VARCHAR(255), time datetime DEFAULT (datetime('now', 'localtime')))`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} + +/** + * 添加数据 + * @param {String} tabName 表名 + * @param {Object} obj 添加数据 +*/ +export const addTabItem = (tabName,obj) => { + if (obj) { + let keys = Object.keys(obj) + let keyStr = keys.toString() + let valStr = '' + keys.forEach((item, index) => { + if (keys.length - 1 == index) { + valStr += ('"' + obj[item] + '"') + } else { + valStr += ('"' + obj[item] + '",') + } + }) + console.log(valStr) + let sqlStr = `insert into ${tabName} (${keyStr}) values(${valStr})` + console.log(sqlStr) + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: sqlStr, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) + } else { + return new Promise((resolve, reject) => { + reject("错误") + }) + } +} + +// 合并数据 +export const mergeSql = (name,tabName,tabs) => { + if (!tabs || tabs.length == 0) { + return new Promise((resolve, reject) => { + reject("错误") + }) + } + let itemValStr = '' + tabs.forEach((item, index) => { + let itemKey = Object.keys(item) + let itemVal = '' + itemKey.forEach((key, i) => { + if (itemKey.length - 1 == i) { + if (typeof item[key] == 'object') { + itemVal += (`'${JSON.stringify(item[key])}'`) + } else { + itemVal += (`'${item[key]}'`) + } + } else { + if (typeof item[key] == 'object') { + itemVal += (`'${JSON.stringify(item[key])}',`) + } else { + itemVal += (`'${item[key]}',`) + } + } + }) + if (tabs.length - 1 == index) { + itemValStr += ('(' + itemVal + ')') + } else { + itemValStr += ('(' + itemVal + '),') + } + }) + let keys = Object.keys(tabs[0]) + let keyStr = keys.toString() + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: name, + sql: `insert or ignore into ${tabName} (${keyStr}) values ${itemValStr}`, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) +} + +/** + * 获取分页数据库数据 + * @param {String} tabName 表名 + * @param {Number} num 页码 + * @param {Number} size 每页数据条数 + * @param {String} byName 排序字段 + * @param {String} byType 排序方式 +*/ +export const getDataList = async (tabName, num = 1, size = 15, byName, byType) => { + let count = 0 + let sql = '' + let numindex = 0 + let total = 0 + await getCount(tabName).then((resNum) => { + count = Math.ceil(resNum[0].num / size) + total = resNum[0].num + }) + if(((num - 1) * size) == 0) { + numindex = 0 + } else { + numindex = ((num - 1) * size) + 1 + } + sql = `select * from ${tabName}` + if(byName && byType) { + // desc asc + sql += ` order by ${byName} ${byType}` + } + sql += ` limit ${numindex},${size}` + if (count < num - 1) { + return new Promise((resolve, reject) => { + reject("无数据") + }); + } else { + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: dbName, + // sql: "select * from userInfo limit 3 offset 3", + sql:sql , + success(e) { + let data = { list: e, totalPage: count, total: total } + resolve(data); + }, + fail(e) { + reject(e); + } + }) + }) + } +} +//查询数据库数据 +export const selectDataList = (tabName,setData,byName,byType) => { + let setStr = '' + let sql = '' + if (JSON.stringify(setData) !== '{}') { + let dataKeys = Object.keys(setData) + dataKeys.forEach((item, index) => { + console.log(setData[item]) + setStr += ( + `${item}=${JSON.stringify(setData[item])}${dataKeys.length - 1 !== index ? " and " : ""}`) + }) + sql = `select * from ${tabName} where ${setStr}` + } else { + sql = `select * from ${tabName}` + } + if(byName && byType) { + // desc asc + sql += ` order by ${byName} ${byType}` + } + console.log(sql) + if (tabName !== undefined) { + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: dbName, + sql: sql, + success(e) { + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + } + }) + }) + } else { + return new Promise((resolve, reject) => { + reject("错误") + }); + } +} + +// 删除数据表 +export const dropTable = (tabName) => { + return new Promise((resolve, reject) => { + plus.sqlite.executeSql({ + name: dbName, + sql: `DROP TABLE ${tabName}`, + success(e) { + resolve(e); + }, + fail(e) { + reject(e); + } + }) + }) +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/js_sdk/zw-devicemac/devicemac.js b/js_sdk/zw-devicemac/devicemac.js new file mode 100644 index 0000000..fbca70f --- /dev/null +++ b/js_sdk/zw-devicemac/devicemac.js @@ -0,0 +1,114 @@ +//获取mac地址 + +// "" +// "" +// "" +// "" +export function getMacAddress() { + try { + var NetworkInterface = plus.android.importClass('java.net.NetworkInterface') + var interfaces = NetworkInterface.getNetworkInterfaces() + + // 直接使用 Enumeration 的方法(而非 Iterator) + while (plus.android.invoke(interfaces, 'hasMoreElements')) { + var intf = plus.android.invoke(interfaces, 'nextElement') + var name = plus.android.invoke(intf, 'getName') + + if (name === 'wlan0' || name === 'eth0' || name === 'wlan1') { + var macBytes = plus.android.invoke(intf, 'getHardwareAddress') + if (macBytes) { + var macStr = Array.from(macBytes) + .map(byte => (byte & 0xff).toString(16).padStart(2, '0')) + .join(':') + .toUpperCase() + console.log('MAC Address:', macStr) + return macStr + } + } + } + + console.error('No valid MAC address found') + return null + } catch (e) { + console.error('Failed to get MAC address:', e) + return null + } +} +// 获取唯一设备ID +export function getDeviceId() { + var settings = plus.android.importClass('android.provider.Settings') + var Secure = settings.Secure + var context = plus.android.runtimeMainActivity() + var androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID) + return androidId +} +// 备用方案 获取UUID +export function generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) +} +// +/** + * 获取蓝牙 MAC 地址(兼容 Android 5.0+) + * @returns {string|null} MAC 地址(格式 "XX:XX:XX:XX:XX:XX"),失败返回 null + */ +function getBluetoothMacLegacy() { + if (plus.os.name !== 'Android') { + console.error('仅支持 Android') + return null + } + + try { + const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter') + const adapter = BluetoothAdapter.getDefaultAdapter() + if (!adapter) { + console.error('蓝牙未启用') + return null + } + + const mac = plus.android.invoke(adapter, 'getAddress') + if (mac && mac !== '02:00:00:00:00:00') { + return mac + } + return null + } catch (e) { + console.error('获取失败:', e) + return null + } +} +function getBluetoothMacModern() { + try { + const Context = plus.android.importClass('android.content.Context') + const BluetoothManager = plus.android.importClass('android.bluetooth.BluetoothManager') + + const mainActivity = plus.android.runtimeMainActivity() + const bluetoothManager = mainActivity.getSystemService(Context.BLUETOOTH_SERVICE) + const adapter = plus.android.invoke(bluetoothManager, 'getAdapter') + + if (!adapter) return null + + const mac = plus.android.invoke(adapter, 'getAddress') + return mac && mac !== '02:00:00:00:00:00' ? mac : null + } catch (e) { + console.error('BluetoothManager 方式失败:', e) + return null + } +} +export function getBluetoothMacAddress() { + const Build = plus.android.importClass('android.os.Build') + const isModernAndroid = Build.VERSION.SDK_INT >= 23 // Android 6.0+ + + // 先尝试新方法,再回退旧方法 + const mac = isModernAndroid ? getBluetoothMacModern() : getBluetoothMacLegacy() + + if (mac) { + console.log('获取到蓝牙 MAC:', mac) + return mac + } else { + console.error('无法获取真实 MAC') + return null + } +} diff --git a/js_sdk/zw-devicemac/package.json b/js_sdk/zw-devicemac/package.json new file mode 100644 index 0000000..a19c5bd --- /dev/null +++ b/js_sdk/zw-devicemac/package.json @@ -0,0 +1,27 @@ +{ + "id": "zw-devicemac", + "name": "获取安卓设备MAC地址", + "displayName": "获取安卓设备MAC地址", + "version": "0.1.0", + "description": "兼容vue3用于获取安卓设备MAC地址,可支持Wi-Fi/蜂窝网络", + "keywords": [ + "js", + "安卓MAC地址", + "vue3" + ], + "dcloudext": { + "type": "js_sdk", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + } + }, + "uni_modules": { + "dependencies": [], + "encrypt": [] + } +} \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..f9c6e01 --- /dev/null +++ b/main.js @@ -0,0 +1,34 @@ +import App from './App' +import * as antIcons from '@ant-design/icons-vue'; +import Antd from 'ant-design-vue'; + +import 'ant-design-vue/dist/antd.css'; +// import { notification } from 'ant-design-vue'; +// import components from './components/global'; +import './assets/global.css'; + +// #ifndef VUE3 +// import Vue from 'vue' +// import './uni.promisify.adaptor' +// Vue.config.productionTip = false +// App.mpType = 'app' +// const app = new Vue({ +// ...App +// }) +// app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +import store from './store' +export function createApp() { + const app = createSSRApp(App) + + + app.use(store).use(Antd); + + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..caf4bc1 --- /dev/null +++ b/manifest.json @@ -0,0 +1,121 @@ +{ + "name" : "endoscope", + "appid" : "__UNI__5A0A7D6", + "description" : "", + "versionName" : "1.0.1", + "versionCode" : 106, + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : false, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : { + "SQLite" : {} + }, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ], + "minSdkVersion" : 21 + }, + /* ios打包配置 */ + "ios" : { + "idfa" : false, + "dSYMs" : false + }, + /* SDK配置 */ + "sdkConfigs" : {}, + "splashscreen" : { + "androidStyle" : "common", + "android" : { + "hdpi" : "", + "xhdpi" : "", + "xxhdpi" : "" + } + }, + "icons" : { + "android" : { + "hdpi" : "unpackage/res/icons/72x72.png", + "xhdpi" : "unpackage/res/icons/96x96.png", + "xxhdpi" : "unpackage/res/icons/144x144.png", + "xxxhdpi" : "unpackage/res/icons/192x192.png" + }, + "ios" : { + "appstore" : "unpackage/res/icons/1024x1024.png", + "ipad" : { + "app" : "unpackage/res/icons/76x76.png", + "app@2x" : "unpackage/res/icons/152x152.png", + "notification" : "unpackage/res/icons/20x20.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "proapp@2x" : "unpackage/res/icons/167x167.png", + "settings" : "unpackage/res/icons/29x29.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "spotlight" : "unpackage/res/icons/40x40.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png" + }, + "iphone" : { + "app@2x" : "unpackage/res/icons/120x120.png", + "app@3x" : "unpackage/res/icons/180x180.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "notification@3x" : "unpackage/res/icons/60x60.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "settings@3x" : "unpackage/res/icons/87x87.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png", + "spotlight@3x" : "unpackage/res/icons/120x120.png" + } + } + } + }, + "nativePlugins" : {} + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3", + "locale" : "zh-Hans" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7db0c1e --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "ant-design-vue": "^3.2.20" + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..7c1894a --- /dev/null +++ b/pages.json @@ -0,0 +1,107 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/start", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/index", + "style": { + "navigationStyle": "custom", + "app-plus": { + "animationType": "none" + } + } + }, + { + "path": "pages/log", + "style": { + "navigationStyle": "custom", + "app-plus": { + "animationType": "none" + } + } + }, + { + "path": "pages/setting", + "style": { + "navigationStyle": "custom", + "app-plus": { + "animationType": "none" + } + } + }, + { + "path": "pages/set/net", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/set/base", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/set/device", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/set/endomanage", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/set/personmanage", + "style": { + "navigationStyle": "custom" + } + }, + { + "path": "pages/set/run", + "style": { + "navigationStyle": "custom" + } + }, + { + "path" : "pages/modbus/modbus", + "style" : + { + "navigationBarTitleText" : "串口调试" + } + }, + { + "path" : "pages/database/database", + "style" : + { + "navigationBarTitleText" : "存储调试" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "#fff", + "navigationBarTitleText": "", + "navigationBarBackgroundColor": "#000000", + "backgroundColor": "#000000" + }, + "uniIdRouter": {}, + // "condition": { + // "current": 0, + // "list": [{ + // "name": "", + // "path": "pages/index" + // }] + // }, + "easycom": { + "autoscan": true, + "custom": { + "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" + } + } +} diff --git a/pages/database/database.vue b/pages/database/database.vue new file mode 100644 index 0000000..40eefae --- /dev/null +++ b/pages/database/database.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/pages/index.vue b/pages/index.vue new file mode 100644 index 0000000..3ddf9af --- /dev/null +++ b/pages/index.vue @@ -0,0 +1,536 @@ + + + + + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..23fac09 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/pages/log.vue b/pages/log.vue new file mode 100644 index 0000000..2233de8 --- /dev/null +++ b/pages/log.vue @@ -0,0 +1,168 @@ + + + + + \ No newline at end of file diff --git a/pages/modbus/modbus.vue b/pages/modbus/modbus.vue new file mode 100644 index 0000000..1665454 --- /dev/null +++ b/pages/modbus/modbus.vue @@ -0,0 +1,432 @@ + + + + + diff --git a/pages/set/base.vue b/pages/set/base.vue new file mode 100644 index 0000000..541c6c9 --- /dev/null +++ b/pages/set/base.vue @@ -0,0 +1,184 @@ + + + + + \ No newline at end of file diff --git a/pages/set/device.vue b/pages/set/device.vue new file mode 100644 index 0000000..4c17bbd --- /dev/null +++ b/pages/set/device.vue @@ -0,0 +1,101 @@ + + + + + \ No newline at end of file diff --git a/pages/set/endomanage.vue b/pages/set/endomanage.vue new file mode 100644 index 0000000..1230bd3 --- /dev/null +++ b/pages/set/endomanage.vue @@ -0,0 +1,291 @@ + + + + + \ No newline at end of file diff --git a/pages/set/net.vue b/pages/set/net.vue new file mode 100644 index 0000000..0f9ed71 --- /dev/null +++ b/pages/set/net.vue @@ -0,0 +1,159 @@ + + + + + \ No newline at end of file diff --git a/pages/set/personmanage.vue b/pages/set/personmanage.vue new file mode 100644 index 0000000..329d9ed --- /dev/null +++ b/pages/set/personmanage.vue @@ -0,0 +1,277 @@ + + + + + \ No newline at end of file diff --git a/pages/set/run.vue b/pages/set/run.vue new file mode 100644 index 0000000..f34b7db --- /dev/null +++ b/pages/set/run.vue @@ -0,0 +1,318 @@ + + + + + \ No newline at end of file diff --git a/pages/setting.vue b/pages/setting.vue new file mode 100644 index 0000000..c6d7f0e --- /dev/null +++ b/pages/setting.vue @@ -0,0 +1,214 @@ + + + + + \ No newline at end of file diff --git a/pages/start.vue b/pages/start.vue new file mode 100644 index 0000000..1ff5960 --- /dev/null +++ b/pages/start.vue @@ -0,0 +1,764 @@ + + + + + \ No newline at end of file diff --git a/static/beep_01.mp3 b/static/beep_01.mp3 new file mode 100644 index 0000000..d08c8ea Binary files /dev/null and b/static/beep_01.mp3 differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..a970a14 --- /dev/null +++ b/store/index.js @@ -0,0 +1,112 @@ +import { createStore } from 'vuex' + +const store = createStore({ + modules: { + }, + state: { + time: '', // 当前时间 + apiUrl: '', // 接口地址 + // 继电器状态 + relay: { + 'door': false, // 开门状态 + 'wind': false, // 风机状态 + 'light': false, // 灯状态 + 'vacuum': false, // 真空泵状态 + 'disinfect': false // 消毒状态 + }, + + // 清扫模式 + clean: false, + // 自动消毒 + autoDisinfect: true, + // 联网模式 + connect: false, + timer: { + 'disinfect': '', // 自动消毒开始时间 + 'wind': '', // 风机开始时间' + 'vacuumStart': '', // 真空泵开始时间 + 'vacuumEnd': '', // 真空泵开始时间 + 'door': '', // 开门开始时间,(6) 3min未关门报警 + 'doorAlert': false // 开门报警声 + }, + // 传感器状态 + sensor: { + temp: 0, + humi: 0, + pressure: 0, + }, + // 基础设置 + base: { + name: '', // 设备名称 + settingPw: '', // 设置密码 + screenPw: '', /// 屏幕密码 + apiKey: '', + }, + // 运行设置 + run: { + endoNear: '72', // 内镜存储临期时间(小时) + endoOver: '96', // 内镜存储超时时间(小时) + temp: '16', // 温度预警 + humi: '30', // 湿度预警 + pressure: '5', // 压差预警 + pressureCom: '+5', // 压差补偿 + + // 自动消毒周期 + group: [{ + start: { h: '00', m: '00' }, + end: { h: '02', m: '00' }, + status: true + },{ + start: { h: '06', m: '00' }, + end: { h: '08', m: '00' }, + status: true + },{ + start: { h: '12', m: '00' }, + end: { h: '14', m: '00' }, + status: true + },{ + start: { h: '18', m: '00' }, + end: { h: '20', m: '00' }, + status: true + }], + disinfectTime: '10', // 手动消毒时长 + + vacuumPerHour: '1', // 真空泵每隔多长时间运行一次 + vacuumRunTime: '10', // 真空泵运行时长 + } + + }, + getters: { + base: state => state.base, + run: state => state.run, + relay: state => state.relay, + status: state => state.status, + sensor: state => state.sensor, + apiUrl: state => state.apiUrl, + }, + mutations: { + SET_BASE(state, base) { + state.base = { ...state.base, ...base } + }, + SET_RUN(state, run) { + state.run = { ...state.run, ...run } + }, + SET_TIME(state, time) { + state.time = time + }, + CLEAR_TIMER(state) { + state.timer = { + 'disinfect': '', // 自动消毒开始时间 + 'wind': '', // 风机开始时间' + 'vacuumStart': '', // 真空泵开始时间 + 'vacuumEnd': '', // 真空泵开始时间 + 'door': '', // 开门开始时间,(6) 3min未关门报警 + 'doorAlert': false // 开门报警声 + } + }, + }, + actions: { + + } +}) +export default store \ No newline at end of file diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -0,0 +1,13 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => { + if (!res) return resolve(res) + return res[0] ? reject(res[0]) : resolve(res[1]) + }); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..b9249e9 --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/uni_modules/android-serialport/changelog.md b/uni_modules/android-serialport/changelog.md new file mode 100644 index 0000000..bc8ec32 --- /dev/null +++ b/uni_modules/android-serialport/changelog.md @@ -0,0 +1,19 @@ +## 1.0.9(2025-04-19) +优化 + +## 1.0.8(2025-04-08) +去掉安全判断 +## 1.0.7(2025-02-28) +优化 +## 1.0.6(2025-02-11) +优化 +## 1.0.5(2025-01-16) +修复uniapp bug +## 1.0.4(2024-10-28) +修改uniapp @UTSJS.keepAlive 问题 +## 1.0.3(2024-10-08) +已知问题修复 +## 1.0.1(2024-09-04) +修复bug +## 1.0.0(2024-09-03) +初始化,本周内完善文档 diff --git a/uni_modules/android-serialport/encrypt b/uni_modules/android-serialport/encrypt new file mode 100644 index 0000000..5176376 Binary files /dev/null and b/uni_modules/android-serialport/encrypt differ diff --git a/uni_modules/android-serialport/package.json b/uni_modules/android-serialport/package.json new file mode 100644 index 0000000..1cf2e56 --- /dev/null +++ b/uni_modules/android-serialport/package.json @@ -0,0 +1,87 @@ +{ + "id": "android-serialport", + "displayName": "Android平台串口通信 serialport(长期维护)", + "version": "1.0.9", + "description": "android/安卓平台串口通信uts,支持串口号、波特率、数据位、校验位、停止位、流控等参数设置(长期维护)", + "keywords": [ + "SerialPort串口", + "UTS", + "安卓串口,233,485" +], + "repository": "", + "engines": { + "HBuilderX": "^3.91" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "19.99" + }, + "sourcecode": { + "price": "101.00" + } + }, + "contact": { + "qq": "1530948626" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据\n使用过程中有任何问题可以加qq 1530948626 联系,随时修复", + "permissions": "必须ROOT" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "y" + }, + "client": { + "Vue": { + "vue2": "u", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "21" + }, + "app-ios": "n", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/android-serialport/readme.md b/uni_modules/android-serialport/readme.md new file mode 100644 index 0000000..ff1558d --- /dev/null +++ b/uni_modules/android-serialport/readme.md @@ -0,0 +1,173 @@ +# android-serialport +### uniappx/uniapp demo 亲测可用 +### 长期维护 有任何问题 可在群中联系 +### uniapp demo 在例子项目下的 zip 文件 +#### 插件测试使用方法 +1. 选择试用,绑定要试用的项目appid, + +2. 选择后下载到对应的本地项目, + +3. 按照文档 -》把插件引入项目(即 import {SerialPortHelper} from "@/uni_modules/android-serialport"; 需要先引入), + +4. 发布-》云打包-》选择制作基座-》打包等基座制作完成 + +5. 运行 -》 运行到手机或模拟器-》运行到Androidapp基座-》选择使用自定义基座运行-》选择手机-》运行 +### uni-app x项目(uvue)中调用示例:(调试需要自定义基座) +``` +import {SerialPortHelper} from "@/uni_modules/android-serialport"; + +var helper=new SerialPortHelper(); +// var array=[] as string[]; +// array=helper.getAllDevices() // 获取串口列表 + +helper.setPath("/dev/ttyS7"); +helper.setBaudrate(9600); +//一般默认 +// helper.dataBits(8); +// helper.parity(0); +// helper.stopBits(1); +// helper.flags(0) +var state= helper.open(); +if(state){ + helper.startAutoReadData(function(res){ + // console.log(res[0]) + console.log(helper.byte2HexString(res)) + }) + // var b:ByteArray=new ByteArray(5); + // b[0]=0x55; + // b[1]=0x00; + // b[2]=0x12; + // b[3]=0x00; + // b[4]=0x7B; + // helper.sendData(b) + + helper.sendDataString("550120057B") + + //停止自动接收 + // helper.stopReadPortData(); + + //关闭串口 + // helper.close() +} + +``` +### uni-app 项目(vue nvue)中调用示例:(调试需要自定义基座) + ``` +import {SerialPortHelper} from "@/uni_modules/android-serialport"; + + + var helper=new SerialPortHelper(); +// console.log(helper.getAllDevices()) + helper.setPath("/dev/ttyS7"); + helper.setBaudrate(9600); + var state= helper.open(); + if(state){ + helper.startAutoReadData(function(res){ + console.log(helper.uint8ArrayToHexString(res)) + }) + var b=new Uint8Array(5); + b[0]=0x55; + b[1]=0x00; + b[2]=0x12; + b[3]=0x00; + b[4]=0x7B; + helper.sendDataUnit8Array(b) + //helper.sendDataString("550120057B") + } + +``` + +### 开发文档 +### 获取设备列表 +#### getAllDevice() +return 串口列表 + +### 设置串口参数 + setPath 设置路径 +#### +setBaudrate 设置波特率 +#### + dataBits 数据位 默认8,可选值为5~8 +#### + parity 校验位 parity 0:无校验位(默认);1:奇校验位 +### +stopBits 停止位 stopBits 默认1;1:1位停止位;2:2位停止位 +### +flags 标志 flags 默认0 + + +### 打开串口 + +#### open 需要调用才可打开 +return 返回是否打开成功 + + +#### isOpen +return 返回是否打开成功 + +### 关闭串口 + +close + +### 开启自动读取串口数据,需要先打开串口 +#### startAutoReadData + 回调读取的数据function 数据类型为ByteArray + +### 关闭自动读取串口数据 +#### stopReadPortData + + +### 手动读取串口数据 手动读取之前需先打开串口 且不可和自动读串口数据同时调用 +#### available() +return 返回-1 表示无可读数据 其它为可读数据长度 + + +#### readData +参数1 需要读取数据的长度 number +参数2 开始读取位置 number +参数3 读取数据结束位置 number +参数4 回调读取的数据function 数据类型为ByteArray + + +### 发送数据 +#### sendData +参数1 需要发送的ByteArray + +#### sendDataString +参数1 string 类型的16进制的字符串 例如 "550120057B" + +### 辅助转换方法 + +### 将16进制字符串转换为ByteArray +#### parseHexStr2Byte +参数1 为16进制字符串 + +### ByteArray转换成16进制字符串 +#### byte2HexString +参数1 ByteArray + +### ByteArray 辅助操作方法 +#### 将两个ByteArray进行合并 + +#### addBytes +参数1 合并ByetArray 1 +参数2 合并ByetArray 2 +return 合并后的ByetArray + + + +#### 将ByteArray进行剪切 + +#### subBytes +参数1 需要剪切的 ByetArray +参数2 开始位置 类型number +参数3 需要剪切的长度 number +return 剪切后的ByetArray + +#### js Unit8Array 转为String +#### uint8ArrayToHexString +参数1 Unit8Array + +return String + + diff --git a/uni_modules/android-serialport/utssdk/app-android/config.json b/uni_modules/android-serialport/utssdk/app-android/config.json new file mode 100644 index 0000000..ba5d3b4 --- /dev/null +++ b/uni_modules/android-serialport/utssdk/app-android/config.json @@ -0,0 +1,4 @@ +{ + "abis": ["armeabi-v7a", "arm64-v8a"], + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/uni_modules/android-serialport/utssdk/app-android/index.uts b/uni_modules/android-serialport/utssdk/app-android/index.uts new file mode 100644 index 0000000..2a3b133 Binary files /dev/null and b/uni_modules/android-serialport/utssdk/app-android/index.uts differ diff --git a/uni_modules/android-serialport/utssdk/app-android/libs/serialport-release.aar b/uni_modules/android-serialport/utssdk/app-android/libs/serialport-release.aar new file mode 100644 index 0000000..2b973c7 Binary files /dev/null and b/uni_modules/android-serialport/utssdk/app-android/libs/serialport-release.aar differ diff --git a/uni_modules/uni-data-select/changelog.md b/uni_modules/uni-data-select/changelog.md new file mode 100644 index 0000000..1681eae --- /dev/null +++ b/uni_modules/uni-data-select/changelog.md @@ -0,0 +1,51 @@ +## 1.1.0(2025-08-19) +- 新增 插槽 selected empty option +- 新增 mutiple 属性,支持多选功能 +- 新增 wrap 属性,支持选中的文字超过一行显示 +- 新增 align 属性,支持修改选中的文字显示的位置 +- 新增 hideRight 属性,支持隐藏右侧所有按钮 +- 新增 mode 属性,支持修改边框样式 +- 新增 事件 open close clear +## 1.0.10(2025-04-14) +- 修复 清除按钮不展示问题 +## 1.0.9(2025-03-26) +- 优化 默认背景为白色与整体组件保持风格统一 +## 1.0.8(2024-03-28) +- 修复 在vue2下:style动态绑定导致编译失败的bug +## 1.0.7(2024-01-20) +- 修复 长文本回显超过容器的bug,超过容器部分显示省略号 +## 1.0.6(2023-04-12) +- 修复 微信小程序点击时会改变背景颜色的 bug +## 1.0.5(2023-02-03) +- 修复 禁用时会显示清空按钮 +## 1.0.4(2023-02-02) +- 优化 查询条件短期内多次变更只查询最后一次变更后的结果 +- 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue +## 1.0.3(2023-01-16) +- 修复 不关联服务空间报错的问题 +## 1.0.2(2023-01-14) +- 新增 属性 `format` 可用于格式化显示选项内容 +## 1.0.1(2022-12-06) +- 修复 当where变化时,数据不会自动更新的问题 +## 0.1.9(2022-09-05) +- 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框 +## 0.1.8(2022-08-29) +- 修复 点击的位置不准确 +## 0.1.7(2022-08-12) +- 新增 支持 disabled 属性 +## 0.1.6(2022-07-06) +- 修复 pc端宽度异常的bug +## 0.1.5 +- 修复 pc端宽度异常的bug +## 0.1.4(2022-07-05) +- 优化 显示样式 +## 0.1.3(2022-06-02) +- 修复 localdata 赋值不生效的 bug +- 新增 支持 uni.scss 修改颜色 +- 新增 支持选项禁用(数据选项设置 disabled: true 即禁用) +## 0.1.2(2022-05-08) +- 修复 当 value 为 0 时选择不生效的 bug +## 0.1.1(2022-05-07) +- 新增 记住上次的选项(仅 collection 存在时有效) +## 0.1.0(2022-04-22) +- 初始化 diff --git a/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue b/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue new file mode 100644 index 0000000..85b2d7b --- /dev/null +++ b/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue @@ -0,0 +1,837 @@ + + + + + diff --git a/uni_modules/uni-data-select/package.json b/uni_modules/uni-data-select/package.json new file mode 100644 index 0000000..4033502 --- /dev/null +++ b/uni_modules/uni-data-select/package.json @@ -0,0 +1,106 @@ +{ + "id": "uni-data-select", + "displayName": "uni-data-select 下拉框选择器", + "version": "1.1.0", + "description": "通过数据驱动的下拉框选择器", + "keywords": [ + "uni-ui", + "select", + "uni-data-select", + "下拉框", + "下拉选" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.1", + "uni-app": "^4.45", + "uni-app-x": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-load-more" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "-", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "-", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-data-select/readme.md b/uni_modules/uni-data-select/readme.md new file mode 100644 index 0000000..eb58de3 --- /dev/null +++ b/uni_modules/uni-data-select/readme.md @@ -0,0 +1,8 @@ +## DataSelect 下拉框选择器 +> **组件名:uni-data-select** +> 代码块: `uDataSelect` + +当选项过多时,使用下拉菜单展示并选择内容 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-easyinput/changelog.md b/uni_modules/uni-easyinput/changelog.md new file mode 100644 index 0000000..065a7c4 --- /dev/null +++ b/uni_modules/uni-easyinput/changelog.md @@ -0,0 +1,121 @@ +## 1.1.22(2025-09-19) +- 修复 禁用状态下背景不生效的问题 +## 1.1.21(2025-08-26) +- 修复 在 @input 中修改 v-model 不生效的问题 +## 1.1.20(2025-08-19) +- 修复 微信小程序平台样式警告问题 +## 1.1.19(2024-07-18) +- 修复 初始值传入 null 导致input报错的bug +## 1.1.18(2024-04-11) +- 修复 easyinput组件双向绑定问题 +## 1.1.17(2024-03-28) +- 修复 在头条小程序下丢失事件绑定的问题 +## 1.1.16(2024-03-20) +- 修复 在密码输入情况下 清除和小眼睛覆盖bug 在edge浏览器下显示双眼睛bug +## 1.1.15(2024-02-21) +- 新增 左侧插槽:left +## 1.1.14(2024-02-19) +- 修复 onBlur的emit传值错误 +## 1.1.12(2024-01-29) +- 补充 adjust-position文档属性补充 +## 1.1.11(2024-01-29) +- 补充 adjust-position属性传递值:(Boolean)当键盘弹起时,是否自动上推页面 +## 1.1.10(2024-01-22) +- 去除 移除无用的log输出 +## 1.1.9(2023-04-11) +- 修复 vue3 下 keyboardheightchange 事件报错的bug +## 1.1.8(2023-03-29) +- 优化 trim 属性默认值 +## 1.1.7(2023-03-29) +- 新增 cursor-spacing 属性 +## 1.1.6(2023-01-28) +- 新增 keyboardheightchange 事件,可监听键盘高度变化 +## 1.1.5(2022-11-29) +- 优化 主题样式 +## 1.1.4(2022-10-27) +- 修复 props 中背景颜色无默认值的bug +## 1.1.0(2022-06-30) + +- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容 +- 新增 clear 事件,点击右侧叉号图标触发 +- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发 +- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等 + +## 1.0.5(2022-06-07) + +- 优化 clearable 显示策略 + +## 1.0.4(2022-06-07) + +- 优化 clearable 显示策略 + +## 1.0.3(2022-05-20) + +- 修复 关闭图标某些情况下无法取消的 bug + +## 1.0.2(2022-04-12) + +- 修复 默认值不生效的 bug + +## 1.0.1(2022-04-02) + +- 修复 value 不能为 0 的 bug + +## 1.0.0(2021-11-19) + +- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput) + +## 0.1.4(2021-08-20) + +- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug + +## 0.1.3(2021-08-11) + +- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 + +## 0.1.2(2021-07-30) + +- 优化 vue3 下事件警告的问题 + +## 0.1.1 + +- 优化 errorMessage 属性支持 Boolean 类型 + +## 0.1.0(2021-07-13) + +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) + +## 0.0.16(2021-06-29) + +- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug + +## 0.0.15(2021-06-21) + +- 修复 passwordIcon 属性拼写错误的 bug + +## 0.0.14(2021-06-18) + +- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标 +- 修复 confirmType 属性不生效的问题 + +## 0.0.13(2021-06-04) + +- 修复 disabled 状态可清出内容的 bug + +## 0.0.12(2021-05-12) + +- 新增 组件示例地址 + +## 0.0.11(2021-05-07) + +- 修复 input-border 属性不生效的问题 + +## 0.0.10(2021-04-30) + +- 修复 ios 遮挡文字、显示一半的问题 + +## 0.0.9(2021-02-05) + +- 调整为 uni_modules 目录规范 +- 优化 兼容 nvue 页面 diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/uni_modules/uni-easyinput/components/uni-easyinput/common.js new file mode 100644 index 0000000..fde8d3c --- /dev/null +++ b/uni_modules/uni-easyinput/components/uni-easyinput/common.js @@ -0,0 +1,54 @@ +/** + * @desc 函数防抖 + * @param func 目标函数 + * @param wait 延迟执行毫秒数 + * @param immediate true - 立即执行, false - 延迟执行 + */ +export const debounce = function(func, wait = 1000, immediate = true) { + let timer; + return function() { + let context = this, + args = arguments; + if (timer) clearTimeout(timer); + if (immediate) { + let callNow = !timer; + timer = setTimeout(() => { + timer = null; + }, wait); + if (callNow) func.apply(context, args); + } else { + timer = setTimeout(() => { + func.apply(context, args); + }, wait) + } + } +} +/** + * @desc 函数节流 + * @param func 函数 + * @param wait 延迟执行毫秒数 + * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发 + */ +export const throttle = (func, wait = 1000, type = 1) => { + let previous = 0; + let timeout; + return function() { + let context = this; + let args = arguments; + if (type === 1) { + let now = Date.now(); + + if (now - previous > wait) { + func.apply(context, args); + previous = now; + } + } else if (type === 2) { + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + func.apply(context, args) + }, wait) + } + } + } +} diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue new file mode 100644 index 0000000..a328da7 --- /dev/null +++ b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue @@ -0,0 +1,662 @@ + + + + + diff --git a/uni_modules/uni-easyinput/package.json b/uni_modules/uni-easyinput/package.json new file mode 100644 index 0000000..00de64a --- /dev/null +++ b/uni_modules/uni-easyinput/package.json @@ -0,0 +1,107 @@ +{ + "id": "uni-easyinput", + "displayName": "uni-easyinput 增强输入框", + "version": "1.1.22", + "description": "Easyinput 组件是对原生input组件的增强", + "keywords": [ + "uni-ui", + "uniui", + "input", + "uni-easyinput", + "输入框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "", + "uni-app": "^4.07", + "uni-app-x": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "√", + "jd": "√", + "harmony": "√", + "qq": "√", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-easyinput/readme.md b/uni_modules/uni-easyinput/readme.md new file mode 100644 index 0000000..f1faf8f --- /dev/null +++ b/uni_modules/uni-easyinput/readme.md @@ -0,0 +1,11 @@ + + +### Easyinput 增强输入框 +> **组件名:uni-easyinput** +> 代码块: `uEasyinput` + + +easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-grid/changelog.md b/uni_modules/uni-grid/changelog.md new file mode 100644 index 0000000..d301166 --- /dev/null +++ b/uni_modules/uni-grid/changelog.md @@ -0,0 +1,13 @@ +## 1.4.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-grid](https://uniapp.dcloud.io/component/uniui/uni-grid) +## 1.3.2(2021-11-09) +- 新增 提供组件设计资源,组件样式调整 +## 1.3.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.3.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.2.4(2021-05-12) +- 新增 组件示例地址 +## 1.2.3(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue b/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue new file mode 100644 index 0000000..19c08d7 --- /dev/null +++ b/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/uni_modules/uni-grid/components/uni-grid/uni-grid.vue b/uni_modules/uni-grid/components/uni-grid/uni-grid.vue new file mode 100644 index 0000000..0edc7ff --- /dev/null +++ b/uni_modules/uni-grid/components/uni-grid/uni-grid.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/uni_modules/uni-grid/package.json b/uni_modules/uni-grid/package.json new file mode 100644 index 0000000..ccb2c91 --- /dev/null +++ b/uni_modules/uni-grid/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-grid", + "displayName": "uni-grid 宫格", + "version": "1.4.0", + "description": "Grid 宫格组件,提供移动端常见的宫格布局,如九宫格。", + "keywords": [ + "uni-ui", + "uniui", + "九宫格", + "表格" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss","uni-icons"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-grid/readme.md b/uni_modules/uni-grid/readme.md new file mode 100644 index 0000000..0aa44cc --- /dev/null +++ b/uni_modules/uni-grid/readme.md @@ -0,0 +1,11 @@ + + +## Grid 宫格 +> **组件名:uni-grid** +> 代码块: `uGrid` + + +宫格组件。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-grid) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-icons/changelog.md b/uni_modules/uni-icons/changelog.md new file mode 100644 index 0000000..62e7682 --- /dev/null +++ b/uni_modules/uni-icons/changelog.md @@ -0,0 +1,44 @@ +## 2.0.12(2025-08-26) +- 优化 uni-app x 下 size 类型问题 +## 2.0.11(2025-08-18) +- 修复 图标点击事件返回 +## 2.0.9(2024-01-12) +fix: 修复图标大小默认值错误的问题 +## 2.0.8(2023-12-14) +- 修复 项目未使用 ts 情况下,打包报错的bug +## 2.0.7(2023-12-14) +- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug +## 2.0.6(2023-12-11) +- 优化 兼容老版本icon类型,如 top ,bottom 等 +## 2.0.5(2023-12-11) +- 优化 兼容老版本icon类型,如 top ,bottom 等 +## 2.0.4(2023-12-06) +- 优化 uni-app x 下示例项目图标排序 +## 2.0.3(2023-12-06) +- 修复 nvue下引入组件报错的bug +## 2.0.2(2023-12-05) +-优化 size 属性支持单位 +## 2.0.1(2023-12-05) +- 新增 uni-app x 支持定义图标 +## 1.3.5(2022-01-24) +- 优化 size 属性可以传入不带单位的字符串数值 +## 1.3.4(2022-01-24) +- 优化 size 支持其他单位 +## 1.3.3(2022-01-17) +- 修复 nvue 有些图标不显示的bug,兼容老版本图标 +## 1.3.2(2021-12-01) +- 优化 示例可复制图标名称 +## 1.3.1(2021-11-23) +- 优化 兼容旧组件 type 值 +## 1.3.0(2021-11-19) +- 新增 更多图标 +- 优化 自定义图标使用方式 +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons) +## 1.1.7(2021-11-08) +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.5(2021-05-12) +- 新增 组件示例地址 +## 1.1.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue new file mode 100644 index 0000000..53eb2ea --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue @@ -0,0 +1,91 @@ + + + + + diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 0000000..1bd3d5e --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,110 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.css b/uni_modules/uni-icons/components/uni-icons/uniicons.css new file mode 100644 index 0000000..0a6b6fe --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons.css @@ -0,0 +1,664 @@ + +.uniui-cart-filled:before { + content: "\e6d0"; +} + +.uniui-gift-filled:before { + content: "\e6c4"; +} + +.uniui-color:before { + content: "\e6cf"; +} + +.uniui-wallet:before { + content: "\e6b1"; +} + +.uniui-settings-filled:before { + content: "\e6ce"; +} + +.uniui-auth-filled:before { + content: "\e6cc"; +} + +.uniui-shop-filled:before { + content: "\e6cd"; +} + +.uniui-staff-filled:before { + content: "\e6cb"; +} + +.uniui-vip-filled:before { + content: "\e6c6"; +} + +.uniui-plus-filled:before { + content: "\e6c7"; +} + +.uniui-folder-add-filled:before { + content: "\e6c8"; +} + +.uniui-color-filled:before { + content: "\e6c9"; +} + +.uniui-tune-filled:before { + content: "\e6ca"; +} + +.uniui-calendar-filled:before { + content: "\e6c0"; +} + +.uniui-notification-filled:before { + content: "\e6c1"; +} + +.uniui-wallet-filled:before { + content: "\e6c2"; +} + +.uniui-medal-filled:before { + content: "\e6c3"; +} + +.uniui-fire-filled:before { + content: "\e6c5"; +} + +.uniui-refreshempty:before { + content: "\e6bf"; +} + +.uniui-location-filled:before { + content: "\e6af"; +} + +.uniui-person-filled:before { + content: "\e69d"; +} + +.uniui-personadd-filled:before { + content: "\e698"; +} + +.uniui-arrowthinleft:before { + content: "\e6d2"; +} + +.uniui-arrowthinup:before { + content: "\e6d3"; +} + +.uniui-arrowthindown:before { + content: "\e6d4"; +} + +.uniui-back:before { + content: "\e6b9"; +} + +.uniui-forward:before { + content: "\e6ba"; +} + +.uniui-arrow-right:before { + content: "\e6bb"; +} + +.uniui-arrow-left:before { + content: "\e6bc"; +} + +.uniui-arrow-up:before { + content: "\e6bd"; +} + +.uniui-arrow-down:before { + content: "\e6be"; +} + +.uniui-arrowthinright:before { + content: "\e6d1"; +} + +.uniui-down:before { + content: "\e6b8"; +} + +.uniui-bottom:before { + content: "\e6b8"; +} + +.uniui-arrowright:before { + content: "\e6d5"; +} + +.uniui-right:before { + content: "\e6b5"; +} + +.uniui-up:before { + content: "\e6b6"; +} + +.uniui-top:before { + content: "\e6b6"; +} + +.uniui-left:before { + content: "\e6b7"; +} + +.uniui-arrowup:before { + content: "\e6d6"; +} + +.uniui-eye:before { + content: "\e651"; +} + +.uniui-eye-filled:before { + content: "\e66a"; +} + +.uniui-eye-slash:before { + content: "\e6b3"; +} + +.uniui-eye-slash-filled:before { + content: "\e6b4"; +} + +.uniui-info-filled:before { + content: "\e649"; +} + +.uniui-reload:before { + content: "\e6b2"; +} + +.uniui-micoff-filled:before { + content: "\e6b0"; +} + +.uniui-map-pin-ellipse:before { + content: "\e6ac"; +} + +.uniui-map-pin:before { + content: "\e6ad"; +} + +.uniui-location:before { + content: "\e6ae"; +} + +.uniui-starhalf:before { + content: "\e683"; +} + +.uniui-star:before { + content: "\e688"; +} + +.uniui-star-filled:before { + content: "\e68f"; +} + +.uniui-calendar:before { + content: "\e6a0"; +} + +.uniui-fire:before { + content: "\e6a1"; +} + +.uniui-medal:before { + content: "\e6a2"; +} + +.uniui-font:before { + content: "\e6a3"; +} + +.uniui-gift:before { + content: "\e6a4"; +} + +.uniui-link:before { + content: "\e6a5"; +} + +.uniui-notification:before { + content: "\e6a6"; +} + +.uniui-staff:before { + content: "\e6a7"; +} + +.uniui-vip:before { + content: "\e6a8"; +} + +.uniui-folder-add:before { + content: "\e6a9"; +} + +.uniui-tune:before { + content: "\e6aa"; +} + +.uniui-auth:before { + content: "\e6ab"; +} + +.uniui-person:before { + content: "\e699"; +} + +.uniui-email-filled:before { + content: "\e69a"; +} + +.uniui-phone-filled:before { + content: "\e69b"; +} + +.uniui-phone:before { + content: "\e69c"; +} + +.uniui-email:before { + content: "\e69e"; +} + +.uniui-personadd:before { + content: "\e69f"; +} + +.uniui-chatboxes-filled:before { + content: "\e692"; +} + +.uniui-contact:before { + content: "\e693"; +} + +.uniui-chatbubble-filled:before { + content: "\e694"; +} + +.uniui-contact-filled:before { + content: "\e695"; +} + +.uniui-chatboxes:before { + content: "\e696"; +} + +.uniui-chatbubble:before { + content: "\e697"; +} + +.uniui-upload-filled:before { + content: "\e68e"; +} + +.uniui-upload:before { + content: "\e690"; +} + +.uniui-weixin:before { + content: "\e691"; +} + +.uniui-compose:before { + content: "\e67f"; +} + +.uniui-qq:before { + content: "\e680"; +} + +.uniui-download-filled:before { + content: "\e681"; +} + +.uniui-pyq:before { + content: "\e682"; +} + +.uniui-sound:before { + content: "\e684"; +} + +.uniui-trash-filled:before { + content: "\e685"; +} + +.uniui-sound-filled:before { + content: "\e686"; +} + +.uniui-trash:before { + content: "\e687"; +} + +.uniui-videocam-filled:before { + content: "\e689"; +} + +.uniui-spinner-cycle:before { + content: "\e68a"; +} + +.uniui-weibo:before { + content: "\e68b"; +} + +.uniui-videocam:before { + content: "\e68c"; +} + +.uniui-download:before { + content: "\e68d"; +} + +.uniui-help:before { + content: "\e679"; +} + +.uniui-navigate-filled:before { + content: "\e67a"; +} + +.uniui-plusempty:before { + content: "\e67b"; +} + +.uniui-smallcircle:before { + content: "\e67c"; +} + +.uniui-minus-filled:before { + content: "\e67d"; +} + +.uniui-micoff:before { + content: "\e67e"; +} + +.uniui-closeempty:before { + content: "\e66c"; +} + +.uniui-clear:before { + content: "\e66d"; +} + +.uniui-navigate:before { + content: "\e66e"; +} + +.uniui-minus:before { + content: "\e66f"; +} + +.uniui-image:before { + content: "\e670"; +} + +.uniui-mic:before { + content: "\e671"; +} + +.uniui-paperplane:before { + content: "\e672"; +} + +.uniui-close:before { + content: "\e673"; +} + +.uniui-help-filled:before { + content: "\e674"; +} + +.uniui-paperplane-filled:before { + content: "\e675"; +} + +.uniui-plus:before { + content: "\e676"; +} + +.uniui-mic-filled:before { + content: "\e677"; +} + +.uniui-image-filled:before { + content: "\e678"; +} + +.uniui-locked-filled:before { + content: "\e668"; +} + +.uniui-info:before { + content: "\e669"; +} + +.uniui-locked:before { + content: "\e66b"; +} + +.uniui-camera-filled:before { + content: "\e658"; +} + +.uniui-chat-filled:before { + content: "\e659"; +} + +.uniui-camera:before { + content: "\e65a"; +} + +.uniui-circle:before { + content: "\e65b"; +} + +.uniui-checkmarkempty:before { + content: "\e65c"; +} + +.uniui-chat:before { + content: "\e65d"; +} + +.uniui-circle-filled:before { + content: "\e65e"; +} + +.uniui-flag:before { + content: "\e65f"; +} + +.uniui-flag-filled:before { + content: "\e660"; +} + +.uniui-gear-filled:before { + content: "\e661"; +} + +.uniui-home:before { + content: "\e662"; +} + +.uniui-home-filled:before { + content: "\e663"; +} + +.uniui-gear:before { + content: "\e664"; +} + +.uniui-smallcircle-filled:before { + content: "\e665"; +} + +.uniui-map-filled:before { + content: "\e666"; +} + +.uniui-map:before { + content: "\e667"; +} + +.uniui-refresh-filled:before { + content: "\e656"; +} + +.uniui-refresh:before { + content: "\e657"; +} + +.uniui-cloud-upload:before { + content: "\e645"; +} + +.uniui-cloud-download-filled:before { + content: "\e646"; +} + +.uniui-cloud-download:before { + content: "\e647"; +} + +.uniui-cloud-upload-filled:before { + content: "\e648"; +} + +.uniui-redo:before { + content: "\e64a"; +} + +.uniui-images-filled:before { + content: "\e64b"; +} + +.uniui-undo-filled:before { + content: "\e64c"; +} + +.uniui-more:before { + content: "\e64d"; +} + +.uniui-more-filled:before { + content: "\e64e"; +} + +.uniui-undo:before { + content: "\e64f"; +} + +.uniui-images:before { + content: "\e650"; +} + +.uniui-paperclip:before { + content: "\e652"; +} + +.uniui-settings:before { + content: "\e653"; +} + +.uniui-search:before { + content: "\e654"; +} + +.uniui-redo-filled:before { + content: "\e655"; +} + +.uniui-list:before { + content: "\e644"; +} + +.uniui-mail-open-filled:before { + content: "\e63a"; +} + +.uniui-hand-down-filled:before { + content: "\e63c"; +} + +.uniui-hand-down:before { + content: "\e63d"; +} + +.uniui-hand-up-filled:before { + content: "\e63e"; +} + +.uniui-hand-up:before { + content: "\e63f"; +} + +.uniui-heart-filled:before { + content: "\e641"; +} + +.uniui-mail-open:before { + content: "\e643"; +} + +.uniui-heart:before { + content: "\e639"; +} + +.uniui-loop:before { + content: "\e633"; +} + +.uniui-pulldown:before { + content: "\e632"; +} + +.uniui-scan:before { + content: "\e62a"; +} + +.uniui-bars:before { + content: "\e627"; +} + +.uniui-checkbox:before { + content: "\e62b"; +} + +.uniui-checkbox-filled:before { + content: "\e62c"; +} + +.uniui-shop:before { + content: "\e62f"; +} + +.uniui-headphones:before { + content: "\e630"; +} + +.uniui-cart:before { + content: "\e631"; +} diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf new file mode 100644 index 0000000..14696d0 Binary files /dev/null and b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf differ diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts new file mode 100644 index 0000000..98e93aa --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts @@ -0,0 +1,664 @@ + +export type IconsData = { + id : string + name : string + font_family : string + css_prefix_text : string + description : string + glyphs : Array +} + +export type IconsDataItem = { + font_class : string + unicode : string +} + + +export const fontData = [ + { + "font_class": "arrow-down", + "unicode": "\ue6be" + }, + { + "font_class": "arrow-left", + "unicode": "\ue6bc" + }, + { + "font_class": "arrow-right", + "unicode": "\ue6bb" + }, + { + "font_class": "arrow-up", + "unicode": "\ue6bd" + }, + { + "font_class": "auth", + "unicode": "\ue6ab" + }, + { + "font_class": "auth-filled", + "unicode": "\ue6cc" + }, + { + "font_class": "back", + "unicode": "\ue6b9" + }, + { + "font_class": "bars", + "unicode": "\ue627" + }, + { + "font_class": "calendar", + "unicode": "\ue6a0" + }, + { + "font_class": "calendar-filled", + "unicode": "\ue6c0" + }, + { + "font_class": "camera", + "unicode": "\ue65a" + }, + { + "font_class": "camera-filled", + "unicode": "\ue658" + }, + { + "font_class": "cart", + "unicode": "\ue631" + }, + { + "font_class": "cart-filled", + "unicode": "\ue6d0" + }, + { + "font_class": "chat", + "unicode": "\ue65d" + }, + { + "font_class": "chat-filled", + "unicode": "\ue659" + }, + { + "font_class": "chatboxes", + "unicode": "\ue696" + }, + { + "font_class": "chatboxes-filled", + "unicode": "\ue692" + }, + { + "font_class": "chatbubble", + "unicode": "\ue697" + }, + { + "font_class": "chatbubble-filled", + "unicode": "\ue694" + }, + { + "font_class": "checkbox", + "unicode": "\ue62b" + }, + { + "font_class": "checkbox-filled", + "unicode": "\ue62c" + }, + { + "font_class": "checkmarkempty", + "unicode": "\ue65c" + }, + { + "font_class": "circle", + "unicode": "\ue65b" + }, + { + "font_class": "circle-filled", + "unicode": "\ue65e" + }, + { + "font_class": "clear", + "unicode": "\ue66d" + }, + { + "font_class": "close", + "unicode": "\ue673" + }, + { + "font_class": "closeempty", + "unicode": "\ue66c" + }, + { + "font_class": "cloud-download", + "unicode": "\ue647" + }, + { + "font_class": "cloud-download-filled", + "unicode": "\ue646" + }, + { + "font_class": "cloud-upload", + "unicode": "\ue645" + }, + { + "font_class": "cloud-upload-filled", + "unicode": "\ue648" + }, + { + "font_class": "color", + "unicode": "\ue6cf" + }, + { + "font_class": "color-filled", + "unicode": "\ue6c9" + }, + { + "font_class": "compose", + "unicode": "\ue67f" + }, + { + "font_class": "contact", + "unicode": "\ue693" + }, + { + "font_class": "contact-filled", + "unicode": "\ue695" + }, + { + "font_class": "down", + "unicode": "\ue6b8" + }, + { + "font_class": "bottom", + "unicode": "\ue6b8" + }, + { + "font_class": "download", + "unicode": "\ue68d" + }, + { + "font_class": "download-filled", + "unicode": "\ue681" + }, + { + "font_class": "email", + "unicode": "\ue69e" + }, + { + "font_class": "email-filled", + "unicode": "\ue69a" + }, + { + "font_class": "eye", + "unicode": "\ue651" + }, + { + "font_class": "eye-filled", + "unicode": "\ue66a" + }, + { + "font_class": "eye-slash", + "unicode": "\ue6b3" + }, + { + "font_class": "eye-slash-filled", + "unicode": "\ue6b4" + }, + { + "font_class": "fire", + "unicode": "\ue6a1" + }, + { + "font_class": "fire-filled", + "unicode": "\ue6c5" + }, + { + "font_class": "flag", + "unicode": "\ue65f" + }, + { + "font_class": "flag-filled", + "unicode": "\ue660" + }, + { + "font_class": "folder-add", + "unicode": "\ue6a9" + }, + { + "font_class": "folder-add-filled", + "unicode": "\ue6c8" + }, + { + "font_class": "font", + "unicode": "\ue6a3" + }, + { + "font_class": "forward", + "unicode": "\ue6ba" + }, + { + "font_class": "gear", + "unicode": "\ue664" + }, + { + "font_class": "gear-filled", + "unicode": "\ue661" + }, + { + "font_class": "gift", + "unicode": "\ue6a4" + }, + { + "font_class": "gift-filled", + "unicode": "\ue6c4" + }, + { + "font_class": "hand-down", + "unicode": "\ue63d" + }, + { + "font_class": "hand-down-filled", + "unicode": "\ue63c" + }, + { + "font_class": "hand-up", + "unicode": "\ue63f" + }, + { + "font_class": "hand-up-filled", + "unicode": "\ue63e" + }, + { + "font_class": "headphones", + "unicode": "\ue630" + }, + { + "font_class": "heart", + "unicode": "\ue639" + }, + { + "font_class": "heart-filled", + "unicode": "\ue641" + }, + { + "font_class": "help", + "unicode": "\ue679" + }, + { + "font_class": "help-filled", + "unicode": "\ue674" + }, + { + "font_class": "home", + "unicode": "\ue662" + }, + { + "font_class": "home-filled", + "unicode": "\ue663" + }, + { + "font_class": "image", + "unicode": "\ue670" + }, + { + "font_class": "image-filled", + "unicode": "\ue678" + }, + { + "font_class": "images", + "unicode": "\ue650" + }, + { + "font_class": "images-filled", + "unicode": "\ue64b" + }, + { + "font_class": "info", + "unicode": "\ue669" + }, + { + "font_class": "info-filled", + "unicode": "\ue649" + }, + { + "font_class": "left", + "unicode": "\ue6b7" + }, + { + "font_class": "link", + "unicode": "\ue6a5" + }, + { + "font_class": "list", + "unicode": "\ue644" + }, + { + "font_class": "location", + "unicode": "\ue6ae" + }, + { + "font_class": "location-filled", + "unicode": "\ue6af" + }, + { + "font_class": "locked", + "unicode": "\ue66b" + }, + { + "font_class": "locked-filled", + "unicode": "\ue668" + }, + { + "font_class": "loop", + "unicode": "\ue633" + }, + { + "font_class": "mail-open", + "unicode": "\ue643" + }, + { + "font_class": "mail-open-filled", + "unicode": "\ue63a" + }, + { + "font_class": "map", + "unicode": "\ue667" + }, + { + "font_class": "map-filled", + "unicode": "\ue666" + }, + { + "font_class": "map-pin", + "unicode": "\ue6ad" + }, + { + "font_class": "map-pin-ellipse", + "unicode": "\ue6ac" + }, + { + "font_class": "medal", + "unicode": "\ue6a2" + }, + { + "font_class": "medal-filled", + "unicode": "\ue6c3" + }, + { + "font_class": "mic", + "unicode": "\ue671" + }, + { + "font_class": "mic-filled", + "unicode": "\ue677" + }, + { + "font_class": "micoff", + "unicode": "\ue67e" + }, + { + "font_class": "micoff-filled", + "unicode": "\ue6b0" + }, + { + "font_class": "minus", + "unicode": "\ue66f" + }, + { + "font_class": "minus-filled", + "unicode": "\ue67d" + }, + { + "font_class": "more", + "unicode": "\ue64d" + }, + { + "font_class": "more-filled", + "unicode": "\ue64e" + }, + { + "font_class": "navigate", + "unicode": "\ue66e" + }, + { + "font_class": "navigate-filled", + "unicode": "\ue67a" + }, + { + "font_class": "notification", + "unicode": "\ue6a6" + }, + { + "font_class": "notification-filled", + "unicode": "\ue6c1" + }, + { + "font_class": "paperclip", + "unicode": "\ue652" + }, + { + "font_class": "paperplane", + "unicode": "\ue672" + }, + { + "font_class": "paperplane-filled", + "unicode": "\ue675" + }, + { + "font_class": "person", + "unicode": "\ue699" + }, + { + "font_class": "person-filled", + "unicode": "\ue69d" + }, + { + "font_class": "personadd", + "unicode": "\ue69f" + }, + { + "font_class": "personadd-filled", + "unicode": "\ue698" + }, + { + "font_class": "personadd-filled-copy", + "unicode": "\ue6d1" + }, + { + "font_class": "phone", + "unicode": "\ue69c" + }, + { + "font_class": "phone-filled", + "unicode": "\ue69b" + }, + { + "font_class": "plus", + "unicode": "\ue676" + }, + { + "font_class": "plus-filled", + "unicode": "\ue6c7" + }, + { + "font_class": "plusempty", + "unicode": "\ue67b" + }, + { + "font_class": "pulldown", + "unicode": "\ue632" + }, + { + "font_class": "pyq", + "unicode": "\ue682" + }, + { + "font_class": "qq", + "unicode": "\ue680" + }, + { + "font_class": "redo", + "unicode": "\ue64a" + }, + { + "font_class": "redo-filled", + "unicode": "\ue655" + }, + { + "font_class": "refresh", + "unicode": "\ue657" + }, + { + "font_class": "refresh-filled", + "unicode": "\ue656" + }, + { + "font_class": "refreshempty", + "unicode": "\ue6bf" + }, + { + "font_class": "reload", + "unicode": "\ue6b2" + }, + { + "font_class": "right", + "unicode": "\ue6b5" + }, + { + "font_class": "scan", + "unicode": "\ue62a" + }, + { + "font_class": "search", + "unicode": "\ue654" + }, + { + "font_class": "settings", + "unicode": "\ue653" + }, + { + "font_class": "settings-filled", + "unicode": "\ue6ce" + }, + { + "font_class": "shop", + "unicode": "\ue62f" + }, + { + "font_class": "shop-filled", + "unicode": "\ue6cd" + }, + { + "font_class": "smallcircle", + "unicode": "\ue67c" + }, + { + "font_class": "smallcircle-filled", + "unicode": "\ue665" + }, + { + "font_class": "sound", + "unicode": "\ue684" + }, + { + "font_class": "sound-filled", + "unicode": "\ue686" + }, + { + "font_class": "spinner-cycle", + "unicode": "\ue68a" + }, + { + "font_class": "staff", + "unicode": "\ue6a7" + }, + { + "font_class": "staff-filled", + "unicode": "\ue6cb" + }, + { + "font_class": "star", + "unicode": "\ue688" + }, + { + "font_class": "star-filled", + "unicode": "\ue68f" + }, + { + "font_class": "starhalf", + "unicode": "\ue683" + }, + { + "font_class": "trash", + "unicode": "\ue687" + }, + { + "font_class": "trash-filled", + "unicode": "\ue685" + }, + { + "font_class": "tune", + "unicode": "\ue6aa" + }, + { + "font_class": "tune-filled", + "unicode": "\ue6ca" + }, + { + "font_class": "undo", + "unicode": "\ue64f" + }, + { + "font_class": "undo-filled", + "unicode": "\ue64c" + }, + { + "font_class": "up", + "unicode": "\ue6b6" + }, + { + "font_class": "top", + "unicode": "\ue6b6" + }, + { + "font_class": "upload", + "unicode": "\ue690" + }, + { + "font_class": "upload-filled", + "unicode": "\ue68e" + }, + { + "font_class": "videocam", + "unicode": "\ue68c" + }, + { + "font_class": "videocam-filled", + "unicode": "\ue689" + }, + { + "font_class": "vip", + "unicode": "\ue6a8" + }, + { + "font_class": "vip-filled", + "unicode": "\ue6c6" + }, + { + "font_class": "wallet", + "unicode": "\ue6b1" + }, + { + "font_class": "wallet-filled", + "unicode": "\ue6c2" + }, + { + "font_class": "weibo", + "unicode": "\ue68b" + }, + { + "font_class": "weixin", + "unicode": "\ue691" + } +] as IconsDataItem[] + +// export const fontData = JSON.parse(fontDataJson) diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js new file mode 100644 index 0000000..1cd11e1 --- /dev/null +++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js @@ -0,0 +1,649 @@ + +export const fontData = [ + { + "font_class": "arrow-down", + "unicode": "\ue6be" + }, + { + "font_class": "arrow-left", + "unicode": "\ue6bc" + }, + { + "font_class": "arrow-right", + "unicode": "\ue6bb" + }, + { + "font_class": "arrow-up", + "unicode": "\ue6bd" + }, + { + "font_class": "auth", + "unicode": "\ue6ab" + }, + { + "font_class": "auth-filled", + "unicode": "\ue6cc" + }, + { + "font_class": "back", + "unicode": "\ue6b9" + }, + { + "font_class": "bars", + "unicode": "\ue627" + }, + { + "font_class": "calendar", + "unicode": "\ue6a0" + }, + { + "font_class": "calendar-filled", + "unicode": "\ue6c0" + }, + { + "font_class": "camera", + "unicode": "\ue65a" + }, + { + "font_class": "camera-filled", + "unicode": "\ue658" + }, + { + "font_class": "cart", + "unicode": "\ue631" + }, + { + "font_class": "cart-filled", + "unicode": "\ue6d0" + }, + { + "font_class": "chat", + "unicode": "\ue65d" + }, + { + "font_class": "chat-filled", + "unicode": "\ue659" + }, + { + "font_class": "chatboxes", + "unicode": "\ue696" + }, + { + "font_class": "chatboxes-filled", + "unicode": "\ue692" + }, + { + "font_class": "chatbubble", + "unicode": "\ue697" + }, + { + "font_class": "chatbubble-filled", + "unicode": "\ue694" + }, + { + "font_class": "checkbox", + "unicode": "\ue62b" + }, + { + "font_class": "checkbox-filled", + "unicode": "\ue62c" + }, + { + "font_class": "checkmarkempty", + "unicode": "\ue65c" + }, + { + "font_class": "circle", + "unicode": "\ue65b" + }, + { + "font_class": "circle-filled", + "unicode": "\ue65e" + }, + { + "font_class": "clear", + "unicode": "\ue66d" + }, + { + "font_class": "close", + "unicode": "\ue673" + }, + { + "font_class": "closeempty", + "unicode": "\ue66c" + }, + { + "font_class": "cloud-download", + "unicode": "\ue647" + }, + { + "font_class": "cloud-download-filled", + "unicode": "\ue646" + }, + { + "font_class": "cloud-upload", + "unicode": "\ue645" + }, + { + "font_class": "cloud-upload-filled", + "unicode": "\ue648" + }, + { + "font_class": "color", + "unicode": "\ue6cf" + }, + { + "font_class": "color-filled", + "unicode": "\ue6c9" + }, + { + "font_class": "compose", + "unicode": "\ue67f" + }, + { + "font_class": "contact", + "unicode": "\ue693" + }, + { + "font_class": "contact-filled", + "unicode": "\ue695" + }, + { + "font_class": "down", + "unicode": "\ue6b8" + }, + { + "font_class": "bottom", + "unicode": "\ue6b8" + }, + { + "font_class": "download", + "unicode": "\ue68d" + }, + { + "font_class": "download-filled", + "unicode": "\ue681" + }, + { + "font_class": "email", + "unicode": "\ue69e" + }, + { + "font_class": "email-filled", + "unicode": "\ue69a" + }, + { + "font_class": "eye", + "unicode": "\ue651" + }, + { + "font_class": "eye-filled", + "unicode": "\ue66a" + }, + { + "font_class": "eye-slash", + "unicode": "\ue6b3" + }, + { + "font_class": "eye-slash-filled", + "unicode": "\ue6b4" + }, + { + "font_class": "fire", + "unicode": "\ue6a1" + }, + { + "font_class": "fire-filled", + "unicode": "\ue6c5" + }, + { + "font_class": "flag", + "unicode": "\ue65f" + }, + { + "font_class": "flag-filled", + "unicode": "\ue660" + }, + { + "font_class": "folder-add", + "unicode": "\ue6a9" + }, + { + "font_class": "folder-add-filled", + "unicode": "\ue6c8" + }, + { + "font_class": "font", + "unicode": "\ue6a3" + }, + { + "font_class": "forward", + "unicode": "\ue6ba" + }, + { + "font_class": "gear", + "unicode": "\ue664" + }, + { + "font_class": "gear-filled", + "unicode": "\ue661" + }, + { + "font_class": "gift", + "unicode": "\ue6a4" + }, + { + "font_class": "gift-filled", + "unicode": "\ue6c4" + }, + { + "font_class": "hand-down", + "unicode": "\ue63d" + }, + { + "font_class": "hand-down-filled", + "unicode": "\ue63c" + }, + { + "font_class": "hand-up", + "unicode": "\ue63f" + }, + { + "font_class": "hand-up-filled", + "unicode": "\ue63e" + }, + { + "font_class": "headphones", + "unicode": "\ue630" + }, + { + "font_class": "heart", + "unicode": "\ue639" + }, + { + "font_class": "heart-filled", + "unicode": "\ue641" + }, + { + "font_class": "help", + "unicode": "\ue679" + }, + { + "font_class": "help-filled", + "unicode": "\ue674" + }, + { + "font_class": "home", + "unicode": "\ue662" + }, + { + "font_class": "home-filled", + "unicode": "\ue663" + }, + { + "font_class": "image", + "unicode": "\ue670" + }, + { + "font_class": "image-filled", + "unicode": "\ue678" + }, + { + "font_class": "images", + "unicode": "\ue650" + }, + { + "font_class": "images-filled", + "unicode": "\ue64b" + }, + { + "font_class": "info", + "unicode": "\ue669" + }, + { + "font_class": "info-filled", + "unicode": "\ue649" + }, + { + "font_class": "left", + "unicode": "\ue6b7" + }, + { + "font_class": "link", + "unicode": "\ue6a5" + }, + { + "font_class": "list", + "unicode": "\ue644" + }, + { + "font_class": "location", + "unicode": "\ue6ae" + }, + { + "font_class": "location-filled", + "unicode": "\ue6af" + }, + { + "font_class": "locked", + "unicode": "\ue66b" + }, + { + "font_class": "locked-filled", + "unicode": "\ue668" + }, + { + "font_class": "loop", + "unicode": "\ue633" + }, + { + "font_class": "mail-open", + "unicode": "\ue643" + }, + { + "font_class": "mail-open-filled", + "unicode": "\ue63a" + }, + { + "font_class": "map", + "unicode": "\ue667" + }, + { + "font_class": "map-filled", + "unicode": "\ue666" + }, + { + "font_class": "map-pin", + "unicode": "\ue6ad" + }, + { + "font_class": "map-pin-ellipse", + "unicode": "\ue6ac" + }, + { + "font_class": "medal", + "unicode": "\ue6a2" + }, + { + "font_class": "medal-filled", + "unicode": "\ue6c3" + }, + { + "font_class": "mic", + "unicode": "\ue671" + }, + { + "font_class": "mic-filled", + "unicode": "\ue677" + }, + { + "font_class": "micoff", + "unicode": "\ue67e" + }, + { + "font_class": "micoff-filled", + "unicode": "\ue6b0" + }, + { + "font_class": "minus", + "unicode": "\ue66f" + }, + { + "font_class": "minus-filled", + "unicode": "\ue67d" + }, + { + "font_class": "more", + "unicode": "\ue64d" + }, + { + "font_class": "more-filled", + "unicode": "\ue64e" + }, + { + "font_class": "navigate", + "unicode": "\ue66e" + }, + { + "font_class": "navigate-filled", + "unicode": "\ue67a" + }, + { + "font_class": "notification", + "unicode": "\ue6a6" + }, + { + "font_class": "notification-filled", + "unicode": "\ue6c1" + }, + { + "font_class": "paperclip", + "unicode": "\ue652" + }, + { + "font_class": "paperplane", + "unicode": "\ue672" + }, + { + "font_class": "paperplane-filled", + "unicode": "\ue675" + }, + { + "font_class": "person", + "unicode": "\ue699" + }, + { + "font_class": "person-filled", + "unicode": "\ue69d" + }, + { + "font_class": "personadd", + "unicode": "\ue69f" + }, + { + "font_class": "personadd-filled", + "unicode": "\ue698" + }, + { + "font_class": "personadd-filled-copy", + "unicode": "\ue6d1" + }, + { + "font_class": "phone", + "unicode": "\ue69c" + }, + { + "font_class": "phone-filled", + "unicode": "\ue69b" + }, + { + "font_class": "plus", + "unicode": "\ue676" + }, + { + "font_class": "plus-filled", + "unicode": "\ue6c7" + }, + { + "font_class": "plusempty", + "unicode": "\ue67b" + }, + { + "font_class": "pulldown", + "unicode": "\ue632" + }, + { + "font_class": "pyq", + "unicode": "\ue682" + }, + { + "font_class": "qq", + "unicode": "\ue680" + }, + { + "font_class": "redo", + "unicode": "\ue64a" + }, + { + "font_class": "redo-filled", + "unicode": "\ue655" + }, + { + "font_class": "refresh", + "unicode": "\ue657" + }, + { + "font_class": "refresh-filled", + "unicode": "\ue656" + }, + { + "font_class": "refreshempty", + "unicode": "\ue6bf" + }, + { + "font_class": "reload", + "unicode": "\ue6b2" + }, + { + "font_class": "right", + "unicode": "\ue6b5" + }, + { + "font_class": "scan", + "unicode": "\ue62a" + }, + { + "font_class": "search", + "unicode": "\ue654" + }, + { + "font_class": "settings", + "unicode": "\ue653" + }, + { + "font_class": "settings-filled", + "unicode": "\ue6ce" + }, + { + "font_class": "shop", + "unicode": "\ue62f" + }, + { + "font_class": "shop-filled", + "unicode": "\ue6cd" + }, + { + "font_class": "smallcircle", + "unicode": "\ue67c" + }, + { + "font_class": "smallcircle-filled", + "unicode": "\ue665" + }, + { + "font_class": "sound", + "unicode": "\ue684" + }, + { + "font_class": "sound-filled", + "unicode": "\ue686" + }, + { + "font_class": "spinner-cycle", + "unicode": "\ue68a" + }, + { + "font_class": "staff", + "unicode": "\ue6a7" + }, + { + "font_class": "staff-filled", + "unicode": "\ue6cb" + }, + { + "font_class": "star", + "unicode": "\ue688" + }, + { + "font_class": "star-filled", + "unicode": "\ue68f" + }, + { + "font_class": "starhalf", + "unicode": "\ue683" + }, + { + "font_class": "trash", + "unicode": "\ue687" + }, + { + "font_class": "trash-filled", + "unicode": "\ue685" + }, + { + "font_class": "tune", + "unicode": "\ue6aa" + }, + { + "font_class": "tune-filled", + "unicode": "\ue6ca" + }, + { + "font_class": "undo", + "unicode": "\ue64f" + }, + { + "font_class": "undo-filled", + "unicode": "\ue64c" + }, + { + "font_class": "up", + "unicode": "\ue6b6" + }, + { + "font_class": "top", + "unicode": "\ue6b6" + }, + { + "font_class": "upload", + "unicode": "\ue690" + }, + { + "font_class": "upload-filled", + "unicode": "\ue68e" + }, + { + "font_class": "videocam", + "unicode": "\ue68c" + }, + { + "font_class": "videocam-filled", + "unicode": "\ue689" + }, + { + "font_class": "vip", + "unicode": "\ue6a8" + }, + { + "font_class": "vip-filled", + "unicode": "\ue6c6" + }, + { + "font_class": "wallet", + "unicode": "\ue6b1" + }, + { + "font_class": "wallet-filled", + "unicode": "\ue6c2" + }, + { + "font_class": "weibo", + "unicode": "\ue68b" + }, + { + "font_class": "weixin", + "unicode": "\ue691" + } +] + +// export const fontData = JSON.parse(fontDataJson) diff --git a/uni_modules/uni-icons/package.json b/uni_modules/uni-icons/package.json new file mode 100644 index 0000000..60e45f0 --- /dev/null +++ b/uni_modules/uni-icons/package.json @@ -0,0 +1,111 @@ +{ + "id": "uni-icons", + "displayName": "uni-icons 图标", + "version": "2.0.12", + "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。", + "keywords": [ + "uni-ui", + "uniui", + "icon", + "图标" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.2.14", + "uni-app": "^4.08", + "uni-app-x": "^4.61" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": { + "extVersion": "", + "minVersion": "29" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "√", + "lark": "-" + }, + "quickapp": { + "huawei": "√", + "union": "√" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": { + "extVersion": "", + "minVersion": "29" + }, + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-icons/readme.md b/uni_modules/uni-icons/readme.md new file mode 100644 index 0000000..86234ba --- /dev/null +++ b/uni_modules/uni-icons/readme.md @@ -0,0 +1,8 @@ +## Icons 图标 +> **组件名:uni-icons** +> 代码块: `uIcons` + +用于展示 icons 图标 。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-load-more/changelog.md b/uni_modules/uni-load-more/changelog.md new file mode 100644 index 0000000..c5750ac --- /dev/null +++ b/uni_modules/uni-load-more/changelog.md @@ -0,0 +1,23 @@ +## 1.3.7(2025-08-20) +- 修复 微信小程序css警告问题 +## 1.3.6(2024-10-15) +- 修复 微信小程序中的getSystemInfo警告 +## 1.3.3(2022-01-20) +- 新增 showText属性 ,是否显示文本 +## 1.3.2(2022-01-19) +- 修复 nvue 平台下不显示文本的bug +## 1.3.1(2022-01-19) +- 修复 微信小程序平台样式选择器报警告的问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more) +## 1.2.1(2021-08-24) +- 新增 支持国际化 +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.8(2021-05-12) +- 新增 组件示例地址 +## 1.1.7(2021-03-30) +- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug +## 1.1.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json new file mode 100644 index 0000000..a4f14a5 --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "Pull up to show more", + "uni-load-more.contentrefresh": "loading...", + "uni-load-more.contentnomore": "No more data" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js b/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json new file mode 100644 index 0000000..f15d510 --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉显示更多", + "uni-load-more.contentrefresh": "正在加载...", + "uni-load-more.contentnomore": "没有更多数据了" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json new file mode 100644 index 0000000..a255c6d --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json @@ -0,0 +1,5 @@ +{ + "uni-load-more.contentdown": "上拉顯示更多", + "uni-load-more.contentrefresh": "正在加載...", + "uni-load-more.contentnomore": "沒有更多數據了" +} diff --git a/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue new file mode 100644 index 0000000..0fa17e8 --- /dev/null +++ b/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue @@ -0,0 +1,404 @@ + + + + + diff --git a/uni_modules/uni-load-more/package.json b/uni_modules/uni-load-more/package.json new file mode 100644 index 0000000..3397e8a --- /dev/null +++ b/uni_modules/uni-load-more/package.json @@ -0,0 +1,105 @@ +{ + "id": "uni-load-more", + "displayName": "uni-load-more 加载更多", + "version": "1.3.7", + "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。", + "keywords": [ + "uni-ui", + "uniui", + "加载更多", + "load-more" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "", + "uni-app": "^4.07", + "uni-app-x": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "-", + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "√", + "lark": "-" + }, + "quickapp": { + "huawei": "√", + "union": "√" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-load-more/readme.md b/uni_modules/uni-load-more/readme.md new file mode 100644 index 0000000..54dc1fa --- /dev/null +++ b/uni_modules/uni-load-more/readme.md @@ -0,0 +1,14 @@ + + +### LoadMore 加载更多 +> **组件名:uni-load-more** +> 代码块: `uLoadMore` + + +用于列表中,做滚动加载使用,展示 loading 的各种状态。 + + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + diff --git a/uni_modules/uni-popup/changelog.md b/uni_modules/uni-popup/changelog.md new file mode 100644 index 0000000..c72474a --- /dev/null +++ b/uni_modules/uni-popup/changelog.md @@ -0,0 +1,102 @@ +## 1.9.11(2025-08-20) +- 修复 uni-popup-dialog组件设置 borderRadius 不生效的 Bug +## 1.9.10(2025-07-18) +- 修复 nvue 下弹窗样式错乱的问题 ,更新依赖 uni-transition 组件 +- 更新 示例取消 borderRadius 属性 ,如需内容圆角,用户应该直接在内容插槽中实现 +## 1.9.9(2025-06-11) +- 修复 uni-popup-dialog 中 setVal 方法报错的问题 +- 修复 uni-popup-dialog 数据双向绑定问题。 +## 1.9.8(2025-04-16) +- 修复 更新组件示例 ,解决更新数据或保存项目导致弹窗消失的问题 +## 1.9.7(2025-04-14) +- 修复 uni-popup-dialog 弹出框在vue3中双向绑定问题 +## 1.9.6(2025-01-08) +- 修复 示例中过期图片地址 +## 1.9.5(2024-10-15) +- 修复 微信小程序中的getSystemInfo警告 +## 1.9.2(2024-09-21) +- 修复 uni-popup在android上的重复点击弹出位置不正确的bug +## 1.9.1(2024-04-02) +- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法) +## 1.9.0(2024-03-28) +- 修复 uni-popup-dialog 双向绑定时初始化逻辑修正 +## 1.8.9(2024-03-20) +- 修复 uni-popup-dialog 数据输入时修正为双向绑定 +## 1.8.8(2024-02-20) +- 修复 uni-popup 在微信小程序下出现文字向上闪动的bug +## 1.8.7(2024-02-02) +- 新增 uni-popup-dialog 新增属性focus:input模式下,是否自动自动聚焦 +## 1.8.6(2024-01-30) +- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数 +## 1.8.5(2024-01-26) +- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示 +## 1.8.4(2023-11-15) +- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close` +## 1.8.3(2023-04-17) +- 修复 uni-popup 重复打开时的 bug +## 1.8.2(2023-02-02) +- uni-popup-dialog 组件新增 inputType 属性 +## 1.8.1(2022-12-01) +- 修复 nvue 下 v-show 报错 +## 1.8.0(2022-11-29) +- 优化 主题样式 +## 1.7.9(2022-04-02) +- 修复 弹出层内部无法滚动的bug +## 1.7.8(2022-03-28) +- 修复 小程序中高度错误的bug +## 1.7.7(2022-03-17) +- 修复 快速调用open出现问题的Bug +## 1.7.6(2022-02-14) +- 修复 safeArea 属性不能设置为false的bug +## 1.7.5(2022-01-19) +- 修复 isMaskClick 失效的bug +## 1.7.4(2022-01-19) +- 新增 cancelText \ confirmText 属性 ,可自定义文本 +- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 +- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 +## 1.7.3(2022-01-13) +- 修复 设置 safeArea 属性不生效的bug +## 1.7.2(2021-11-26) +- 优化 组件示例 +## 1.7.1(2021-11-26) +- 修复 vuedoc 文字错误 +## 1.7.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup) +## 1.6.2(2021-08-24) +- 新增 支持国际化 +## 1.6.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.6.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.5.0(2021-06-23) +- 新增 mask-click 遮罩层点击事件 +## 1.4.5(2021-06-22) +- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.4(2021-06-18) +- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.3(2021-06-08) +- 修复 错误的 watch 字段 +- 修复 safeArea 属性不生效的问题 +- 修复 点击内容,再点击遮罩无法关闭的Bug +## 1.4.2(2021-05-12) +- 新增 组件示例地址 +## 1.4.1(2021-04-29) +- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 +## 1.4.0 (2021-04-29) +- 新增 type 属性的 left\right 值,支持左右弹出 +- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 +- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 +- 新增 safeArea 属性,是否适配底部安全区 +- 修复 App\h5\微信小程序底部安全区占位不对的Bug +- 修复 App 端弹出等待的Bug +- 优化 提升低配设备性能,优化动画卡顿问题 +- 优化 更简单的组件自定义方式 +## 1.2.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.2.8(2021-02-05) +- 调整为uni_modules目录规范 +## 1.2.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 +- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js new file mode 100644 index 0000000..6ef26a2 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue new file mode 100644 index 0000000..ea93ea5 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue @@ -0,0 +1,330 @@ + + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue new file mode 100644 index 0000000..91370a8 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue @@ -0,0 +1,143 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue new file mode 100644 index 0000000..c8945d5 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue @@ -0,0 +1,188 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/uni_modules/uni-popup/components/uni-popup/i18n/en.json new file mode 100644 index 0000000..7f1bd06 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/en.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "cancel", + "uni-popup.ok": "ok", + "uni-popup.placeholder": "pleace enter", + "uni-popup.title": "Hint", + "uni-popup.shareTitle": "Share to" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/uni_modules/uni-popup/components/uni-popup/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json new file mode 100644 index 0000000..5e3003c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "确定", + "uni-popup.placeholder": "请输入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json new file mode 100644 index 0000000..13e39eb --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "確定", + "uni-popup.placeholder": "請輸入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/keypress.js b/uni_modules/uni-popup/components/uni-popup/keypress.js new file mode 100644 index 0000000..62dda46 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup/popup.js b/uni_modules/uni-popup/components/uni-popup/popup.js new file mode 100644 index 0000000..c4e5781 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/popup.js @@ -0,0 +1,26 @@ + +export default { + data() { + return { + + } + }, + created(){ + this.popup = this.getParent() + }, + methods:{ + /** + * 获取父元素实例 + */ + getParent(name = 'uniPopup') { + let parent = this.$parent; + let parentName = parent.$options.name; + while (parentName !== name) { + parent = parent.$parent; + if (!parent) return false + parentName = parent.$options.name; + } + return parent; + }, + } +} diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue new file mode 100644 index 0000000..5eb8d5b --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue @@ -0,0 +1,90 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue new file mode 100644 index 0000000..5af55e0 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue @@ -0,0 +1,518 @@ + + + + diff --git a/uni_modules/uni-popup/package.json b/uni_modules/uni-popup/package.json new file mode 100644 index 0000000..eb2bb05 --- /dev/null +++ b/uni_modules/uni-popup/package.json @@ -0,0 +1,107 @@ +{ + "id": "uni-popup", + "displayName": "uni-popup 弹出层", + "version": "1.9.11", + "description": " Popup 组件,提供常用的弹层", + "keywords": [ + "uni-ui", + "弹出层", + "弹窗", + "popup", + "弹框" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "", + "uni-app": "^4.07", + "uni-app-x": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-transition" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "√", + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√", + "alipay": "√", + "toutiao": "√", + "baidu": "√", + "kuaishou": "-", + "jd": "-", + "harmony": "-", + "qq": "√", + "lark": "-" + }, + "quickapp": { + "huawei": "-", + "union": "-" + } + }, + "uni-app-x": { + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": "√" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-popup/readme.md b/uni_modules/uni-popup/readme.md new file mode 100644 index 0000000..fdad4b3 --- /dev/null +++ b/uni_modules/uni-popup/readme.md @@ -0,0 +1,17 @@ + + +## Popup 弹出层 +> **组件名:uni-popup** +> 代码块: `uPopup` +> 关联组件:`uni-transition` + + +弹出层组件,在应用中弹出一个消息提示窗口、提示框等 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/uni_modules/uni-row/changelog.md b/uni_modules/uni-row/changelog.md new file mode 100644 index 0000000..5b465bc --- /dev/null +++ b/uni_modules/uni-row/changelog.md @@ -0,0 +1,10 @@ +## 1.0.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-row](https://uniapp.dcloud.io/component/uniui/uni-row) +## 0.1.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 0.0.4(2021-05-12) +- 新增 组件示例地址 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 新增uni-row组件 diff --git a/uni_modules/uni-row/components/uni-col/uni-col.vue b/uni_modules/uni-row/components/uni-col/uni-col.vue new file mode 100644 index 0000000..84e2deb --- /dev/null +++ b/uni_modules/uni-row/components/uni-col/uni-col.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/uni_modules/uni-row/components/uni-row/uni-row.vue b/uni_modules/uni-row/components/uni-row/uni-row.vue new file mode 100644 index 0000000..f8e8542 --- /dev/null +++ b/uni_modules/uni-row/components/uni-row/uni-row.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/uni_modules/uni-row/package.json b/uni_modules/uni-row/package.json new file mode 100644 index 0000000..3f52fa6 --- /dev/null +++ b/uni_modules/uni-row/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-row", + "displayName": "uni-row 布局-行", + "version": "1.0.0", + "description": "流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。", + "keywords": [ + "uni-ui", + "uniui", + "栅格", + "布局", + "layout" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-row/readme.md b/uni_modules/uni-row/readme.md new file mode 100644 index 0000000..3c9c8b9 --- /dev/null +++ b/uni_modules/uni-row/readme.md @@ -0,0 +1,10 @@ +## Layout 布局 + +> **组件名 uni-row、uni-col** +> 代码块: `uRow`、`uCol` + + +流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-row) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/changelog.md b/uni_modules/uni-scss/changelog.md new file mode 100644 index 0000000..b863bb0 --- /dev/null +++ b/uni_modules/uni-scss/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2022-01-21) +- 优化 组件示例 +## 1.0.2(2021-11-22) +- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 +## 1.0.1(2021-11-22) +- 修复 vue3中scss语法兼容问题 +## 1.0.0(2021-11-18) +- init diff --git a/uni_modules/uni-scss/index.scss b/uni_modules/uni-scss/index.scss new file mode 100644 index 0000000..1744a5f --- /dev/null +++ b/uni_modules/uni-scss/index.scss @@ -0,0 +1 @@ +@import './styles/index.scss'; diff --git a/uni_modules/uni-scss/package.json b/uni_modules/uni-scss/package.json new file mode 100644 index 0000000..7cc0ccb --- /dev/null +++ b/uni_modules/uni-scss/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-scss", + "displayName": "uni-scss 辅助样式", + "version": "1.0.3", + "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", + "keywords": [ + "uni-scss", + "uni-ui", + "辅助样式" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-scss/readme.md b/uni_modules/uni-scss/readme.md new file mode 100644 index 0000000..b7d1c25 --- /dev/null +++ b/uni_modules/uni-scss/readme.md @@ -0,0 +1,4 @@ +`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/index.scss b/uni_modules/uni-scss/styles/index.scss new file mode 100644 index 0000000..ffac4fe --- /dev/null +++ b/uni_modules/uni-scss/styles/index.scss @@ -0,0 +1,7 @@ +@import './setting/_variables.scss'; +@import './setting/_border.scss'; +@import './setting/_color.scss'; +@import './setting/_space.scss'; +@import './setting/_radius.scss'; +@import './setting/_text.scss'; +@import './setting/_styles.scss'; diff --git a/uni_modules/uni-scss/styles/setting/_border.scss b/uni_modules/uni-scss/styles/setting/_border.scss new file mode 100644 index 0000000..12a11c3 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_border.scss @@ -0,0 +1,3 @@ +.uni-border { + border: 1px $uni-border-1 solid; +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_color.scss b/uni_modules/uni-scss/styles/setting/_color.scss new file mode 100644 index 0000000..1ededd9 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_color.scss @@ -0,0 +1,66 @@ + +// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 +// @mixin get-styles($k,$c) { +// @if $k == size or $k == weight{ +// font-#{$k}:#{$c} +// }@else{ +// #{$k}:#{$c} +// } +// } +$uni-ui-color:( + // 主色 + primary: $uni-primary, + primary-disable: $uni-primary-disable, + primary-light: $uni-primary-light, + // 辅助色 + success: $uni-success, + success-disable: $uni-success-disable, + success-light: $uni-success-light, + warning: $uni-warning, + warning-disable: $uni-warning-disable, + warning-light: $uni-warning-light, + error: $uni-error, + error-disable: $uni-error-disable, + error-light: $uni-error-light, + info: $uni-info, + info-disable: $uni-info-disable, + info-light: $uni-info-light, + // 中性色 + main-color: $uni-main-color, + base-color: $uni-base-color, + secondary-color: $uni-secondary-color, + extra-color: $uni-extra-color, + // 背景色 + bg-color: $uni-bg-color, + // 边框颜色 + border-1: $uni-border-1, + border-2: $uni-border-2, + border-3: $uni-border-3, + border-4: $uni-border-4, + // 黑色 + black:$uni-black, + // 白色 + white:$uni-white, + // 透明 + transparent:$uni-transparent +) !default; +@each $key, $child in $uni-ui-color { + .uni-#{"" + $key} { + color: $child; + } + .uni-#{"" + $key}-bg { + background-color: $child; + } +} +.uni-shadow-sm { + box-shadow: $uni-shadow-sm; +} +.uni-shadow-base { + box-shadow: $uni-shadow-base; +} +.uni-shadow-lg { + box-shadow: $uni-shadow-lg; +} +.uni-mask { + background-color:$uni-mask; +} diff --git a/uni_modules/uni-scss/styles/setting/_radius.scss b/uni_modules/uni-scss/styles/setting/_radius.scss new file mode 100644 index 0000000..9a0428b --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_radius.scss @@ -0,0 +1,55 @@ +@mixin radius($r,$d:null ,$important: false){ + $radius-value:map-get($uni-radius, $r) if($important, !important, null); + // Key exists within the $uni-radius variable + @if (map-has-key($uni-radius, $r) and $d){ + @if $d == t { + border-top-left-radius:$radius-value; + border-top-right-radius:$radius-value; + }@else if $d == r { + border-top-right-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == b { + border-bottom-left-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == l { + border-top-left-radius:$radius-value; + border-bottom-left-radius:$radius-value; + }@else if $d == tl { + border-top-left-radius:$radius-value; + }@else if $d == tr { + border-top-right-radius:$radius-value; + }@else if $d == br { + border-bottom-right-radius:$radius-value; + }@else if $d == bl { + border-bottom-left-radius:$radius-value; + } + }@else{ + border-radius:$radius-value; + } +} + +@each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $key} { + @include radius($key) + } + }@else{ + .uni-radius { + @include radius($key) + } + } +} + +@each $direction in t, r, b, l,tl, tr, br, bl { + @each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $direction}-#{"" + $key} { + @include radius($key,$direction,false) + } + }@else{ + .uni-radius-#{$direction} { + @include radius($key,$direction,false) + } + } + } +} diff --git a/uni_modules/uni-scss/styles/setting/_space.scss b/uni_modules/uni-scss/styles/setting/_space.scss new file mode 100644 index 0000000..3c89528 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_space.scss @@ -0,0 +1,56 @@ + +@mixin fn($space,$direction,$size,$n) { + @if $n { + #{$space}-#{$direction}: #{$size*$uni-space-root}px + } @else { + #{$space}-#{$direction}: #{-$size*$uni-space-root}px + } +} +@mixin get-styles($direction,$i,$space,$n){ + @if $direction == t { + @include fn($space, top,$i,$n); + } + @if $direction == r { + @include fn($space, right,$i,$n); + } + @if $direction == b { + @include fn($space, bottom,$i,$n); + } + @if $direction == l { + @include fn($space, left,$i,$n); + } + @if $direction == x { + @include fn($space, left,$i,$n); + @include fn($space, right,$i,$n); + } + @if $direction == y { + @include fn($space, top,$i,$n); + @include fn($space, bottom,$i,$n); + } + @if $direction == a { + @if $n { + #{$space}:#{$i*$uni-space-root}px; + } @else { + #{$space}:#{-$i*$uni-space-root}px; + } + } +} + +@each $orientation in m,p { + $space: margin; + @if $orientation == m { + $space: margin; + } @else { + $space: padding; + } + @for $i from 0 through 16 { + @each $direction in t, r, b, l, x, y, a { + .uni-#{$orientation}#{$direction}-#{$i} { + @include get-styles($direction,$i,$space,true); + } + .uni-#{$orientation}#{$direction}-n#{$i} { + @include get-styles($direction,$i,$space,false); + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_styles.scss b/uni_modules/uni-scss/styles/setting/_styles.scss new file mode 100644 index 0000000..689afec --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_styles.scss @@ -0,0 +1,167 @@ +/* #ifndef APP-NVUE */ + +$-color-white:#fff; +$-color-black:#000; +@mixin base-style($color) { + color: #fff; + background-color: $color; + border-color: mix($-color-black, $color, 8%); + &:not([hover-class]):active { + background: mix($-color-black, $color, 10%); + border-color: mix($-color-black, $color, 20%); + color: $-color-white; + outline: none; + } +} +@mixin is-color($color) { + @include base-style($color); + &[loading] { + @include base-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &[loading], + &:not([hover-class]):active { + color: $-color-white; + border-color: mix(darken($color,10%), $-color-white); + background-color: mix($color, $-color-white); + } + } + +} +@mixin base-plain-style($color) { + color:$color; + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 70%); + &:not([hover-class]):active { + background: mix($-color-white, $color, 80%); + color: $color; + outline: none; + border-color: mix($-color-white, $color, 50%); + } +} +@mixin is-plain($color){ + &[plain] { + @include base-plain-style($color); + &[loading] { + @include base-plain-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &:active { + color: mix($-color-white, $color, 40%); + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 80%); + } + } + } +} + + +.uni-btn { + margin: 5px; + color: #393939; + border:1px solid #ccc; + font-size: 16px; + font-weight: 200; + background-color: #F9F9F9; + // TODO 暂时处理边框隐藏一边的问题 + overflow: visible; + &::after{ + border: none; + } + + &:not([type]),&[type=default] { + color: #999; + &[loading] { + background: none; + &::before { + margin-right:5px; + } + } + + + + &[disabled]{ + color: mix($-color-white, #999, 60%); + &, + &[loading], + &:active { + color: mix($-color-white, #999, 60%); + background-color: mix($-color-white,$-color-black , 98%); + border-color: mix($-color-white, #999, 85%); + } + } + + &[plain] { + color: #999; + background: none; + border-color: $uni-border-1; + &:not([hover-class]):active { + background: none; + color: mix($-color-white, $-color-black, 80%); + border-color: mix($-color-white, $-color-black, 90%); + outline: none; + } + &[disabled]{ + &, + &[loading], + &:active { + background: none; + color: mix($-color-white, #999, 60%); + border-color: mix($-color-white, #999, 85%); + } + } + } + } + + &:not([hover-class]):active { + color: mix($-color-white, $-color-black, 50%); + } + + &[size=mini] { + font-size: 16px; + font-weight: 200; + border-radius: 8px; + } + + + + &.uni-btn-small { + font-size: 14px; + } + &.uni-btn-mini { + font-size: 12px; + } + + &.uni-btn-radius { + border-radius: 999px; + } + &[type=primary] { + @include is-color($uni-primary); + @include is-plain($uni-primary) + } + &[type=success] { + @include is-color($uni-success); + @include is-plain($uni-success) + } + &[type=error] { + @include is-color($uni-error); + @include is-plain($uni-error) + } + &[type=warning] { + @include is-color($uni-warning); + @include is-plain($uni-warning) + } + &[type=info] { + @include is-color($uni-info); + @include is-plain($uni-info) + } +} +/* #endif */ diff --git a/uni_modules/uni-scss/styles/setting/_text.scss b/uni_modules/uni-scss/styles/setting/_text.scss new file mode 100644 index 0000000..a34d08f --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_text.scss @@ -0,0 +1,24 @@ +@mixin get-styles($k,$c) { + @if $k == size or $k == weight{ + font-#{$k}:#{$c} + }@else{ + #{$k}:#{$c} + } +} + +@each $key, $child in $uni-headings { + /* #ifndef APP-NVUE */ + .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ + /* #ifdef APP-NVUE */ + .container .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ +} diff --git a/uni_modules/uni-scss/styles/setting/_variables.scss b/uni_modules/uni-scss/styles/setting/_variables.scss new file mode 100644 index 0000000..557d3d7 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_variables.scss @@ -0,0 +1,146 @@ +// @use "sass:math"; +@import '../tools/functions.scss'; +// 间距基础倍数 +$uni-space-root: 2 !default; +// 边框半径默认值 +$uni-radius-root:5px !default; +$uni-radius: () !default; +// 边框半径断点 +$uni-radius: map-deep-merge( + ( + 0: 0, + // TODO 当前版本暂时不支持 sm 属性 + // 'sm': math.div($uni-radius-root, 2), + null: $uni-radius-root, + 'lg': $uni-radius-root * 2, + 'xl': $uni-radius-root * 6, + 'pill': 9999px, + 'circle': 50% + ), + $uni-radius +); +// 字体家族 +$body-font-family: 'Roboto', sans-serif !default; +// 文本 +$heading-font-family: $body-font-family !default; +$uni-headings: () !default; +$letterSpacing: -0.01562em; +$uni-headings: map-deep-merge( + ( + 'h1': ( + size: 32px, + weight: 300, + line-height: 50px, + // letter-spacing:-0.01562em + ), + 'h2': ( + size: 28px, + weight: 300, + line-height: 40px, + // letter-spacing: -0.00833em + ), + 'h3': ( + size: 24px, + weight: 400, + line-height: 32px, + // letter-spacing: normal + ), + 'h4': ( + size: 20px, + weight: 400, + line-height: 30px, + // letter-spacing: 0.00735em + ), + 'h5': ( + size: 16px, + weight: 400, + line-height: 24px, + // letter-spacing: normal + ), + 'h6': ( + size: 14px, + weight: 500, + line-height: 18px, + // letter-spacing: 0.0125em + ), + 'subtitle': ( + size: 12px, + weight: 400, + line-height: 20px, + // letter-spacing: 0.00937em + ), + 'body': ( + font-size: 14px, + font-weight: 400, + line-height: 22px, + // letter-spacing: 0.03125em + ), + 'caption': ( + 'size': 12px, + 'weight': 400, + 'line-height': 20px, + // 'letter-spacing': 0.03333em, + // 'text-transform': false + ) + ), + $uni-headings +); + + + +// 主色 +$uni-primary: #2979ff !default; +$uni-primary-disable:lighten($uni-primary,20%) !default; +$uni-primary-light: lighten($uni-primary,25%) !default; + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37 !default; +$uni-success-disable:lighten($uni-success,20%) !default; +$uni-success-light: lighten($uni-success,25%) !default; + +$uni-warning: #f3a73f !default; +$uni-warning-disable:lighten($uni-warning,20%) !default; +$uni-warning-light: lighten($uni-warning,25%) !default; + +$uni-error: #e43d33 !default; +$uni-error-disable:lighten($uni-error,20%) !default; +$uni-error-light: lighten($uni-error,25%) !default; + +$uni-info: #8f939c !default; +$uni-info-disable:lighten($uni-info,20%) !default; +$uni-info-light: lighten($uni-info,25%) !default; + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a !default; // 主要文字 +$uni-base-color: #6a6a6a !default; // 常规文字 +$uni-secondary-color: #909399 !default; // 次要文字 +$uni-extra-color: #c7c7c7 !default; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0 !default; +$uni-border-2: #EDEDED !default; +$uni-border-3: #DCDCDC !default; +$uni-border-4: #B9B9B9 !default; + +// 常规色 +$uni-black: #000000 !default; +$uni-white: #ffffff !default; +$uni-transparent: rgba($color: #000000, $alpha: 0) !default; + +// 背景色 +$uni-bg-color: #f7f7f7 !default; + +/* 水平间距 */ +$uni-spacing-sm: 8px !default; +$uni-spacing-base: 15px !default; +$uni-spacing-lg: 30px !default; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default; +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default; + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4) !default; diff --git a/uni_modules/uni-scss/styles/tools/functions.scss b/uni_modules/uni-scss/styles/tools/functions.scss new file mode 100644 index 0000000..ac6f63e --- /dev/null +++ b/uni_modules/uni-scss/styles/tools/functions.scss @@ -0,0 +1,19 @@ +// 合并 map +@function map-deep-merge($parent-map, $child-map){ + $result: $parent-map; + @each $key, $child in $child-map { + $parent-has-key: map-has-key($result, $key); + $parent-value: map-get($result, $key); + $parent-type: type-of($parent-value); + $child-type: type-of($child); + $parent-is-map: $parent-type == map; + $child-is-map: $child-type == map; + + @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ + $result: map-merge($result, ( $key: $child )); + }@else { + $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); + } + } + @return $result; +}; diff --git a/uni_modules/uni-scss/theme.scss b/uni_modules/uni-scss/theme.scss new file mode 100644 index 0000000..80ee62f --- /dev/null +++ b/uni_modules/uni-scss/theme.scss @@ -0,0 +1,31 @@ +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; +// 主色 +$uni-primary: #2979ff; +// 辅助色 +$uni-success: #4cd964; +// 警告色 +$uni-warning: #f0ad4e; +// 错误色 +$uni-error: #dd524d; +// 描述色 +$uni-info: #909399; +// 中性色 +$uni-main-color: #303133; +$uni-base-color: #606266; +$uni-secondary-color: #909399; +$uni-extra-color: #C0C4CC; +// 背景色 +$uni-bg-color: #f5f5f5; +// 边框颜色 +$uni-border-1: #DCDFE6; +$uni-border-2: #E4E7ED; +$uni-border-3: #EBEEF5; +$uni-border-4: #F2F6FC; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); diff --git a/uni_modules/uni-scss/variables.scss b/uni_modules/uni-scss/variables.scss new file mode 100644 index 0000000..1c062d4 --- /dev/null +++ b/uni_modules/uni-scss/variables.scss @@ -0,0 +1,62 @@ +@import './styles/setting/_variables.scss'; +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; + +// 主色 +$uni-primary: #2979ff; +$uni-primary-disable:mix(#fff,$uni-primary,50%); +$uni-primary-light: mix(#fff,$uni-primary,80%); + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37; +$uni-success-disable:mix(#fff,$uni-success,50%); +$uni-success-light: mix(#fff,$uni-success,80%); + +$uni-warning: #f3a73f; +$uni-warning-disable:mix(#fff,$uni-warning,50%); +$uni-warning-light: mix(#fff,$uni-warning,80%); + +$uni-error: #e43d33; +$uni-error-disable:mix(#fff,$uni-error,50%); +$uni-error-light: mix(#fff,$uni-error,80%); + +$uni-info: #8f939c; +$uni-info-disable:mix(#fff,$uni-info,50%); +$uni-info-light: mix(#fff,$uni-info,80%); + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a; // 主要文字 +$uni-base-color: #6a6a6a; // 常规文字 +$uni-secondary-color: #909399; // 次要文字 +$uni-extra-color: #c7c7c7; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0; +$uni-border-2: #EDEDED; +$uni-border-3: #DCDCDC; +$uni-border-4: #B9B9B9; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); + +// 背景色 +$uni-bg-color: #f7f7f7; + +/* 水平间距 */ +$uni-spacing-sm: 8px; +$uni-spacing-base: 15px; +$uni-spacing-lg: 30px; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4); diff --git a/uni_modules/uni-section/changelog.md b/uni_modules/uni-section/changelog.md new file mode 100644 index 0000000..738f2b3 --- /dev/null +++ b/uni_modules/uni-section/changelog.md @@ -0,0 +1,2 @@ +## 0.0.1(2022-07-22) +- 初始化 diff --git a/uni_modules/uni-section/components/uni-section/uni-section.vue b/uni_modules/uni-section/components/uni-section/uni-section.vue new file mode 100644 index 0000000..9a52e0b --- /dev/null +++ b/uni_modules/uni-section/components/uni-section/uni-section.vue @@ -0,0 +1,167 @@ + + + + diff --git a/uni_modules/uni-section/package.json b/uni_modules/uni-section/package.json new file mode 100644 index 0000000..0a31fb5 --- /dev/null +++ b/uni_modules/uni-section/package.json @@ -0,0 +1,87 @@ +{ + "id": "uni-section", + "displayName": "uni-section 标题栏", + "version": "0.0.1", + "description": "标题栏组件", + "keywords": [ + "uni-ui", + "uniui", + "标题栏" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-section/readme.md b/uni_modules/uni-section/readme.md new file mode 100644 index 0000000..d47faab --- /dev/null +++ b/uni_modules/uni-section/readme.md @@ -0,0 +1,8 @@ +## Section 标题栏 +> **组件名:uni-section** +> 代码块: `uSection` + +uni-section 组件主要用于文章、列表详情等标题展示 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-section) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 diff --git a/uni_modules/uni-transition/changelog.md b/uni_modules/uni-transition/changelog.md new file mode 100644 index 0000000..01bfb58 --- /dev/null +++ b/uni_modules/uni-transition/changelog.md @@ -0,0 +1,31 @@ +## 1.3.6(2025-07-18) +- 修复 nvue 页面,样式错误问题 +## 1.3.5(2025-06-11) +- 修复 第一次执行不显示动画的问题 +## 1.3.4(2025-04-16) +- 修复 页面数据更新到底动画复原的问题 +- 修复 示例页面打开报错的问题 +## 1.3.3(2024-04-23) +- 修复 当元素会受变量影响自动隐藏的bug +## 1.3.2(2023-05-04) +- 修复 NVUE 平台报错的问题 +## 1.3.1(2021-11-23) +- 修复 init 方法初始化问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) +## 1.2.1(2021-09-27) +- 修复 init 方法不生效的 Bug +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.1(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的 Bug +## 1.1.0(2021-04-22) +- 新增 通过方法自定义动画 +- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 +- 优化 动画触发逻辑,使动画更流畅 +- 优化 支持单独的动画类型 +- 优化 文档示例 +## 1.0.2(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/uni_modules/uni-transition/components/uni-transition/createAnimation.js new file mode 100644 index 0000000..8f89b18 --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/createAnimation.js @@ -0,0 +1,131 @@ +// const defaultOption = { +// duration: 300, +// timingFunction: 'linear', +// delay: 0, +// transformOrigin: '50% 50% 0' +// } +// #ifdef APP-NVUE +const nvueAnimation = uni.requireNativePlugin('animation') +// #endif +class MPAnimation { + constructor(options, _this) { + this.options = options + // 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误 + this.animation = uni.createAnimation({ + ...options + }) + this.currentStepAnimates = {} + this.next = 0 + this.$ = _this + + } + + _nvuePushAnimates(type, args) { + let aniObj = this.currentStepAnimates[this.next] + let styles = {} + if (!aniObj) { + styles = { + styles: {}, + config: {} + } + } else { + styles = aniObj + } + if (animateTypes1.includes(type)) { + if (!styles.styles.transform) { + styles.styles.transform = '' + } + let unit = '' + if(type === 'rotate'){ + unit = 'deg' + } + styles.styles.transform += `${type}(${args+unit}) ` + } else { + styles.styles[type] = `${args}` + } + this.currentStepAnimates[this.next] = styles + } + _animateRun(styles = {}, config = {}) { + let ref = this.$.$refs['ani'].ref + if (!ref) return + return new Promise((resolve, reject) => { + nvueAnimation.transition(ref, { + styles, + ...config + }, res => { + resolve() + }) + }) + } + + _nvueNextAnimate(animates, step = 0, fn) { + let obj = animates[step] + if (obj) { + let { + styles, + config + } = obj + this._animateRun(styles, config).then(() => { + step += 1 + this._nvueNextAnimate(animates, step, fn) + }) + } else { + this.currentStepAnimates = {} + typeof fn === 'function' && fn() + this.isEnd = true + } + } + + step(config = {}) { + // #ifndef APP-NVUE + this.animation.step(config) + // #endif + // #ifdef APP-NVUE + this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) + this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin + this.next++ + // #endif + return this + } + + run(fn) { + // #ifndef APP-NVUE + this.$.animationData = this.animation.export() + this.$.timer = setTimeout(() => { + typeof fn === 'function' && fn() + }, this.$.durationTime) + // #endif + // #ifdef APP-NVUE + this.isEnd = false + let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref + if(!ref) return + this._nvueNextAnimate(this.currentStepAnimates, 0, fn) + this.next = 0 + // #endif + } +} + + +const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', + 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', + 'translateZ' +] +const animateTypes2 = ['opacity', 'backgroundColor'] +const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'] +animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { + MPAnimation.prototype[type] = function(...args) { + // #ifndef APP-NVUE + this.animation[type](...args) + // #endif + // #ifdef APP-NVUE + this._nvuePushAnimates(type, args) + // #endif + return this + } +}) + +export function createAnimation(option, _this) { + if(!_this) return + clearTimeout(_this.timer) + return new MPAnimation(option, _this) +} diff --git a/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue new file mode 100644 index 0000000..7677553 --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/uni_modules/uni-transition/package.json b/uni_modules/uni-transition/package.json new file mode 100644 index 0000000..0542c52 --- /dev/null +++ b/uni_modules/uni-transition/package.json @@ -0,0 +1,112 @@ +{ + "id": "uni-transition", + "displayName": "uni-transition 过渡动画", + "version": "1.3.6", + "description": "元素的简单过渡动画", + "keywords": [ + "uni-ui", + "uniui", + "动画", + "过渡", + "过渡动画" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "", + "uni-app": "^4.12", + "uni-app-x": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [ + "uni-scss" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "x", + "aliyun": "x", + "alipay": "x" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "√", + "chrome": "√" + }, + "app": { + "vue": "√", + "nvue": "√", + "android": "√", + "ios": "√", + "harmony": "√" + }, + "mp": { + "weixin": { + }, + "alipay": { + }, + "toutiao": { + }, + "baidu": { + }, + "kuaishou": { + }, + "jd": { + }, + "harmony": "-", + "qq": "√", + "lark": "-" + }, + "quickapp": { + "huawei": "√", + "union": "√" + } + }, + "uni-app-x": { + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "android": "-", + "ios": "-", + "harmony": "-" + }, + "mp": { + "weixin": "-" + } + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-transition/readme.md b/uni_modules/uni-transition/readme.md new file mode 100644 index 0000000..2f8a77e --- /dev/null +++ b/uni_modules/uni-transition/readme.md @@ -0,0 +1,11 @@ + + +## Transition 过渡动画 +> **组件名:uni-transition** +> 代码块: `uTransition` + + +元素过渡动画 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/utils/actions.js b/utils/actions.js new file mode 100644 index 0000000..e96bbca --- /dev/null +++ b/utils/actions.js @@ -0,0 +1,9 @@ +const actions = [ + { key: 1, 'name': '刷卡开门' }, + { key: 2, 'name': '内镜存入' }, + { key: 3, 'name': '内镜取出' }, +] + +export default { + actions, +} \ No newline at end of file diff --git a/utils/beeper.js b/utils/beeper.js new file mode 100644 index 0000000..699d896 --- /dev/null +++ b/utils/beeper.js @@ -0,0 +1,56 @@ +// 蜂鸣音效管理器 +class Beeper { + + audioContext = null; + // 初始化音频上下文 + initAudioContext() { + if (!this.audioContext) { + this.audioContext = uni.createInnerAudioContext(); + this.audioContext.autoplay = false; + this.audioContext.loop = true; + this.audioContext.src = '/static/beep_01.mp3'; + } + return this.audioContext; + } + + // 播放蜂鸣声 + play() { + if (this.audioContext) { + try { + this.audioContext.pause(); + this.audioContext.play(); + } catch (e) { + // 忽略播放失败的错误 + console.log('播放失败:', e); + } + } else{ + // 创建AudioContext实例 + let audioContext = this.initAudioContext(); + audioContext.play(); + } + } + + // 停止蜂鸣声 + stop() { + if (this.audioContext) { + console.log('停止播放'); + this.audioContext.pause(); + } + } +} + +// 创建全局实例 +const beeper = new Beeper(); + +// 导出函数 +export default { + + play() { + return beeper.play(); + }, + // 停止播放 + stop() { + return beeper.stop(); + }, + +}; \ No newline at end of file diff --git a/utils/cmd.js b/utils/cmd.js new file mode 100644 index 0000000..60b11b7 --- /dev/null +++ b/utils/cmd.js @@ -0,0 +1,167 @@ + +// 接收数据 +// 压差站号:01,温湿度站号:02 +// 压差 01 03 02 12 34 B5 33 +// 温湿度 01 03 04 02 98 00 BC 7B D5 +// IC卡 20 01 00 08 04 00 00 00 0e 26 fe ab 8f 03 +// ID卡 20 01 00 05 49 00 b5 6a b5 d8 03 +// 卡离开 20 01 00 01 02 fd 03 + +// 卡片放入和离开 起始位20, 第二位是地址0人员卡,1-16内镜卡 +// let RS232 = getApp().globalData.RS232 +import store from '@/store/index.js' + +export default { + // 开门关门控制 01 + Door: async (status) => { + let op = status ? '01' : '00' + let cmd = '5AA5EE01' + op + store.state.relay.door = status + let RS232 = getApp().globalData.RS232 + await RS232.sendDataString(cmd); + }, + // 开风机指令 02 + Wind: async (status) => { + let op = status ? '01' : '00' + let cmd = '5AA5EE02' + op + store.state.relay.wind = status + let RS232 = getApp().globalData.RS232 + await RS232.sendDataString(cmd); + }, + // 开灯指令 03 + Light: async (status) => { + let op = status ? '01' : '00' + let cmd = '5AA5EE03' + op + store.state.relay.light = status + let RS232 = getApp().globalData.RS232 + await RS232.sendDataString(cmd); + }, + // 开真空指令 04 + Vacuum: async (status) => { + let op = status ? '01' : '00' + let cmd = '5AA5EE04' + op + store.state.relay.vacuum = status + let RS232 = getApp().globalData.RS232 + await RS232.sendDataString(cmd); + }, + // 开关消毒指令 05 + Disinfect: async (status) => { + let op = status ? '01' : '00' + let cmd = '5AA5EE05' + op + store.state.relay.disinfect = status + let RS232 = getApp().globalData.RS232 + await RS232.sendDataString(cmd); + }, + // 获取温湿度 + getTemp: () => { + let RS485 = getApp().globalData.RS485 + let cmd = '020300000002C438'; + RS485.sendDataString(cmd); + }, + + // 获取压差指令 + getPressure: () => { + let RS485 = getApp().globalData.RS485 + let cmd = '01030001000295CB' + RS485.sendDataString(cmd); + }, + + // 解析门卡数据,返回卡号 + parse232dData: (hexString) => { + // IC卡 20 01 00 08 04 00 00 00 0e 26 fe ab 8f 03 + // ID卡 20 01 00 05 49 00 b5 6a b5 d8 03 + // 卡离开 20 01 00 01 02 fd 03 + // 01 地址, 04 00 卡类型,0e 26 fe ab 卡号,8f 校验 03固定值 + // 人员卡地址号0,卡号4个字节,倒数4个字节,倒数一位03固定值,倒数二位校验 + // 内镜卡地址号1-16,卡号4个字节,倒数4个字节,倒数一位03固定值,倒数二位校验 + // 卡离开8位,卡进入11位和14位 + + // 移除空格和换行符 + const hexStr = hexString.replace(/\s+/g, ''); + + // 验证输入 + if (hexStr.length === 0) { + throw new Error('请输入Modbus十六进制数据'); + } + + if (hexStr.length % 2 !== 0) { + throw new Error('请输入有效的Modbus十六进制数据'); + } + + // 解析后的数据对象 + let data = {}; + // 刷卡数据 起始字节20,第二字节站号,结束字节03 + if (hexStr.substr(0, 2) == '20' && hexStr.substr(hexStr.length - 2, 2) == '03') { + // 卡数据 + let hexNum = hexStr.substr(hexStr.length - 12, 8) + // 第二位是地址 + let addHex = hexStr.substr(2, 2) + // 转换成10进制地址号 + let address = parseInt(addHex, 16) + + // 解析后的数据 { address: 0, number: 12345678, cardType: 'ic', action: 'enter', type: 'person' } + data.address = address + if (hexStr.length == 28) { + // 14字节是IC卡号 + let icNo = parseInt(hexNum, 16) + data.number = icNo + data.cardType = 'ic' + data.action = 'enter' + } + if (hexStr.length == 22) { + // 11字节是ID卡号 + let idNo = parseInt(hexNum, 16) + data.number = idNo + data.cardType = 'id' + data.action = 'enter' + } + if (hexStr.length == 14) { + // 7字节是卡离开 + data.action = 'leave' + } + if (address == 0) { + // 人员卡 + data.type = 'person' + } + if (address >= 1 && address <= 16) { + // 内镜卡 + data.type = 'internal' + } + } + // 关门上报指令 + if (hexStr.toUpperCase() == '5AA50000000000FF') { + // 开门数据 8个字节 + data.action = 'door' + } + return data + }, + parse485Data: (hexString) => { + // 移除空格和换行符 + const hexStr = hexString.replace(/\s+/g, ''); + // 压差站号:01,温湿度站号:02 + let addHex = hexStr.substr(0, 2) + let data = {} + if (hexStr.length == 14 || hexStr.length == 18) { + if (addHex == '01') { + let pressure = parseInt(hexStr.substr(6, 4), 16); + data.pressure = pressure / 10 + } + if (addHex == '02') { + let humi = parseInt(hexStr.substr(6, 4), 16); + let temp = parseInt(hexStr.substr(10, 4), 16); + // 温湿度上报数据异常处理,取正常温湿度范围内数据 + temp = (temp / 10).toFixed(1) + if (temp >= 0 && temp < 100) { + data.temp = temp + } + humi = (humi / 10).toFixed(1) + if (humi >= 0 && humi < 100) { + data.humi = humi + } + } + } + + // console.log('parse485Data:',hexStr, data) + return data + }, +} \ No newline at end of file diff --git a/utils/common.js b/utils/common.js new file mode 100644 index 0000000..0a1577a --- /dev/null +++ b/utils/common.js @@ -0,0 +1,91 @@ + +export const formatDateTime = (date = new Date()) => { + // 确保传入的是 Date 对象 + if (!(date instanceof Date)) { + date = new Date(date); + } + + // 提取日期时间各部分 + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); + const timezoneOffset = -date.getTimezoneOffset(); + const timezoneHours = String(Math.floor(Math.abs(timezoneOffset) / 60)).padStart(2, '0'); + const timezoneMinutes = String(Math.abs(timezoneOffset) % 60).padStart(2, '0'); + const timezoneSign = timezoneOffset >= 0 ? '+' : '-'; + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + +export const getTimeDifference = (time1, time2) => { + // 将时间字符串转换为 Date 对象 + const date1 = new Date(time1); + const date2 = new Date(time2); + + // 计算时间差(毫秒) + const diffMs = Math.abs(date2 - date1); + + // 转换为分钟 + const diffMinutes = Math.floor(diffMs / (1000 * 60)); + + // 计算小时和分钟 + const hours = Math.floor(diffMinutes / 60); + const minutes = diffMinutes % 60; + + // 确定时间差的方向 + const direction = date2 > date1 ? "之后" : "之前"; + + return { + hours, + minutes, + totalMinutes: diffMinutes, + direction + }; +} + +/** + * 比较两个时间字符串(格式:HH:MM) + * @param {string} time1 - 第一个时间字符串,如 "14:00" + * @param {string} time2 - 第二个时间字符串,如 "15:00" + * @returns {number} + * -1: time1 在 time2 之前 + * 0: time1 等于 time2 + * 1: time1 在 time2 之后 + * @throws {Error} 如果时间格式无效 + */ +export function compareTimes(time1, time2) { + // 验证时间格式 + const timeRegex = /^([01]?[0-9]|2[0-3]):([0-5][0-9])$/; + + if (!timeRegex.test(time1) || !timeRegex.test(time2)) { + throw new Error('时间格式无效,请使用 HH:MM 格式(24小时制)'); + } + + // 将时间字符串转换为分钟数进行比较 + const timeToMinutes = (time) => { + const [hours, minutes] = time.split(':').map(Number); + return hours * 60 + minutes; + }; + + const minutes1 = timeToMinutes(time1); + const minutes2 = timeToMinutes(time2); + + if (minutes1 < minutes2) return 1; + if (minutes1 > minutes2) return -1; + return 0; +} + + +// 数字转16进制字符串 +export const numberToHex = (number) => { + return (number & 0xFF).toString(16).padStart(2, '0') +} + +// 延迟执行 +export const delay = (ms) =>{ + return new Promise(resolve => setTimeout(resolve, ms)); +} \ No newline at end of file diff --git a/utils/request/core/request.js b/utils/request/core/request.js new file mode 100644 index 0000000..ed81b7f --- /dev/null +++ b/utils/request/core/request.js @@ -0,0 +1,143 @@ +import { + mergeConfig, + dispatchRequest, + jsonpRequest +} from "./utils" + +export default class request { + + constructor(options) { + // 请求公共地址 + this.baseUrl = options.baseUrl || ""; + // 公共文件上传请求地址 + this.fileUrl = options.fileUrl || ""; + // 超时时间 + this.timeout = options.timeout || 6000; + // 服务器上传图片默认url + this.defaultUploadUrl = options.defaultUploadUrl || ""; + // 默认请求头 + this.header = options.header || {}; + // 默认配置 + this.config = options.config || { + isPrompt: true, + load: true, + isFactory: true, + resend: 0 + }; + } + + // post请求 + post(url = '', data = {}, options = {}) { + return this.request({ + method: "POST", + data: data, + url: url, + ...options + }); + } + + // get请求 + get(url = '', data = {}, options = {}) { + return this.request({ + method: "GET", + data: data, + url: url, + ...options + }); + } + + // put请求 + put(url = '', data = {}, options = {}) { + return this.request({ + method: "PUT", + data: data, + url: url, + ...options + }); + } + + // delete请求 + delete(url = '', data = {}, options = {}) { + return this.request({ + method: "DELETE", + data: data, + url: url, + ...options + }); + } + + // jsonp请求(只限于H5使用) + jsonp(url = '', data = {}, options = {}) { + return this.request({ + method: "JSONP", + data: data, + url: url, + ...options + }); + } + + // 接口请求方法 + async request(data) { + // 请求数据 + let requestInfo, + // 是否运行过请求开始钩子 + runRequestStart = false; + try { + if (!data.url) { + throw { + errMsg: "【request】缺失数据url", + statusCode: 0 + } + } + // 数据合并 + requestInfo = mergeConfig(this, data); + // 代表之前运行到这里 + runRequestStart = true; + // 请求前回调 + if (this.requestStart) { + let requestStart = this.requestStart(requestInfo); + if (typeof requestStart == "object") { + let changekeys = ["data", "header", "isPrompt", "load", "isFactory"]; + changekeys.forEach(key => { + requestInfo[key] = requestStart[key]; + }); + } else { + throw { + errMsg: "【request】请求开始拦截器未通过", + statusCode: 0, + data: requestInfo.data, + method: requestInfo.method, + header: requestInfo.header, + url: requestInfo.url, + } + } + } + let requestResult = {}; + if (requestInfo.method == "JSONP") { + requestResult = await jsonpRequest(requestInfo); + } else { + requestResult = await dispatchRequest(requestInfo); + } + // 是否用外部的数据处理方法 + if (requestInfo.isFactory && this.dataFactory) { + // 数据处理 + let result = await this.dataFactory({ + ...requestInfo, + response: requestResult + }); + return Promise.resolve(result); + } else { + return Promise.resolve(requestResult); + } + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } finally { + // 如果请求开始未运行到,请求结束也不运行 + if (runRequestStart) { + this.requestEnd && this.requestEnd(requestInfo); + } + } + } + +} diff --git a/utils/request/core/utils.js b/utils/request/core/utils.js new file mode 100644 index 0000000..ee412c5 --- /dev/null +++ b/utils/request/core/utils.js @@ -0,0 +1,102 @@ +// 获取合并的数据 +export const mergeConfig = (_this, options) => { + //判断url是不是链接 + let urlType = /^(http|https):\/\//.test(options.url); + let config = Object.assign({ + timeout: _this.timeout + }, _this.config, options); + if (options.method == "FILE") { + config.url = urlType ? options.url : _this.fileUrl + options.url; + } else { + config.url = urlType ? options.url : _this.baseUrl + options.url; + } + //请求头 + if (options.header) { + config.header = Object.assign({}, _this.header, options.header); + } else { + config.header = Object.assign({}, _this.header); + } + return config; +} + +// 请求 +export const dispatchRequest = (requestInfo) => { + return new Promise((resolve, reject) => { + let requestAbort = true; + let requestData = { + url: requestInfo.url, + header: requestInfo.header, //加入请求头 + success: (res) => { + requestAbort = false; + resolve(res); + }, + fail: (err) => { + requestAbort = false; + if (err.errMsg == "request:fail abort") { + reject({ + errMsg: "请求超时,请重新尝试", + statusCode: 0, + }); + } else { + reject(err); + } + } + }; + //请求类型 + if (requestInfo.method) { + requestData.method = requestInfo.method; + } + if (requestInfo.data) { + requestData.data = requestInfo.data; + } + // #ifdef MP-WEIXIN || MP-ALIPAY + if (requestInfo.timeout) { + requestData.timeout = requestInfo.timeout; + } + // #endif + if (requestInfo.dataType) { + requestData.dataType = requestInfo.dataType; + } + // #ifndef APP-PLUS || MP-ALIPAY + if (requestInfo.responseType) { + requestData.responseType = requestInfo.responseType; + } + // #endif + // #ifdef H5 + if (requestInfo.withCredentials) { + requestData.withCredentials = requestInfo.withCredentials; + } + // #endif + let requestTask = uni.request(requestData); + setTimeout(() => { + if (requestAbort) { + requestTask.abort(); + } + }, requestInfo.timeout) + }) +} +// jsonp请求 +export const jsonpRequest = (requestInfo) => { + return new Promise((resolve, reject) => { + let dataStr = ''; + Object.keys(requestInfo.data).forEach(key => { + dataStr += key + '=' + requestInfo.data[key] + '&'; + }); + //匹配最后一个&并去除 + if (dataStr !== '') { + dataStr = dataStr.substr(0, dataStr.lastIndexOf('&')); + } + requestInfo.url = requestInfo.url + '?' + dataStr; + let callbackName = "callback" + Math.ceil(Math.random() * 1000000); + // #ifdef H5 + window[callbackName] = (data) => { + resolve(data); + } + let script = document.createElement("script"); + script.src = requestInfo.url + "&callback=" + callbackName; + document.head.appendChild(script); + // 及时删除,防止加载过多的JS + document.head.removeChild(script); + // #endif + }); +} diff --git a/utils/request/index.js b/utils/request/index.js new file mode 100644 index 0000000..6d50778 --- /dev/null +++ b/utils/request/index.js @@ -0,0 +1,182 @@ +/** + * request插件地址:https://ext.dcloud.net.cn/plugin?id=822 + */ +import store from '@/store' +import request from './request' + +// 后端api地址 +// const apiUrl = 'http://' + store.getters.apiUrl +const apiUrl = 'http://ectms.dev.opmonitor.com' + +// 可以new多个request来支持多个域名请求 +const $http = new request({ + // 接口请求地址 + baseUrl: apiUrl, + // 服务器本地上传文件地址 + fileUrl: apiUrl, + // 服务器上传图片默认url + defaultUploadUrl: 'upload/image', + // 设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致) + header: { + 'content-type': 'application/json;charset=utf-8' + }, + // 请求超时时间, 单位ms(默认15000) + timeout: 15000, + // 默认配置(可不写) + config: { + // 是否自动提示错误 + isPrompt: true, + // 是否显示加载动画 + load: true, + // 是否使用数据工厂 + isFactory: true + } +}) + +// 当前接口请求数 +let requestNum = 0 +// 请求开始拦截器 +$http.requestStart = options => { + if (options.load) { + if (requestNum <= 0) { + // 打开加载动画 + uni.showLoading({ + title: '加载中', + mask: true + }) + } + requestNum += 1 + } + // 图片上传大小限制 + if (options.method == "FILE" && options.maxSize) { + // 文件最大字节: options.maxSize 可以在调用方法的时候加入参数 + const maxSize = options.maxSize + for (let item of options.files) { + if (item.size > maxSize) { + setTimeout(() => { + uni.showToast({ + title: "图片过大,请重新上传", + icon: "none" + }) + }, 10) + return false + } + } + } + // 请求前加入当前终端 + // options.header['platform'] = store.getters.platform + // 请求前加入Token + // options.header['Access-Token'] = store.getters.token + // return false 表示请求拦截,不会继续请求 + return options +} + +// 请求结束 +$http.requestEnd = options => { + // 判断当前接口是否需要加载动画 + if (options.load) { + requestNum = requestNum - 1 + if (requestNum <= 0) { + uni.hideLoading() + } + } +} + +// 当前是否显示modal +let loginModal = false + +// 所有接口数据处理(可在接口里设置不调用此方法) +// 此方法需要开发者根据各自的接口返回类型修改,以下只是模板 +$http.dataFactory = async res => { + console.log("接口请求数据", { + url: res.url, + resolve: res.response, + header: res.header, + data: res.data, + method: res.method, + }) + + if (!res.response.statusCode || res.response.statusCode != 200) { + // 返回错误的结果(catch接受数据) + return Promise.reject({ + statusCode: res.response.statusCode, + errMsg: 'http状态码错误' + }) + } + + let httpData = res.response.data + return Promise.resolve(httpData) + // if (typeof httpData == "string") { + // try { + // httpData = JSON.parse(httpData) + // } catch (error) { + // // httpData = false + // } + // } + // if (httpData === false || typeof httpData !== 'object') { + // // 返回错误的结果(catch接受数据) + // return Promise.reject({ + // statusCode: res.response.statusCode, + // errMsg: "请检查api地址能否访问正常" + // }) + // } + + /*********以下只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/ + + // 判断数据是否请求成功 + // result.status [ 200正常 500有错误 401未登录 403没有权限访问 ] + // if (httpData.status == 200) { + // // 返回正确的结果(then接受数据) + // return Promise.resolve(httpData) + // } + + // 其他错误提示 + if (httpData.status == 500) { + if (res.isPrompt) { + setTimeout(() => { + uni.showToast({ + title: httpData.message, + icon: "none", + duration: 2500 + }) + }, 10) + } + // 返回错误的结果(catch接受数据) + return Promise.reject({ + statusCode: 0, + errMsg: httpData.message, + result: httpData + }) + } + + /*********以上只是模板(及共参考),需要开发者根据各自的接口返回类型修改*********/ +} + +// 错误回调 +$http.requestError = e => { + if (e.statusCode === 0) { + throw e + } else { + setTimeout(() => showRequestError(e), 10) + } +} + +// 显示请求错误信息 +const showRequestError = (e) => { + let errMsg = `网络请求出错:${e.errMsg}` + // #ifdef MP-WEIXIN + if (e.errMsg === 'request:fail url not in domain list') { + errMsg = '当前API域名未添加到微信小程序授权名单 ' + e.errMsg + } + // #endif + if (e.errMsg === 'request:fail') { + errMsg = '网络请求错误:请检查api地址能否访问正常' + } + uni.showToast({ + title: errMsg, + icon: "none", + duration: 3500 + }) +} + +export default $http \ No newline at end of file diff --git a/utils/request/request.js b/utils/request/request.js new file mode 100644 index 0000000..16d79d4 --- /dev/null +++ b/utils/request/request.js @@ -0,0 +1,7 @@ +/***************纯粹的数据请求(如果使用这种可以删除掉fileUpload.js)******************/ +// import request from "./core/request.js"; +// export default request; + +/********数据请求同时继承了文件上传(包括七牛云上传)************/ +import upload from "./upload/upload" +export default upload diff --git a/utils/request/request.md b/utils/request/request.md new file mode 100644 index 0000000..14cd8e1 --- /dev/null +++ b/utils/request/request.md @@ -0,0 +1,471 @@ +# request请求、配置简单、批量上传图片、视频、超强适应性(支持多域名请求) +1. 配置简单、源码清晰注释多、适用于一项目多域名请求、第三方请求、七牛云图片上传、本地服务器图片上传等等 +2. 支持请求`get`、`post`、`put`、`delete` +3. 自动显示请求加载动画(可单个接口关闭) +4. 全局`api`数据处理函数,只回调请求正确的数据(可单个接口关闭) +5. 未登录或登录失效自动拦截并调用登录方法(可单个接口关闭) +6. 全局自动提示接口抛出的错误信息(可单个接口关闭) +7. 支持 Promise +8. 支持拦截器 +9. 支持七牛云文件(图片、视频)批量上传 +10. 支持本地服务器文件(图片、视频)批量上传 +11. 支持上传文件拦截过滤 +12. 支持上传文件进度监听 +13. 支持上传文件单张成功回调 + +| `QQ交流群(607391225)` | `微信交流群(加我好友备注"进群")` | +| ----------------------------|--------------------------- | +|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)| +| QQ群号:607391225 |微信号:zhou0612wei| + +### [点击跳转-插件示例](https://ext.dcloud.net.cn/plugin?id=2009) +### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009) + +### 常见问题 +1.接口请求成功了,没有返回数据或者数据是走的catch回调 + +答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改` + +2.官方的方法有数据,本插件方法请求报错跨域问题 + +答:`requestConfig.js` 请求配置文件里面,`header`请求头设置的`content-type`请求类型需求和后台保持一致 + +3.登录后用户`token`怎么设置? + +答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置 + +4.怎么判断上传的文件(图片)太大?怎么过滤掉太大的文件(图片)? + +答:`requestConfig.js` 请求配置文件里面,`$http.requestStart`请求开始拦截器里面设置 + +5.接口请求成功了,一直提示“网络错误,请检查一下网络”? + +答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改` + +### 本次更新注意事项 +1. 所有的headers都改成了header(和官方统一) +2. 七牛云的获取token等信息提取到了`requestConfig.js`文件,参考如下 + +``` +// 添加获取七牛云token的方法 +$http.getQnToken = function(callback){ + //该地址需要开发者自行配置(每个后台的接口风格都不一样) + $http.get("api/kemean/aid/qn_upload").then(data => { + /* + *接口返回参数: + *visitPrefix:访问文件的域名 + *token:七牛云上传token + *folderPath:上传的文件夹 + *region: 地区 默认为:SCN + */ + callback({ + visitPrefix: data.visitPrefix, + token: data.token, + folderPath: data.folderPath, + region: "SCN" + }); + }); +} +``` + +### 文件说明 +1. `request => core` 请求方法的目录 +2. `request => core => request.js` 请求方法的class文件 +3. `request => core => utils.js` 请求方法的源码文件 +4. `request => upload` 上传方法的目录 +5. `request => upload => upload.js` 上传方法的class文件 +6. `request => upload => utils.js` 上传方法源码文件 +7. `request => upload => qiniuUploader.js` 七牛云官方上传文件 +8. `request => index.js` 输出方法的文件 +9. `requestConfig.js` 请求配置文件(具体看代码) + +### 在main.js引入并挂在Vue上 +``` +import $http from '@/zhouWei-request/requestConfig'; +Vue.prototype.$http = $http; +``` + +### `requestConfig.js`配置说明(requestConfig.js有配置示例) +``` +import request from "@/plugins/request"; +//可以new多个request来支持多个域名请求 +let $http = new request({ + //接口请求地址 + baseUrl: "https://twin-ui.com/", //示例域名,请自行设计 + //服务器本地上传文件地址 + fileUrl: "https://twin-ui.com/", //示例域名,请自行设计 + // 服务器上传图片默认url + defaultUploadUrl: "api/common/v1/upload_image", + //设置请求头(如果使用报错跨域问题,可能是content-type请求类型和后台那边设置的不一致) + header: { + 'Content-Type': 'application/json;charset=UTF-8' + }, + // 请求超时时间(默认6000) + timeout: 6000, + // 默认配置(可不写) + config: { + // 是否自动提示错误 + isPrompt: true, + // 是否显示加载动画 + load: true, + // 是否使用数据工厂 + isFactory: true, + // ... 可写更多配置 + } +}); + +// 添加获取七牛云token的方法 +$http.getQnToken = function(callback){ + //该地址需要开发者自行配置(每个后台的接口风格都不一样) + $http.get("api/common/v1/qn_upload").then(data => { + /* + *接口返回参数: + *visitPrefix:访问文件的域名 + *token:七牛云上传token + *folderPath:上传的文件夹 + *region: 地区 默认为:SCN + */ + callback({ + visitPrefix: data.visitPrefix, + token: data.token, + folderPath: data.folderPath + }); + }); +} +//当前接口请求数 +let requestNum = 0; +//请求开始拦截器 +$http.requestStart = function(options) { + if (options.load) { + if (requestNum <= 0) { + //打开加载动画 + uni.showLoading({ + title: '加载中', + mask: true + }); + } + requestNum += 1; + } + // 图片上传大小限制 + if (options.method == "FILE" && options.maxSize) { + // 文件最大字节: options.maxSize 可以在调用方法的时候加入参数 + let maxSize = options.maxSize; + for (let item of options.files) { + if (item.size > maxSize) { + setTimeout(() => { + uni.showToast({ + title: "图片过大,请重新上传", + icon: "none" + }); + }, 500); + return false; + } + } + } + //请求前加入token + options.header['token'] = "你的项目登录token"; + return options; // return false 表示请求拦截,不会继续请求 +} +//请求结束 +$http.requestEnd = function(options) { + //判断当前接口是否需要加载动画 + if (options.load) { + requestNum = requestNum - 1; + if (requestNum <= 0) { + uni.hideLoading(); + } + } +} +//所有接口数据处理(可在接口里设置不调用此方法) +//此方法需要开发者根据各自的接口返回类型修改,以下只是模板 +$http.dataFactory = async function(res) { + console.log("接口请求数据", { + url: res.url, + resolve: res.response, + header: res.header, + data: res.data, + method: res.method, + }); + if (res.response.statusCode && res.response.statusCode == 200) { + let httpData = res.response.data; + if (typeof (httpData) == "string") { + httpData = JSON.parse(httpData); + } + //判断数据是否请求成功 + if (httpData.success || httpData.code == 200) { + // ---------重点----------返回正确的结果(then接受数据)------------重点------------ + return Promise.resolve(httpData.data); + } else { + //其他错误提示 + if (res.isPrompt) { // 是否提示 + uni.showToast({ + title: httpData.info || httpData.msg, + icon: "none", + duration: 3000 + }); + } + // --------重点---------返回错误的结果(catch接受数据)------------重点------------ + return Promise.reject({ + statusCode: 0, + errMsg: "【request】" + (httpData.info || httpData.msg) + }); + } + } else { + // 返回错误的结果(catch接受数据) + return Promise.reject({ + statusCode: res.response.statusCode, + errMsg: "【request】数据工厂验证不通过" + }); + } +}; +// 错误回调 +$http.requestError = function (e) { + if (e.statusCode === 0) { + throw e; + } else { + uni.showToast({ + title: "网络错误,请检查一下网络", + icon: "none" + }); + } +} +``` + +### 通用请求方法 +``` +this.$http.request({ + url: 'aid/region', + method: "GET", // POST、GET、PUT、DELETE、JSONP,具体说明查看官方文档 + data: {pid:0}, + timeout: 30000, // 默认 30000 说明:超时时间,单位 ms,具体说明查看官方文档 + dataType: "json", // 默认 json 说明:如果设为 json,会尝试对返回的数据做一次 JSON.parse,具体说明查看官方文档 + responseType: "text", // 默认 text 说明:设置响应的数据类型。合法值:text、arraybuffer,具体说明查看官方文档 + withCredentials: false, // 默认 false 说明:跨域请求时是否携带凭证(cookies),具体说明查看官方文档 + isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示) + load: true,//(默认 true 说明:本接口是否提示加载动画) + header: { //默认 无 说明:请求头 + 'Content-Type': 'application/json' + }, + isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用) +}).then(function (response) { + //这里只会在接口是成功状态返回 +}).catch(function (error) { + //这里只会在接口是失败状态返回,不需要去处理错误提示 + console.log(error); +}); +``` + +### get请求 正常写法 +``` +this.$http.get('aid/region',{pid:0}). +then(function (response) { + //这里只会在接口是成功状态返回 +}).catch(function (error) { + //这里只会在接口是失败状态返回,不需要去处理错误提示 + console.log(error); +}); +``` + +### post请求 async写法 +``` +async request(){ + let data = await this.$http.post('aid/region',{pid:0}); + console.log(data); +} +``` + +### 其他功能配置项 +``` +let data = await this.$http.post( + 'http://www.aaa.com/aid/region', //可以直接放链接(将不启用全局定义域名) + { + pid:0 + }, + { + isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示) + load: true,//(默认 true 说明:本接口是否提示加载动画) + header: { //默认 无 说明:请求头 + 'Content-Type': 'application/json' + }, + isFactory: true //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数将失去作用) + } +); +``` + +### `requestConfig.js`可以设置服务器上传图片默认url +``` +//可以new多个request来支持多个域名请求 +let $http = new request({ + //服务器本地上传文件地址 + fileUrl: base.baseUrl, + // 服务器上传图片默认url + defaultUploadUrl: "api/common/v1/upload_image", +}); +``` +``` +// 上传可以不用传递url(使用全局的上传图片url) +this.$http.urlImgUpload({ + name:"后台接受文件key名称", //默认 file + count:"最大选择数",//默认 9 + sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed'] + sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera'] + data:"而外参数" //可不填, +}); +// 上传可以不用传递url(使用全局的上传图片url) +this.$http.urlVideoUpload({ + sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera'] + compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false + maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60 + camera: '前置还是后置摄像头', //'front'、'back',默认'back' + name:"后台接受文件key名称", //默认 file + data:"而外参数" //可不填, +}); +// 上传可以不用传递url(使用全局的上传图片url) +this.$http.urlFileUpload({ + files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}] + data:"向服务器传递的参数", //可不填 + name:"后台接受文件key名称", //默认 file +}); +``` + +### 本地服务器图片上传(支持多张上传) +``` +this.$http.urlImgUpload('flie/upload',{ + name:"后台接受文件key名称", //默认 file + count:"最大选择数",//默认 9 + sizeType:"选择压缩图原图,默认两个都选",//默认 ['original', 'compressed'] + sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera'] + data:"而外参数" //可不填, + isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示) + load: true,//(默认 true 说明:本接口是否提示加载动画) + header: { //默认 无 说明:请求头 + 'Content-Type': 'application/json' + }, + isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onSelectComplete: res => { + console.log("选择完成返回:",res); + }, + onEachUpdate: res => { + console.log("单张上传成功返回:",res); + }, + onProgressUpdate: res => { + console.log("上传进度返回:",res); + } +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` +### 本地服务器视频上传 +``` +this.$http.urlVideoUpload('flie/upload',{ + sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera'] + compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false + maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60 + camera: '前置还是后置摄像头', //'front'、'back',默认'back' + name:"后台接受文件key名称", //默认 file + data:"而外参数" //可不填, + isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示) + load: true,//(默认 true 说明:本接口是否提示加载动画) + header: { //默认 无 说明:请求头 + 'Content-Type': 'application/json' + }, + isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onProgressUpdate: res => { + console.log("上传进度返回:",res); + }, + onSelectComplete: res => { + console.log("选择完成返回:",res); + }, +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` +### 本地服务器文件上传(支持多张上传) +``` +this.$http.urlFileUpload("flie/upload",{ + files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}] + data:"向服务器传递的参数", //可不填 + name:"后台接受文件key名称", //默认 file + isPrompt: true,//(默认 true 说明:本接口抛出的错误是否提示) + load: true,//(默认 true 说明:本接口是否提示加载动画) + header: { //默认 无 说明:请求头 + 'Content-Type': 'application/json' + }, + isFactory: true, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onEachUpdate: res => { + console.log("单张上传成功返回:",res); + }, + onProgressUpdate: res => { + console.log("上传进度返回:",res); + } +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` + +### 七牛云图片上传(支持多张上传) +``` +this.$http.qnImgUpload({ + count:"最大选择数", // 默认 9 + sizeType:"选择压缩图原图,默认两个都选", // 默认 ['original', 'compressed'] + sourceType:"选择相机拍照或相册上传 默认两个都选", // 默认 ['album','camera'] + load: true, //(默认 true 说明:本接口是否提示加载动画) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onSelectComplete: res => { + console.log("选择完成返回:",res); + }, + onEachUpdate: res => { + console.log("单张上传成功返回:",res); + }, + onProgressUpdate: res => { + console.log("上传进度返回:",res); + } +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` +### 七牛云视频上传 +``` +this.$http.qnVideoUpload({ + sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera'] + compressed:"是否压缩所选的视频源文件,默认值为 true,需要压缩",//默认 false + maxDuration: "拍摄视频最长拍摄时间,单位秒。最长支持 60 秒", //默认 60 + camera: '前置还是后置摄像头', //'front'、'back',默认'back' + load: true,//(默认 true 说明:本接口是否提示加载动画) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onSelectComplete: res => { + console.log("选择完成返回:",res); + }, + onProgressUpdate: res => { + console.log("上传进度返回:",res); + } +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` +### 七牛云文件上传(支持多张上传) +``` +this.$http.qnFileUpload( +{ + files:[], // 必填 临时文件路径 格式: [{path: "图片地址"}] + load: true, //(默认 true 说明:本接口是否提示加载动画) + maxSize: 300000, //(默认 无 说明:上传的文件最大字节数限制,默认不限制) + onEachUpdate: res => { + console.log("单张上传成功返回:",res); + }, + onProgressUpdate: res => { + console.log("上传进度返回:",res); + } +}).then(res => { + console.log("全部上传完返回结果:",res); +}); +``` +### jsonp 跨域请求(只支持H5) +``` +let data = await this.$http.jsonp('http://www.aaa.com/aid/region',{pid:0}, { + isFactory: false, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用) +}); +``` diff --git a/utils/request/upload/qiniuUploader.js b/utils/request/upload/qiniuUploader.js new file mode 100644 index 0000000..9542eb6 --- /dev/null +++ b/utils/request/upload/qiniuUploader.js @@ -0,0 +1,163 @@ + + + var config = { + qiniuRegion: '', + qiniuImageURLPrefix: '', + qiniuUploadToken: '', + qiniuUploadTokenURL: '', + qiniuUploadTokenFunction: null, + qiniuShouldUseQiniuFileName: false + } + + // 在整个程序生命周期中,只需要 init 一次即可 + // 如果需要变更参数,再调用 init 即可 + function init(options) { + config = { + qiniuRegion: '', + qiniuImageURLPrefix: '', + qiniuUploadToken: '', + qiniuUploadTokenURL: '', + qiniuUploadTokenFunction: null, + qiniuShouldUseQiniuFileName: false + }; + updateConfigWithOptions(options); + } + + function updateConfigWithOptions(options) { + if (options.region) { + config.qiniuRegion = options.region; + } else { + console.error('qiniu uploader need your bucket region'); + } + if (options.uptoken) { + config.qiniuUploadToken = options.uptoken; + } else if (options.uptokenURL) { + config.qiniuUploadTokenURL = options.uptokenURL; + } else if (options.uptokenFunc) { + config.qiniuUploadTokenFunction = options.uptokenFunc; + } + if (options.domain) { + config.qiniuImageURLPrefix = options.domain; + } + config.qiniuShouldUseQiniuFileName = options.shouldUseQiniuFileName + } + + function upload(filePath, success, fail, options, progress, cancelTask) { + if (null == filePath) { + console.error('qiniu uploader need filePath to upload'); + return; + } + if (options) { + updateConfigWithOptions(options); + } + if (config.qiniuUploadToken) { + doUpload(filePath, success, fail, options, progress, cancelTask); + } else if (config.qiniuUploadTokenURL) { + getQiniuToken(function () { + doUpload(filePath, success, fail, options, progress, cancelTask); + }); + } else if (config.qiniuUploadTokenFunction) { + config.qiniuUploadToken = config.qiniuUploadTokenFunction(); + if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { + console.error('qiniu UploadTokenFunction result is null, please check the return value'); + return + } + doUpload(filePath, success, fail, options, progress, cancelTask); + } else { + console.error('qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]'); + return; + } + } + + function doUpload(filePath, success, fail, options, progress, cancelTask) { + if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { + console.error('qiniu UploadToken is null, please check the init config or networking'); + return + } + var url = uploadURLFromRegionCode(config.qiniuRegion); + var fileName = filePath.split('//')[1]; + if (options && options.key) { + fileName = options.key; + } + var formData = { + 'token': config.qiniuUploadToken + }; + if (!config.qiniuShouldUseQiniuFileName) { + formData['key'] = fileName + } + var uploadTask = wx.uploadFile({ + url: url, + filePath: filePath, + name: 'file', + formData: formData, + success: function (res) { + var dataString = res.data + if (res.data.hasOwnProperty('type') && res.data.type === 'Buffer') { + dataString = String.fromCharCode.apply(null, res.data.data) + } + try { + var dataObject = JSON.parse(dataString); + //do something + var imageUrl = config.qiniuImageURLPrefix + '/' + dataObject.key; + dataObject.imageURL = imageUrl; + if (success) { + success(dataObject); + } + } catch (e) { + console.log('parse JSON failed, origin String is: ' + dataString) + if (fail) { + fail(e); + } + } + }, + fail: function (error) { + console.error(error); + if (fail) { + fail(error); + } + } + }) + + uploadTask.onProgressUpdate((res) => { + progress && progress(res) + }) + + cancelTask && cancelTask(() => { + uploadTask.abort() + }) + } + + function getQiniuToken(callback) { + wx.request({ + url: config.qiniuUploadTokenURL, + success: function (res) { + var token = res.data.uptoken; + if (token && token.length > 0) { + config.qiniuUploadToken = token; + if (callback) { + callback(); + } + } else { + console.error('qiniuUploader cannot get your token, please check the uptokenURL or server') + } + }, + fail: function (error) { + console.error('qiniu UploadToken is null, please check the init config or networking: ' + error); + } + }) + } + + function uploadURLFromRegionCode(code) { + var uploadURL = null; + switch (code) { + case 'ECN': uploadURL = 'https://up.qbox.me'; break; + case 'NCN': uploadURL = 'https://up-z1.qbox.me'; break; + case 'SCN': uploadURL = 'https://up-z2.qbox.me'; break; + case 'NA': uploadURL = 'https://up-na0.qbox.me'; break; + case 'ASG': uploadURL = 'https://up-as0.qbox.me'; break; + default: console.error('please make the region is with one of [ECN, SCN, NCN, NA, ASG]'); + } + return uploadURL; + } + + export { init, upload } diff --git a/utils/request/upload/upload.js b/utils/request/upload/upload.js new file mode 100644 index 0000000..ea3d35d --- /dev/null +++ b/utils/request/upload/upload.js @@ -0,0 +1,203 @@ +import request from "./../core/request.js"; +import { chooseImage, chooseVideo, qiniuUpload, urlUpload } from './utils' +import { + mergeConfig +} from "./../core/utils.js"; +export default class fileUpload extends request { + constructor(props) { + // 调用实现父类的构造函数 + super(props); + } + //七牛云上传图片 + async qnImgUpload(options = {}) { + let files; + try { + files = await chooseImage(options); + // 选择完成回调 + options.onSelectComplete && options.onSelectComplete(files); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } + if (files) { + return this.qnFileUpload({ + ...options, + files: files + }); + } + } + //七牛云上传视频 + async qnVideoUpload(options = {}) { + let files; + try { + files = await chooseVideo(options); + // 选择完成回调 + options.onSelectComplete && options.onSelectComplete(files); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } + if (files) { + return this.qnFileUpload({ + ...options, + files: files + }); + } + } + + //七牛云文件上传(支持多张上传) + async qnFileUpload(options = {}) { + let requestInfo; + try { + // 数据合并 + requestInfo = { + ...this.config, + ...options, + header: {}, + method: "FILE" + }; + //请求前回调 + if (this.requestStart) { + let requestStart = this.requestStart(requestInfo); + if (typeof requestStart == "object") { + let changekeys = ["load", "files"]; + changekeys.forEach(key => { + requestInfo[key] = requestStart[key]; + }); + } else { + throw { + errMsg: "【request】请求开始拦截器未通过", + statusCode: 0, + data: requestInfo.data, + method: requestInfo.method, + header: requestInfo.header, + url: requestInfo.url, + } + } + } + let requestResult = await qiniuUpload(requestInfo, this.getQnToken); + return Promise.resolve(requestResult); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } finally { + this.requestEnd && this.requestEnd(requestInfo); + } + } + //本地服务器图片上传 + async urlImgUpload() { + let options = {}; + if (arguments[0]) { + if (typeof(arguments[0]) == "string") { + options.url = arguments[0]; + } else if (typeof(arguments[0]) == "object") { + options = Object.assign(options, arguments[0]); + } + } + if (arguments[1] && typeof(arguments[1]) == "object") { + options = Object.assign(options, arguments[1]); + } + try { + options.files = await chooseImage(options); + // 选择完成回调 + options.onSelectComplete && options.onSelectComplete(options.files); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } + if (options.files) { + return this.urlFileUpload(options); + } + } + //本地服务器上传视频 + async urlVideoUpload() { + let options = {}; + if (arguments[0]) { + if (typeof(arguments[0]) == "string") { + options.url = arguments[0]; + } else if (typeof(arguments[0]) == "object") { + options = Object.assign(options, arguments[0]); + } + } + if (arguments[1] && typeof(arguments[1]) == "object") { + options = Object.assign(options, arguments[1]); + } + try { + options.files = await chooseVideo(options); + // 选择完成回调 + options.onSelectComplete && options.onSelectComplete(options.files); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } + if (options.files) { + return this.urlFileUpload(options); + } + } + //本地服务器文件上传方法 + async urlFileUpload() { + let requestInfo = { + method: "FILE" + }; + if (arguments[0]) { + if (typeof(arguments[0]) == "string") { + requestInfo.url = arguments[0]; + } else if (typeof(arguments[0]) == "object") { + requestInfo = Object.assign(requestInfo, arguments[0]); + } + } + if (arguments[1] && typeof(arguments[1]) == "object") { + requestInfo = Object.assign(requestInfo, arguments[1]); + } + if (!requestInfo.url && this.defaultUploadUrl) { + requestInfo.url = this.defaultUploadUrl; + } + // 请求数据 + // 是否运行过请求开始钩子 + let runRequestStart = false; + try { + if (!requestInfo.url) { + throw { + errMsg: "【request】文件上传缺失数据url", + statusCode: 0, + data: requestInfo.data, + method: requestInfo.method, + header: requestInfo.header, + url: requestInfo.url, + } + } + // 数据合并 + requestInfo = mergeConfig(this, requestInfo); + // 代表之前运行到这里 + runRequestStart = true; + //请求前回调 + if (this.requestStart) { + let requestStart = this.requestStart(requestInfo); + if (typeof requestStart == "object") { + let changekeys = ["data", "header", "isPrompt", "load", "isFactory", "files"]; + changekeys.forEach(key => { + requestInfo[key] = requestStart[key]; + }); + } else { + throw { + errMsg: "【request】请求开始拦截器未通过", + statusCode: 0, + data: requestInfo.data, + method: requestInfo.method, + header: requestInfo.header, + url: requestInfo.url, + } + } + } + let requestResult = await urlUpload(requestInfo, this.dataFactory); + return Promise.resolve(requestResult); + } catch (err) { + this.requestError && this.requestError(err); + return Promise.reject(err); + } finally { + if (runRequestStart) { + this.requestEnd && this.requestEnd(requestInfo); + } + } + } +} diff --git a/utils/request/upload/utils.js b/utils/request/upload/utils.js new file mode 100644 index 0000000..ce5004e --- /dev/null +++ b/utils/request/upload/utils.js @@ -0,0 +1,288 @@ +import * as qiniuUploader from './qiniuUploader' +//七牛云上传文件命名 +export const randomChar = function(l, url = "") { + const x = "0123456789qwertyuioplkjhgfdsazxcvbnm"; + let tmp = ""; + let time = new Date(); + for (let i = 0; i < l; i++) { + tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length); + } + return ( + "file/" + + url + + time.getTime() + + tmp + ); +} +//图片选择 +export const chooseImage = function(data) { + return new Promise((resolve, reject) => { + uni.chooseImage({ + count: data.count || 9, //默认9 + sizeType: data.sizeType || ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有 + sourceType: data.sourceType || ['album', 'camera'], //从相册选择 + success: function(res) { + resolve(res.tempFiles); + }, + fail: err => { + reject({ + errMsg: err.errMsg, + errCode: err.errCode, + statusCode: 0, + }); + } + }); + }); +} +//视频选择 +export const chooseVideo = function(data) { + return new Promise((resolve, reject) => { + uni.chooseVideo({ + sourceType: data.sourceType || ['album', 'camera'], //从相册选择 + compressed: data.compressed || false, //是否压缩所选的视频源文件,默认值为 true,需要压缩。 + maxDuration: data.maxDuration || 60, //拍摄视频最长拍摄时间,单位秒。最长支持 60 秒。 + camera: data.camera || 'back', //'front'、'back',默认'back' + success: function(res) { + let files = [{ + path: res.tempFilePath + }]; + // #ifdef APP-PLUS || H5 || MP-WEIXIN + files[0].duration = res.duration; + files[0].size = res.size; + files[0].height = res.height; + files[0].width = res.width; + // #endif + // #ifdef H5 + files[0].name = res.name; + // #endif + resolve(files); + }, + fail: err => { + reject({ + errMsg: err.errMsg, + errCode: err.errCode, + statusCode: 0, + }); + } + }); + }); +} +// 七牛云上传 +export const qiniuUpload = function(requestInfo, getQnToken) { + return new Promise((resolve, reject) => { + if (Array.isArray(requestInfo.files)) { + let len = requestInfo.files.length; + let fileList = new Array; + if (getQnToken) { + getQnToken(qnRes => { + /* + *接口返回参数: + *visitPrefix:访问文件的域名 + *token:七牛云上传token + *folderPath:上传的文件夹 + *region: 地区 默认为:SCN + */ + let prefixLen = qnRes.visitPrefix.length; + if(qnRes.visitPrefix.charAt(prefixLen - 1) == '/'){ + qnRes.visitPrefix = qnRes.visitPrefix.substring(0, prefixLen - 1) + } + uploadFile(0); + + function uploadFile(i) { + let item = requestInfo.files[i]; + let updateUrl = randomChar(10, qnRes.folderPath); + let fileData = { + fileIndex: i, + files: requestInfo.files, + ...item + }; + if (item.name) { + fileData.name = item.name; + let nameArr = item.name.split("."); + updateUrl += "." + nameArr[nameArr.length - 1]; + } + // 交给七牛上传 + qiniuUploader.upload(item.path || item, (res) => { + fileData.url = res.imageURL; + requestInfo.onEachUpdate && requestInfo.onEachUpdate({ + url: res.imageURL, + ...fileData + }); + fileList.push(res.imageURL); + if (len - 1 > i) { + uploadFile(i + 1); + } else { + resolve(fileList); + } + }, (error) => { + reject(error); + }, { + region: qnRes.region || 'SCN', //地区 + domain: qnRes.visitPrefix, // bucket 域名,下载资源时用到。 + key: updateUrl, + uptoken: qnRes.token, // 由其他程序生成七牛 uptoken + uptokenURL: 'UpTokenURL.com/uptoken' // 上传地址 + }, (res) => { + console.log(requestInfo); + requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res)); + // console.log('上传进度', res.progress) + // console.log('已经上传的数据长度', res.totalBytesSent) + // console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend) + }); + } + }); + } else { + reject({ + errMsg: "请添加七牛云回调方法:getQnToken", + statusCode: 0 + }); + } + } else { + reject({ + errMsg: "files 必须是数组类型", + statusCode: 0 + }); + }; + }); +} +// 服务器URL上传 +export const urlUpload = function(requestInfo, dataFactory) { + return new Promise((resolve, reject) => { + // 本地文件上传去掉默认Content-Type + if (requestInfo.header['Content-Type']) { + delete requestInfo.header['Content-Type']; + } + // 本地文件上传去掉默认Content-Type + if (requestInfo.header['content-type']) { + delete requestInfo.header['content-type']; + } + if (Array.isArray(requestInfo.files)) { + // // #ifdef APP-PLUS || H5 + // let files = []; + // let fileData = { + // files: requestInfo.files, + // name: requestInfo.name || "file" + // }; + // requestInfo.files.forEach(item => { + // let fileInfo = { + // name: requestInfo.name || "file", + // }; + // if(item.path){ + // fileInfo.uri = item.path; + // } else { + // fileInfo.file = item; + // } + // files.push(fileInfo); + // }); + // let config = { + // url: requestInfo.url, + // files: files, + // header: requestInfo.header, //加入请求头 + // success: (response) => { + // //是否用外部的数据处理方法 + // if (requestInfo.isFactory && dataFactory) { + // //数据处理 + // dataFactory({ + // ...requestInfo, + // response: response, + // }).then(data => { + // requestInfo.onEachUpdate && requestInfo.onEachUpdate({ + // data: data, + // ...fileData + // }); + // resolve(data); + // },err => { + // reject(err); + // }); + // } else { + // requestInfo.onEachUpdate && requestInfo.onEachUpdate({ + // data: response, + // ...fileData + // }); + // resolve(response); + // } + // }, + // fail: (err) => { + // reject(err); + // } + // }; + // if (requestInfo.data) { + // config.formData = requestInfo.data; + // } + // const uploadTask = uni.uploadFile(config); + // uploadTask.onProgressUpdate(res => { + // requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res)); + // }); + // // #endif + // #-ifdef MP + const len = requestInfo.files.length - 1; + let fileList = new Array; + fileUpload(0); + + function fileUpload(i) { + let item = requestInfo.files[i]; + let fileData = { + fileIndex: i, + files: requestInfo.files, + ...item + }; + let config = { + url: requestInfo.url, + filePath: item.path, + header: requestInfo.header, //加入请求头 + name: requestInfo.name || "file", + success: (response) => { + //是否用外部的数据处理方法 + if (requestInfo.isFactory && dataFactory) { + //数据处理 + dataFactory({ + ...requestInfo, + response: response, + }).then(data => { + fileList.push(data); + requestInfo.onEachUpdate && requestInfo.onEachUpdate({ + data: data, + ...fileData + }); + if (len <= i) { + resolve(fileList); + } else { + fileUpload(i + 1); + } + },err => { + reject(err); + }); + } else { + requestInfo.onEachUpdate && requestInfo.onEachUpdate({ + data: response, + ...fileData + }); + fileList.push(response); + if (len <= i) { + resolve(fileList); + } else { + fileUpload(i + 1); + } + } + }, + fail: (err) => { + reject(err); + } + }; + if (requestInfo.data) { + config.formData = requestInfo.data; + } + const uploadTask = uni.uploadFile(config); + uploadTask.onProgressUpdate(res => { + requestInfo.onProgressUpdate && requestInfo.onProgressUpdate(Object.assign({}, fileData, res)); + }); + } + // #-endif + } else { + reject({ + errMsg: "files 必须是数组类型", + statusCode: 0 + }); + } + }); +} diff --git a/utils/storage.js b/utils/storage.js new file mode 100644 index 0000000..7b2ac32 --- /dev/null +++ b/utils/storage.js @@ -0,0 +1,85 @@ +/** + * 缓存数据优化 + * import storage from '@/utils/storage' + * 使用方法 【 + * 一、设置缓存 + * string storage.set('k', 'string你好啊'); + * json storage.set('k', { "b": "3" }, 2); + * array storage.set('k', [1, 2, 3]); + * boolean storage.set('k', true); + * 二、读取缓存 + * 默认值 storage.get('k') + * string storage.get('k', '你好') + * json storage.get('k', { "a": "1" }) + * 三、移除/清理 + * 移除: storage.remove('k'); + * 清理:storage.clear(); + * 】 + * @type {String} + */ + +const postfix = '_expiry' // 缓存有效期后缀 + +export default { + + /** + * 设置缓存 + * @param {[type]} k [键名] + * @param {[type]} v [键值] + * @param {[type]} t [时间、单位秒] + */ + set(k, v, t) { + uni.setStorageSync(k, v) + const seconds = parseInt(t) + if (seconds > 0) { + let timestamp = Date.parse(new Date()) + timestamp = timestamp / 1000 + seconds + uni.setStorageSync(k + postfix, timestamp + '') + } else { + uni.removeStorageSync(k + postfix) + } + }, + + /** + * 获取缓存 + * @param {[type]} k [键名] + * @param {[type]} def [获取为空时默认] + */ + get(k, def) { + const deadtime = parseInt(uni.getStorageSync(k + postfix)) + if (deadtime) { + if (parseInt(deadtime) < Date.parse(new Date()) / 1000) { + if (def) { + return def + } else { + return false + } + } + } + const res = uni.getStorageSync(k) + if (res) { + return res + } + if (def == undefined || def == "") { + def = false + } + return def + }, + + /** + * 删除指定缓存 + * @param {Object} k + */ + remove(k) { + uni.removeStorageSync(k) + uni.removeStorageSync(k + postfix) + }, + + /** + * 清理所有缓存 + * @return {[type]} [description] + */ + clear() { + uni.clearStorageSync() + } +} \ No newline at end of file