Commit 1af1c1b14bdd3212ce47519a73979c0bb34d53f0

Authored by 易尊强
1 parent cf19c4b0

2/29 17:39

Showing 76 changed files with 6062 additions and 74 deletions
pages/demand/demand.vue
... ... @@ -76,11 +76,16 @@
76 76 nowShow: 1
77 77 }
78 78 },
79   - onLoad() {
  79 + mounted() {
80 80 let that = this
81 81 this.getDemandList()
82 82 this.allPro()
83 83 },
  84 + // onLoad() {
  85 + // let that = this
  86 + // this.getDemandList()
  87 + // this.allPro()
  88 + // },
84 89 methods: {
85 90 // 点击全部
86 91 allPro(index, name) {
... ... @@ -129,7 +134,7 @@
129 134 getDemandList() {
130 135 let that = this
131 136 that.API.getDemandList({
132   - pageSize: 50,
  137 + pageSize: 10000,
133 138 }).then(res => {
134 139 console.log(res)
135 140 that.demandList = res.data.list
... ...
pages/equip/equip.scss
... ... @@ -2,6 +2,29 @@
2 2 width: 100%;
3 3 height: 100%;
4 4 background-color: #f9f9f9;
  5 + overflow-y: scroll;
  6 +}
  7 +.top{
  8 + width: 100%;
  9 + height: 100rpx;
  10 + border-bottom: 1px solid gray;
  11 + display: flex;
  12 + justify-content: space-evenly;
  13 + align-items: center;
  14 + position: fixed;
  15 + top: 70rpx;
  16 + background-color: white;
  17 + z-index: 2;
  18 +}
  19 +.supply{
  20 + font-size: 35rpx;
  21 +}
  22 +.demand{
  23 + font-size: 35rpx;
  24 +}
  25 +.act{
  26 + font-weight: bold;
  27 + color: #E60012;
5 28 }
6 29 .main{
7 30 position: relative;
... ...
pages/equip/equip.vue
1 1 <template>
2 2 <view class="page">
3   - <view class="main">
  3 + <!-- <view class="main">
4 4 <view class="top">
5 5 <view><image src="../../static/nav/supply.png" mode="widthFix" @click="toSupply"></image></view>
6 6 <view><image src="../../static/nav/demand.png" mode="widthFix" @click="toDemand"></image></view>
7 7 </view>
8   - <!-- 明星企业 -->
  8 +
9 9 <view class="star_box">
10 10 <view class="title_box">
11 11 <view class="right">
... ... @@ -14,14 +14,9 @@
14 14 </view>
15 15 <p @click="toAllCompany">查看更多 <image src="../../static/right.png"></image></p>
16 16 </view>
17   - <!-- 下方轮播 -->
18   - <!-- <view class="swiper" style="margin-left: 20rpx;">
19   - <orange-longswiper :list="listData" :config="configData" @tapMore="tapMore" @tapList="tapList"></orange-longswiper>
20   - </view> -->
21 17 <piaoyiSwiper :imgList="imgList" :itemMargin="60" :autoplay="false" :interval="3000" :duration="1000"/>
22 18 </view>
23 19  
24   - <!-- 全部企业 -->
25 20 <view class="all_box">
26 21 <view class="title_box">
27 22 <view class="right">
... ... @@ -41,6 +36,22 @@
41 36 </view>
42 37 </view>
43 38 </view>
  39 + </view> -->
  40 + <view class="top">
  41 + <view class="supply" :style="show === 0 ? 'font-weight: bold;color: #E60012;' : '' " @click="toSupply()">
  42 + 供应中心
  43 + </view>
  44 + <view class="demand" :style="show === 1 ? 'font-weight: bold;color: #E60012;' : '' " @click="toDemand()">
  45 + 需求中心
  46 + </view>
  47 + </view>
  48 + <view class="shuju" style="margin-top: 40rpx;">
  49 + <view class="one" v-if="show === 0">
  50 + <supply></supply>
  51 + </view>
  52 + <view class="two" v-if="show === 1">
  53 + <demand></demand>
  54 + </view>
44 55 </view>
45 56 </view>
46 57 </template>
... ... @@ -48,9 +59,13 @@
48 59 <script>
49 60 import piaoyiSwiper from '../../components/piaoyi-swiper/piaoyi-swiper.vue'
50 61 import request from '@/utils/request.js'
  62 + import supply from '@/pages/supply/supply.vue'
  63 + import demand from '@/pages/demand/demand.vue'
51 64 export default {
52 65 components:{
53   - piaoyiSwiper
  66 + piaoyiSwiper,
  67 + supply,
  68 + demand
54 69 },
55 70 data() {
56 71 return {
... ... @@ -61,68 +76,23 @@
61 76 // 前五的明星企业
62 77 fiveList:[],
63 78 twentyList:[],
64   - baseUrl:'https://app.cehuimi.com'
  79 + baseUrl:'https://app.cehuimi.com',
  80 + show:0
65 81 }
66 82 },
67 83 onLoad(options) {
68   - console.log(options)
69   - this.type = options.data
70   - console.log(this.type)
71   - this.getCompanyList()
  84 +
72 85 },
73 86 methods: {
74   - // 获取对应分类的公司机构
75   - getCompanyList(){
76   - request({
77   - url:'/api/permission/organize',
78   - methos:'get',
79   - data:{stage:this.type}
80   - }).then(res=>{
81   - if(res.code === 200){
82   - console.log(this.type,res)
83   - this.allList = res.data.list
84   - this.fiveList = this.allList.sort(function(a,b){return a.ViewCount - b.ViewCount}).slice(-5)
85   - this.imgList = this.fiveList.map(it=>{
86   - return {
87   - ...it,
88   - id:it.id,
89   - img:'../../static/image/default_logo.jpg',
90   - subject:it.fullName,
91   - detail:it.product
92   - }
93   - })
94   - this.twentyList = this.allList.slice(-20)
95   - }
96   - })
97   - },
98   - GoodsDetails() {
99   - uni.navigateTo({
100   - url: '/pages/GoodsDetails/GoodsDetails'
101   - })
102   - },
103 87 // 跳转到需求中心
104 88 toDemand(){
105   - uni.navigateTo({
106   - url: '/pages/demand/demand'
107   - })
  89 + this.show = 1
108 90 },
109 91 // 跳转到供应中心
110 92 toSupply(){
111   - uni.navigateTo({
112   - url: '/pages/supply/supply'
113   - })
114   - },
115   - // 跳转到所有企业
116   - toAllCompany(){
117   - uni.navigateTo({
118   - url:'/pages/allCompany/allCompany'
119   - })
  93 + this.show = 0
120 94 },
121   - onCompany(item){
122   - uni.navigateTo({
123   - url: `/pages/companyDetail/companyDetail?data=${JSON.stringify(item)}`
124   - })
125   - }
  95 +
126 96 }
127 97 };
128 98 </script>
... ...
pages/home/home.vue
... ... @@ -330,7 +330,7 @@
330 330 },
331 331 neighbor() {
332 332 uni.navigateTo({
333   - url: '/pages/neighbor/neighbor'
  333 + url: '/pages/equip/equip'
334 334 })
335 335 },
336 336 talent() {
... ...
pages/news/news.scss
... ... @@ -81,12 +81,19 @@
81 81 display: flex;
82 82 flex-direction: column;
83 83 justify-content: space-between;
84   - width: 68%;
  84 + // width: 68%;
  85 + width: 100%;
85 86 height: 100%;
86 87 margin-right: 2%;
87 88 .title{
88 89 display: flex;
89 90 margin-bottom: 20rpx;
  91 + width: 100%;
  92 + overflow: hidden;
  93 + -webkit-line-clamp: 2;
  94 + text-overflow: ellipsis;
  95 + display: -webkit-box;
  96 + -webkit-box-orient: vertical;
90 97 text{
91 98 color: #212121;
92 99 font-size: 30rpx;
... ...
pages/news/news.vue
... ... @@ -89,9 +89,9 @@
89 89 <view class="thumb" v-if="item.isImg">
90 90 <image :src="baseUrl + item.imgUrl[0].url"></image>
91 91 </view>
92   - <view class="thumb" v-else>
  92 + <!-- <view class="thumb" v-else>
93 93 <image src="../../static/img/img3.jpg"></image>
94   - </view>
  94 + </view> -->
95 95 </view>
96 96 </view>
97 97 </view>
... ... @@ -110,8 +110,8 @@
110 110 newsList: [],
111 111 // 点击量最高的三个
112 112 highThree: [],
113   - // baseUrl: "http://deyanggaoxin.fengshiyun.com",
114   - baseUrl: "http://192.168.31.224:2018",
  113 + baseUrl: "http://deyanggaoxin.fengshiyun.com",
  114 + // baseUrl: "http://192.168.31.224:2018",
115 115 keyword: '',
116 116 isAdmin: false,
117 117 // 判断你是否有图片
... ...
pages/notice/notice.scss
... ... @@ -86,6 +86,12 @@
86 86 .title{
87 87 display: flex;
88 88 margin-bottom: 20rpx;
  89 + width: 100%;
  90 + overflow: hidden;
  91 + -webkit-line-clamp: 2;
  92 + text-overflow: ellipsis;
  93 + display: -webkit-box;
  94 + -webkit-box-orient: vertical;
89 95 text{
90 96 color: #212121;
91 97 font-size: 30rpx;
... ...
pages/notice/notice.vue
... ... @@ -80,9 +80,9 @@
80 80 <view class="thumb" v-if="item.isImg">
81 81 <image :src="baseUrl + item.imgUrl[0].url"></image>
82 82 </view>
83   - <view class="thumb" v-else>
  83 + <!-- <view class="thumb" v-else>
84 84 <image src="../../static/img/img3.jpg"></image>
85   - </view>
  85 + </view> -->
86 86 </view>
87 87 </view>
88 88 </view>
... ...
pages/policy/policy.scss
... ... @@ -82,12 +82,18 @@
82 82 display: flex;
83 83 flex-direction: column;
84 84 justify-content: space-between;
85   - width: 68%;
  85 + width: 100%;
86 86 height: 100%;
87 87 margin-right: 2%;
88 88 .title{
89 89 display: flex;
90 90 margin-bottom: 20rpx;
  91 + width: 100%;
  92 + overflow: hidden;
  93 + -webkit-line-clamp: 2;
  94 + text-overflow: ellipsis;
  95 + display: -webkit-box;
  96 + -webkit-box-orient: vertical;
91 97 text{
92 98 color: #212121;
93 99 font-size: 30rpx;
... ...
pages/policy/policy.vue
... ... @@ -75,9 +75,9 @@
75 75 <!-- <view class="thumb" v-if="item.isImg">
76 76 <image :src="baseUrl + item.imgUrl[0].url"></image>
77 77 </view> -->
78   - <view class="thumb">
  78 + <!-- <view class="thumb">
79 79 <image src="../../static/img/img3.jpg"></image>
80   - </view>
  80 + </view> -->
81 81 </view>
82 82 </view>
83 83 </view>
... ...
pages/supply/supply.vue
... ... @@ -101,8 +101,6 @@
101 101 mounted() {
102 102 // console.log(this.$refs.line.getBoundingClientRect())
103 103 // console.log(this.$refs.ling)
104   - },
105   - onLoad() {
106 104 // #ifdef APP-PLUS
107 105 this.getProList()
108 106 // this.equipPro()
... ... @@ -111,6 +109,15 @@
111 109 // this.equipPro()
112 110 // this.equipPro()
113 111 },
  112 + // onLoad() {
  113 + // // #ifdef APP-PLUS
  114 + // this.getProList()
  115 + // // this.equipPro()
  116 + // // #endif
  117 + // this.getProList()
  118 + // // this.equipPro()
  119 + // // this.equipPro()
  120 + // },
114 121 methods: {
115 122 // 获取商品列表
116 123 getProList(){
... ...
uni_modules/uv-badge/changelog.md 0 → 100644
  1 +## 1.0.2(2023-06-04)
  2 +1. 修复type等属性为null的时候不显示徽标的BUG
  3 +## 1.0.1(2023-05-16)
  4 +1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
  5 +2. 优化部分功能
  6 +## 1.0.0(2023-05-10)
  7 +uv-badge 徽标数,数字角标
... ...
uni_modules/uv-badge/components/uv-badge/props.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + // 是否显示圆点
  4 + isDot: {
  5 + type: Boolean,
  6 + default: false
  7 + },
  8 + // 显示的内容
  9 + value: {
  10 + type: [Number, String],
  11 + default: ''
  12 + },
  13 + // 是否显示
  14 + show: {
  15 + type: Boolean,
  16 + default: true
  17 + },
  18 + // 最大值,超过最大值会显示 '{max}+'
  19 + max: {
  20 + type: [Number, String],
  21 + default: 999
  22 + },
  23 + // 主题类型,error|warning|success|primary
  24 + type: {
  25 + type: [String,undefined,null],
  26 + default: 'error'
  27 + },
  28 + // 当数值为 0 时,是否展示 Badge
  29 + showZero: {
  30 + type: Boolean,
  31 + default: false
  32 + },
  33 + // 背景颜色,优先级比type高,如设置,type参数会失效
  34 + bgColor: {
  35 + type: [String, null],
  36 + default: null
  37 + },
  38 + // 字体颜色
  39 + color: {
  40 + type: [String, null],
  41 + default: null
  42 + },
  43 + // 徽标形状,circle-四角均为圆角,horn-左下角为直角
  44 + shape: {
  45 + type: [String,undefined,null],
  46 + default: 'circle'
  47 + },
  48 + // 设置数字的显示方式,overflow|ellipsis|limit
  49 + // overflow会根据max字段判断,超出显示`${max}+`
  50 + // ellipsis会根据max判断,超出显示`${max}...`
  51 + // limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
  52 + numberType: {
  53 + type: [String,undefined,null],
  54 + default: 'overflow'
  55 + },
  56 + // 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
  57 + offset: {
  58 + type: Array,
  59 + default: () => []
  60 + },
  61 + // 是否反转背景和字体颜色
  62 + inverted: {
  63 + type: Boolean,
  64 + default: false
  65 + },
  66 + // 是否绝对定位
  67 + absolute: {
  68 + type: Boolean,
  69 + default: false
  70 + },
  71 + ...uni.$uv?.props?.badge
  72 + }
  73 +}
0 74 \ No newline at end of file
... ...
uni_modules/uv-badge/components/uv-badge/uv-badge.vue 0 → 100644
  1 +<template>
  2 + <text
  3 + v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
  4 + :class="[isDot ? 'uv-badge--dot' : 'uv-badge--not-dot', inverted && 'uv-badge--inverted', shape === 'horn' && 'uv-badge--horn', `uv-badge--${propsType}${inverted ? '--inverted' : ''}`]"
  5 + :style="[$uv.addStyle(customStyle), badgeStyle]"
  6 + class="uv-badge"
  7 + >{{ isDot ? '' :showValue }}</text>
  8 +</template>
  9 +
  10 +<script>
  11 + import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
  12 + import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
  13 + import props from './props.js';
  14 + /**
  15 + * badge 徽标数
  16 + * @description 该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
  17 + * @tutorial https://www.uvui.cn/components/badge.html
  18 + *
  19 + * @property {Boolean} isDot 是否显示圆点 (默认 false )
  20 + * @property {String | Number} value 显示的内容
  21 + * @property {Boolean} show 是否显示 (默认 true )
  22 + * @property {String | Number} max 最大值,超过最大值会显示 '{max}+' (默认999)
  23 + * @property {String} type 主题类型,error|warning|success|primary (默认 'error' )
  24 + * @property {Boolean} showZero 当数值为 0 时,是否展示 Badge (默认 false )
  25 + * @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效
  26 + * @property {String} color 字体颜色 (默认 '#ffffff' )
  27 + * @property {String} shape 徽标形状,circle-四角均为圆角,horn-左下角为直角 (默认 'circle' )
  28 + * @property {String} numberType 设置数字的显示方式,overflow|ellipsis|limit (默认 'overflow' )
  29 + * @property {Array}} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
  30 + * @property {Boolean} inverted 是否反转背景和字体颜色(默认 false )
  31 + * @property {Boolean} absolute 是否绝对定位(默认 false )
  32 + * @property {Object} customStyle 定义需要用到的外部样式
  33 + * @example <uv-badge :type="type" :count="count"></uv-badge>
  34 + */
  35 + export default {
  36 + name: 'uv-badge',
  37 + mixins: [mpMixin, mixin, props],
  38 + computed: {
  39 + // 是否将badge中心与父组件右上角重合
  40 + boxStyle() {
  41 + let style = {};
  42 + return style;
  43 + },
  44 + // 整个组件的样式
  45 + badgeStyle() {
  46 + const style = {}
  47 + if(this.color) {
  48 + style.color = this.color
  49 + }
  50 + if (this.bgColor && !this.inverted) {
  51 + style.backgroundColor = this.bgColor
  52 + }
  53 + if (this.absolute) {
  54 + style.position = 'absolute'
  55 + // 如果有设置offset参数
  56 + if(this.offset.length) {
  57 + // top和right分为为offset的第一个和第二个值,如果没有第二个值,则right等于top
  58 + const top = this.offset[0]
  59 + const right = this.offset[1] || top
  60 + style.top = this.$uv.addUnit(top)
  61 + style.right = this.$uv.addUnit(right)
  62 + }
  63 + }
  64 + return style
  65 + },
  66 + showValue() {
  67 + switch (this.numberType) {
  68 + case "overflow":
  69 + return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
  70 + break;
  71 + case "ellipsis":
  72 + return Number(this.value) > Number(this.max) ? "..." : this.value
  73 + break;
  74 + case "limit":
  75 + return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
  76 + Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
  77 + 1e3 * 100) / 100 + "k" : this.value
  78 + break;
  79 + default:
  80 + return Number(this.value)
  81 + }
  82 + },
  83 + propsType(){
  84 + return this.type || 'error'
  85 + }
  86 + }
  87 + }
  88 +</script>
  89 +
  90 +<style lang="scss" scoped>
  91 + @import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
  92 + @import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
  93 + $uv-badge-primary: $uv-primary !default;
  94 + $uv-badge-error: $uv-error !default;
  95 + $uv-badge-success: $uv-success !default;
  96 + $uv-badge-info: $uv-info !default;
  97 + $uv-badge-warning: $uv-warning !default;
  98 + $uv-badge-dot-radius: 100px !default;
  99 + $uv-badge-dot-size: 8px !default;
  100 + $uv-badge-dot-right: 4px !default;
  101 + $uv-badge-dot-top: 0 !default;
  102 + $uv-badge-text-font-size: 11px !default;
  103 + $uv-badge-text-right: 10px !default;
  104 + $uv-badge-text-padding: 2px 5px !default;
  105 + $uv-badge-text-align: center !default;
  106 + $uv-badge-text-color: #FFFFFF !default;
  107 +
  108 + .uv-badge {
  109 + border-top-right-radius: $uv-badge-dot-radius;
  110 + border-top-left-radius: $uv-badge-dot-radius;
  111 + border-bottom-left-radius: $uv-badge-dot-radius;
  112 + border-bottom-right-radius: $uv-badge-dot-radius;
  113 + @include flex;
  114 + line-height: $uv-badge-text-font-size;
  115 + text-align: $uv-badge-text-align;
  116 + font-size: $uv-badge-text-font-size;
  117 + color: $uv-badge-text-color;
  118 +
  119 + &--dot {
  120 + height: $uv-badge-dot-size;
  121 + width: $uv-badge-dot-size;
  122 + }
  123 +
  124 + &--inverted {
  125 + font-size: 13px;
  126 + }
  127 +
  128 + &--not-dot {
  129 + padding: $uv-badge-text-padding;
  130 + }
  131 +
  132 + &--horn {
  133 + border-bottom-left-radius: 0;
  134 + }
  135 +
  136 + &--primary {
  137 + background-color: $uv-badge-primary;
  138 + }
  139 +
  140 + &--primary--inverted {
  141 + color: $uv-badge-primary;
  142 + }
  143 +
  144 + &--error {
  145 + background-color: $uv-badge-error;
  146 + }
  147 +
  148 + &--error--inverted {
  149 + color: $uv-badge-error;
  150 + }
  151 +
  152 + &--success {
  153 + background-color: $uv-badge-success;
  154 + }
  155 +
  156 + &--success--inverted {
  157 + color: $uv-badge-success;
  158 + }
  159 +
  160 + &--info {
  161 + background-color: $uv-badge-info;
  162 + }
  163 +
  164 + &--info--inverted {
  165 + color: $uv-badge-info;
  166 + }
  167 +
  168 + &--warning {
  169 + background-color: $uv-badge-warning;
  170 + }
  171 +
  172 + &--warning--inverted {
  173 + color: $uv-badge-warning;
  174 + }
  175 + }
  176 +</style>
... ...
uni_modules/uv-badge/package.json 0 → 100644
  1 +{
  2 + "id": "uv-badge",
  3 + "displayName": "uv-badge 徽标数,数字角标 全面兼容小程序、nvue、vue2、vue3等多端",
  4 + "version": "1.0.2",
  5 + "description": "徽标数一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。",
  6 + "keywords": [
  7 + "uv-badge",
  8 + "uvui",
  9 + "uv-ui",
  10 + "徽标数",
  11 + "数字角标"
  12 + ],
  13 + "repository": "",
  14 + "engines": {
  15 + "HBuilderX": "^3.1.0"
  16 + },
  17 + "dcloudext": {
  18 + "type": "component-vue",
  19 + "sale": {
  20 + "regular": {
  21 + "price": "0.00"
  22 + },
  23 + "sourcecode": {
  24 + "price": "0.00"
  25 + }
  26 + },
  27 + "contact": {
  28 + "qq": ""
  29 + },
  30 + "declaration": {
  31 + "ads": "无",
  32 + "data": "插件不采集任何数据",
  33 + "permissions": "无"
  34 + },
  35 + "npmurl": ""
  36 + },
  37 + "uni_modules": {
  38 + "dependencies": [
  39 + "uv-ui-tools"
  40 + ],
  41 + "encrypt": [],
  42 + "platforms": {
  43 + "cloud": {
  44 + "tcb": "y",
  45 + "aliyun": "y"
  46 + },
  47 + "client": {
  48 + "Vue": {
  49 + "vue2": "y",
  50 + "vue3": "y"
  51 + },
  52 + "App": {
  53 + "app-vue": "y",
  54 + "app-nvue": "y"
  55 + },
  56 + "H5-mobile": {
  57 + "Safari": "y",
  58 + "Android Browser": "y",
  59 + "微信浏览器(Android)": "y",
  60 + "QQ浏览器(Android)": "y"
  61 + },
  62 + "H5-pc": {
  63 + "Chrome": "y",
  64 + "IE": "y",
  65 + "Edge": "y",
  66 + "Firefox": "y",
  67 + "Safari": "y"
  68 + },
  69 + "小程序": {
  70 + "微信": "y",
  71 + "阿里": "y",
  72 + "百度": "y",
  73 + "字节跳动": "y",
  74 + "QQ": "y",
  75 + "钉钉": "u",
  76 + "快手": "u",
  77 + "飞书": "u",
  78 + "京东": "u"
  79 + },
  80 + "快应用": {
  81 + "华为": "u",
  82 + "联盟": "u"
  83 + }
  84 + }
  85 + }
  86 + }
  87 +}
0 88 \ No newline at end of file
... ...
uni_modules/uv-badge/readme.md 0 → 100644
  1 +## Badge 徽标数
  2 +
  3 +> **组件名:uv-badge**
  4 +
  5 +该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
  6 +
  7 +### <a href="https://www.uvui.cn/components/badge.html" target="_blank">查看文档</a>
  8 +
  9 +### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  10 +
  11 +#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
... ...
uni_modules/uv-icon/changelog.md 0 → 100644
  1 +## 1.0.13(2023-12-06)
  2 +1. 优化
  3 +## 1.0.12(2023-12-06)
  4 +1. 阻止事件冒泡处理
  5 +## 1.0.11(2023-10-29)
  6 +1. imgMode默认值改成aspectFit
  7 +## 1.0.10(2023-08-13)
  8 +1. 优化nvue,方便自定义图标
  9 +## 1.0.9(2023-07-28)
  10 +1. 修改几个对应错误图标的BUG
  11 +## 1.0.8(2023-07-24)
  12 +1. 优化 支持base64图片
  13 +## 1.0.7(2023-07-17)
  14 +1. 修复 uv-icon 恢复uv-empty相关的图标
  15 +## 1.0.6(2023-07-13)
  16 +1. 修复icon设置name属性对应图标错误的BUG
  17 +## 1.0.5(2023-07-04)
  18 +1. 更新图标,删除一些不常用的图标
  19 +2. 删除base64,修改成ttf文件引入读取图标
  20 +3. 自定义图标文档说明:https://www.uvui.cn/guide/customIcon.html
  21 +## 1.0.4(2023-07-03)
  22 +1. 修复主题颜色在APP不生效的BUG
  23 +## 1.0.3(2023-05-24)
  24 +1. 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
  25 +## 1.0.2(2023-05-16)
  26 +1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
  27 +2. 优化部分功能
  28 +## 1.0.1(2023-05-10)
  29 +1. 修复小程序中异常显示
  30 +## 1.0.0(2023-05-04)
  31 +新发版
... ...
uni_modules/uv-icon/components/uv-icon/icons.js 0 → 100644
  1 +export default {
  2 + 'uvicon-level': 'e68f',
  3 + 'uvicon-checkbox-mark': 'e659',
  4 + 'uvicon-folder': 'e694',
  5 + 'uvicon-movie': 'e67c',
  6 + 'uvicon-star-fill': 'e61e',
  7 + 'uvicon-star': 'e618',
  8 + 'uvicon-phone-fill': 'e6ac',
  9 + 'uvicon-phone': 'e6ba',
  10 + 'uvicon-apple-fill': 'e635',
  11 + 'uvicon-backspace': 'e64d',
  12 + 'uvicon-attach': 'e640',
  13 + 'uvicon-empty-data': 'e671',
  14 + 'uvicon-empty-address': 'e68a',
  15 + 'uvicon-empty-favor': 'e662',
  16 + 'uvicon-empty-car': 'e657',
  17 + 'uvicon-empty-order': 'e66b',
  18 + 'uvicon-empty-list': 'e672',
  19 + 'uvicon-empty-search': 'e677',
  20 + 'uvicon-empty-permission': 'e67d',
  21 + 'uvicon-empty-news': 'e67e',
  22 + 'uvicon-empty-history': 'e685',
  23 + 'uvicon-empty-coupon': 'e69b',
  24 + 'uvicon-empty-page': 'e60e',
  25 + 'uvicon-empty-wifi-off': 'e6cc',
  26 + 'uvicon-reload': 'e627',
  27 + 'uvicon-order': 'e695',
  28 + 'uvicon-server-man': 'e601',
  29 + 'uvicon-search': 'e632',
  30 + 'uvicon-more-dot-fill': 'e66f',
  31 + 'uvicon-scan': 'e631',
  32 + 'uvicon-map': 'e665',
  33 + 'uvicon-map-fill': 'e6a8',
  34 + 'uvicon-tags': 'e621',
  35 + 'uvicon-tags-fill': 'e613',
  36 + 'uvicon-eye': 'e664',
  37 + 'uvicon-eye-fill': 'e697',
  38 + 'uvicon-eye-off': 'e69c',
  39 + 'uvicon-eye-off-outline': 'e688',
  40 + 'uvicon-mic': 'e66d',
  41 + 'uvicon-mic-off': 'e691',
  42 + 'uvicon-calendar': 'e65c',
  43 + 'uvicon-trash': 'e623',
  44 + 'uvicon-trash-fill': 'e6ce',
  45 + 'uvicon-play-left': 'e6bf',
  46 + 'uvicon-play-right': 'e6b3',
  47 + 'uvicon-minus': 'e614',
  48 + 'uvicon-plus': 'e625',
  49 + 'uvicon-info-circle': 'e69f',
  50 + 'uvicon-info-circle-fill': 'e6a7',
  51 + 'uvicon-question-circle': 'e622',
  52 + 'uvicon-question-circle-fill': 'e6bc',
  53 + 'uvicon-close': 'e65a',
  54 + 'uvicon-checkmark': 'e64a',
  55 + 'uvicon-checkmark-circle': 'e643',
  56 + 'uvicon-checkmark-circle-fill': 'e668',
  57 + 'uvicon-setting': 'e602',
  58 + 'uvicon-setting-fill': 'e6d0',
  59 + 'uvicon-heart': 'e6a2',
  60 + 'uvicon-heart-fill': 'e68b',
  61 + 'uvicon-camera': 'e642',
  62 + 'uvicon-camera-fill': 'e650',
  63 + 'uvicon-more-circle': 'e69e',
  64 + 'uvicon-more-circle-fill': 'e684',
  65 + 'uvicon-chat': 'e656',
  66 + 'uvicon-chat-fill': 'e63f',
  67 + 'uvicon-bag': 'e647',
  68 + 'uvicon-error-circle': 'e66e',
  69 + 'uvicon-error-circle-fill': 'e655',
  70 + 'uvicon-close-circle': 'e64e',
  71 + 'uvicon-close-circle-fill': 'e666',
  72 + 'uvicon-share': 'e629',
  73 + 'uvicon-share-fill': 'e6bb',
  74 + 'uvicon-share-square': 'e6c4',
  75 + 'uvicon-shopping-cart': 'e6cb',
  76 + 'uvicon-shopping-cart-fill': 'e630',
  77 + 'uvicon-bell': 'e651',
  78 + 'uvicon-bell-fill': 'e604',
  79 + 'uvicon-list': 'e690',
  80 + 'uvicon-list-dot': 'e6a9',
  81 + 'uvicon-zhifubao-circle-fill': 'e617',
  82 + 'uvicon-weixin-circle-fill': 'e6cd',
  83 + 'uvicon-weixin-fill': 'e620',
  84 + 'uvicon-qq-fill': 'e608',
  85 + 'uvicon-qq-circle-fill': 'e6b9',
  86 + 'uvicon-moments-circel-fill': 'e6c2',
  87 + 'uvicon-moments': 'e6a0',
  88 + 'uvicon-car': 'e64f',
  89 + 'uvicon-car-fill': 'e648',
  90 + 'uvicon-warning-fill': 'e6c7',
  91 + 'uvicon-warning': 'e6c1',
  92 + 'uvicon-clock-fill': 'e64b',
  93 + 'uvicon-clock': 'e66c',
  94 + 'uvicon-edit-pen': 'e65d',
  95 + 'uvicon-edit-pen-fill': 'e679',
  96 + 'uvicon-email': 'e673',
  97 + 'uvicon-email-fill': 'e683',
  98 + 'uvicon-minus-circle': 'e6a5',
  99 + 'uvicon-plus-circle': 'e603',
  100 + 'uvicon-plus-circle-fill': 'e611',
  101 + 'uvicon-file-text': 'e687',
  102 + 'uvicon-file-text-fill': 'e67f',
  103 + 'uvicon-pushpin': 'e6d1',
  104 + 'uvicon-pushpin-fill': 'e6b6',
  105 + 'uvicon-grid': 'e68c',
  106 + 'uvicon-grid-fill': 'e698',
  107 + 'uvicon-play-circle': 'e6af',
  108 + 'uvicon-play-circle-fill': 'e62a',
  109 + 'uvicon-pause-circle-fill': 'e60c',
  110 + 'uvicon-pause': 'e61c',
  111 + 'uvicon-pause-circle': 'e696',
  112 + 'uvicon-gift-fill': 'e6b0',
  113 + 'uvicon-gift': 'e680',
  114 + 'uvicon-kefu-ermai': 'e660',
  115 + 'uvicon-server-fill': 'e610',
  116 + 'uvicon-coupon-fill': 'e64c',
  117 + 'uvicon-coupon': 'e65f',
  118 + 'uvicon-integral': 'e693',
  119 + 'uvicon-integral-fill': 'e6b1',
  120 + 'uvicon-home-fill': 'e68e',
  121 + 'uvicon-home': 'e67b',
  122 + 'uvicon-account': 'e63a',
  123 + 'uvicon-account-fill': 'e653',
  124 + 'uvicon-thumb-down-fill': 'e628',
  125 + 'uvicon-thumb-down': 'e60a',
  126 + 'uvicon-thumb-up': 'e612',
  127 + 'uvicon-thumb-up-fill': 'e62c',
  128 + 'uvicon-lock-fill': 'e6a6',
  129 + 'uvicon-lock-open': 'e68d',
  130 + 'uvicon-lock-opened-fill': 'e6a1',
  131 + 'uvicon-lock': 'e69d',
  132 + 'uvicon-red-packet': 'e6c3',
  133 + 'uvicon-photo-fill': 'e6b4',
  134 + 'uvicon-photo': 'e60d',
  135 + 'uvicon-volume-off-fill': 'e6c8',
  136 + 'uvicon-volume-off': 'e6bd',
  137 + 'uvicon-volume-fill': 'e624',
  138 + 'uvicon-volume': 'e605',
  139 + 'uvicon-download': 'e670',
  140 + 'uvicon-arrow-up-fill': 'e636',
  141 + 'uvicon-arrow-down-fill': 'e638',
  142 + 'uvicon-play-left-fill': 'e6ae',
  143 + 'uvicon-play-right-fill': 'e6ad',
  144 + 'uvicon-arrow-downward': 'e634',
  145 + 'uvicon-arrow-leftward': 'e63b',
  146 + 'uvicon-arrow-rightward': 'e644',
  147 + 'uvicon-arrow-upward': 'e641',
  148 + 'uvicon-arrow-down': 'e63e',
  149 + 'uvicon-arrow-right': 'e63c',
  150 + 'uvicon-arrow-left': 'e646',
  151 + 'uvicon-arrow-up': 'e633',
  152 + 'uvicon-skip-back-left': 'e6c5',
  153 + 'uvicon-skip-forward-right': 'e61f',
  154 + 'uvicon-arrow-left-double': 'e637',
  155 + 'uvicon-man': 'e675',
  156 + 'uvicon-woman': 'e626',
  157 + 'uvicon-en': 'e6b8',
  158 + 'uvicon-twitte': 'e607',
  159 + 'uvicon-twitter-circle-fill': 'e6cf'
  160 +}
0 161 \ No newline at end of file
... ...
uni_modules/uv-icon/components/uv-icon/props.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + // 图标类名
  4 + name: {
  5 + type: String,
  6 + default: ''
  7 + },
  8 + // 图标颜色,可接受主题色
  9 + color: {
  10 + type: String,
  11 + default: '#606266'
  12 + },
  13 + // 字体大小,单位px
  14 + size: {
  15 + type: [String, Number],
  16 + default: '16px'
  17 + },
  18 + // 是否显示粗体
  19 + bold: {
  20 + type: Boolean,
  21 + default: false
  22 + },
  23 + // 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
  24 + index: {
  25 + type: [String, Number],
  26 + default: null
  27 + },
  28 + // 触摸图标时的类名
  29 + hoverClass: {
  30 + type: String,
  31 + default: ''
  32 + },
  33 + // 自定义扩展前缀,方便用户扩展自己的图标库
  34 + customPrefix: {
  35 + type: String,
  36 + default: 'uvicon'
  37 + },
  38 + // 图标右边或者下面的文字
  39 + label: {
  40 + type: [String, Number],
  41 + default: ''
  42 + },
  43 + // label的位置,只能右边或者下边
  44 + labelPos: {
  45 + type: String,
  46 + default: 'right'
  47 + },
  48 + // label的大小
  49 + labelSize: {
  50 + type: [String, Number],
  51 + default: '15px'
  52 + },
  53 + // label的颜色
  54 + labelColor: {
  55 + type: String,
  56 + default: '#606266'
  57 + },
  58 + // label与图标的距离
  59 + space: {
  60 + type: [String, Number],
  61 + default: '3px'
  62 + },
  63 + // 图片的mode
  64 + imgMode: {
  65 + type: String,
  66 + default: 'aspectFit'
  67 + },
  68 + // 用于显示图片小图标时,图片的宽度
  69 + width: {
  70 + type: [String, Number],
  71 + default: ''
  72 + },
  73 + // 用于显示图片小图标时,图片的高度
  74 + height: {
  75 + type: [String, Number],
  76 + default: ''
  77 + },
  78 + // 用于解决某些情况下,让图标垂直居中的用途
  79 + top: {
  80 + type: [String, Number],
  81 + default: 0
  82 + },
  83 + // 是否阻止事件传播
  84 + stop: {
  85 + type: Boolean,
  86 + default: false
  87 + },
  88 + ...uni.$uv?.props?.icon
  89 + }
  90 +}
0 91 \ No newline at end of file
... ...
uni_modules/uv-icon/components/uv-icon/uv-icon.vue 0 → 100644
  1 +<template>
  2 + <view
  3 + class="uv-icon"
  4 + @tap="clickHandler"
  5 + :class="['uv-icon--' + labelPos]"
  6 + >
  7 + <image
  8 + class="uv-icon__img"
  9 + v-if="isImg"
  10 + :src="name"
  11 + :mode="imgMode"
  12 + :style="[imgStyle, $uv.addStyle(customStyle)]"
  13 + ></image>
  14 + <text
  15 + v-else
  16 + class="uv-icon__icon"
  17 + :class="uClasses"
  18 + :style="[iconStyle, $uv.addStyle(customStyle)]"
  19 + :hover-class="hoverClass"
  20 + >{{icon}}</text>
  21 + <!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
  22 + <text
  23 + v-if="label !== ''"
  24 + class="uv-icon__label"
  25 + :style="{
  26 + color: labelColor,
  27 + fontSize: $uv.addUnit(labelSize),
  28 + marginLeft: labelPos == 'right' ? $uv.addUnit(space) : 0,
  29 + marginTop: labelPos == 'bottom' ? $uv.addUnit(space) : 0,
  30 + marginRight: labelPos == 'left' ? $uv.addUnit(space) : 0,
  31 + marginBottom: labelPos == 'top' ? $uv.addUnit(space) : 0
  32 + }"
  33 + >{{ label }}</text>
  34 + </view>
  35 +</template>
  36 +
  37 +<script>
  38 + import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
  39 + import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
  40 + // #ifdef APP-NVUE
  41 + // nvue通过weex的dom模块引入字体,相关文档地址如下:
  42 + // https://weex.apache.org/zh/docs/modules/dom.html#addrule
  43 + import iconUrl from './uvicons.ttf';
  44 + const domModule = weex.requireModule('dom')
  45 + domModule.addRule('fontFace', {
  46 + 'fontFamily': "uvicon-iconfont",
  47 + 'src': "url('" + iconUrl + "')"
  48 + })
  49 + // #endif
  50 + // 引入图标名称,已经对应的unicode
  51 + import icons from './icons';
  52 + import props from './props.js';
  53 + /**
  54 + * icon 图标
  55 + * @description 基于字体的图标集,包含了大多数常见场景的图标。
  56 + * @tutorial https://www.uvui.cn/components/icon.html
  57 + * @property {String} name 图标名称,见示例图标集
  58 + * @property {String} color 图标颜色,可接受主题色 (默认 color['uv-content-color'] )
  59 + * @property {String | Number} size 图标字体大小,单位px (默认 '16px' )
  60 + * @property {Boolean} bold 是否显示粗体 (默认 false )
  61 + * @property {String | Number} index 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
  62 + * @property {String} hoverClass 图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
  63 + * @property {String} customPrefix 自定义扩展前缀,方便用户扩展自己的图标库 (默认 'uicon' )
  64 + * @property {String | Number} label 图标右侧的label文字
  65 + * @property {String} labelPos label相对于图标的位置,只能right或bottom (默认 'right' )
  66 + * @property {String | Number} labelSize label字体大小,单位px (默认 '15px' )
  67 + * @property {String} labelColor 图标右侧的label文字颜色 ( 默认 color['uv-content-color'] )
  68 + * @property {String | Number} space label与图标的距离,单位px (默认 '3px' )
  69 + * @property {String} imgMode 图片的mode
  70 + * @property {String | Number} width 显示图片小图标时的宽度
  71 + * @property {String | Number} height 显示图片小图标时的高度
  72 + * @property {String | Number} top 图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途 (默认 0 )
  73 + * @property {Boolean} stop 是否阻止事件传播 (默认 false )
  74 + * @property {Object} customStyle icon的样式,对象形式
  75 + * @event {Function} click 点击图标时触发
  76 + * @event {Function} touchstart 事件触摸时触发
  77 + * @example <uv-icon name="photo" color="#2979ff" size="28"></uv-icon>
  78 + */
  79 + export default {
  80 + name: 'uv-icon',
  81 + emits: ['click'],
  82 + mixins: [mpMixin, mixin, props],
  83 + data() {
  84 + return {
  85 + colorType: [
  86 + 'primary',
  87 + 'success',
  88 + 'info',
  89 + 'error',
  90 + 'warning'
  91 + ]
  92 + }
  93 + },
  94 + computed: {
  95 + uClasses() {
  96 + let classes = []
  97 + classes.push(this.customPrefix)
  98 + classes.push(this.customPrefix + '-' + this.name)
  99 + // 主题色,通过类配置
  100 + if (this.color && this.colorType.includes(this.color)) classes.push('uv-icon__icon--' + this.color)
  101 + // 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
  102 + // 故需将其拆成一个字符串的形式,通过空格隔开各个类名
  103 + //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
  104 + classes = classes.join(' ')
  105 + //#endif
  106 + return classes
  107 + },
  108 + iconStyle() {
  109 + let style = {}
  110 + style = {
  111 + fontSize: this.$uv.addUnit(this.size),
  112 + lineHeight: this.$uv.addUnit(this.size),
  113 + fontWeight: this.bold ? 'bold' : 'normal',
  114 + // 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
  115 + top: this.$uv.addUnit(this.top)
  116 + }
  117 + // 非主题色值时,才当作颜色值
  118 + if (this.color && !this.colorType.includes(this.color)) style.color = this.color
  119 + return style
  120 + },
  121 + // 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
  122 + isImg() {
  123 + const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
  124 + return this.name.indexOf('/') !== -1 || isBase64;
  125 + },
  126 + imgStyle() {
  127 + let style = {}
  128 + // 如果设置width和height属性,则优先使用,否则使用size属性
  129 + style.width = this.width ? this.$uv.addUnit(this.width) : this.$uv.addUnit(this.size)
  130 + style.height = this.height ? this.$uv.addUnit(this.height) : this.$uv.addUnit(this.size)
  131 + return style
  132 + },
  133 + // 通过图标名,查找对应的图标
  134 + icon() {
  135 + // 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
  136 + const code = icons['uvicon-' + this.name];
  137 + // #ifdef APP-NVUE
  138 + if(!code) {
  139 + return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? unescape(`%u${this.name}`) : '';
  140 + }
  141 + // #endif
  142 + return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? this.name : '';
  143 + }
  144 + },
  145 + methods: {
  146 + clickHandler(e) {
  147 + this.$emit('click', this.index)
  148 + // 是否阻止事件冒泡
  149 + this.stop && this.preventEvent(e)
  150 + }
  151 + }
  152 + }
  153 +</script>
  154 +
  155 +<style lang="scss" scoped>
  156 + @import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
  157 + @import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
  158 + // 变量定义
  159 + $uv-icon-primary: $uv-primary !default;
  160 + $uv-icon-success: $uv-success !default;
  161 + $uv-icon-info: $uv-info !default;
  162 + $uv-icon-warning: $uv-warning !default;
  163 + $uv-icon-error: $uv-error !default;
  164 + $uv-icon-label-line-height: 1 !default;
  165 + /* #ifndef APP-NVUE */
  166 + // 非nvue下加载字体
  167 + @font-face {
  168 + font-family: 'uvicon-iconfont';
  169 + src: url('./uvicons.ttf') format('truetype');
  170 + }
  171 + /* #endif */
  172 + .uv-icon {
  173 + /* #ifndef APP-NVUE */
  174 + display: flex;
  175 + /* #endif */
  176 + align-items: center;
  177 + &--left {
  178 + flex-direction: row-reverse;
  179 + align-items: center;
  180 + }
  181 + &--right {
  182 + flex-direction: row;
  183 + align-items: center;
  184 + }
  185 + &--top {
  186 + flex-direction: column-reverse;
  187 + justify-content: center;
  188 + }
  189 + &--bottom {
  190 + flex-direction: column;
  191 + justify-content: center;
  192 + }
  193 + &__icon {
  194 + font-family: uvicon-iconfont;
  195 + position: relative;
  196 + @include flex;
  197 + align-items: center;
  198 + &--primary {
  199 + color: $uv-icon-primary;
  200 + }
  201 + &--success {
  202 + color: $uv-icon-success;
  203 + }
  204 + &--error {
  205 + color: $uv-icon-error;
  206 + }
  207 + &--warning {
  208 + color: $uv-icon-warning;
  209 + }
  210 + &--info {
  211 + color: $uv-icon-info;
  212 + }
  213 + }
  214 + &__img {
  215 + /* #ifndef APP-NVUE */
  216 + height: auto;
  217 + will-change: transform;
  218 + /* #endif */
  219 + }
  220 + &__label {
  221 + /* #ifndef APP-NVUE */
  222 + line-height: $uv-icon-label-line-height;
  223 + /* #endif */
  224 + }
  225 + }
  226 +</style>
0 227 \ No newline at end of file
... ...
uni_modules/uv-icon/components/uv-icon/uvicons.ttf 0 → 100644
No preview for this file type
uni_modules/uv-icon/package.json 0 → 100644
  1 +{
  2 + "id": "uv-icon",
  3 + "displayName": "uv-icon 图标 全面兼容vue3+2、app、h5、小程序等多端",
  4 + "version": "1.0.13",
  5 + "description": "基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。可自定义颜色、大小。",
  6 + "keywords": [
  7 + "uv-ui,uvui,uv-icon,icon,图标,字体图标"
  8 +],
  9 + "repository": "",
  10 + "engines": {
  11 + "HBuilderX": "^3.1.0"
  12 + },
  13 + "dcloudext": {
  14 + "type": "component-vue",
  15 + "sale": {
  16 + "regular": {
  17 + "price": "0.00"
  18 + },
  19 + "sourcecode": {
  20 + "price": "0.00"
  21 + }
  22 + },
  23 + "contact": {
  24 + "qq": ""
  25 + },
  26 + "declaration": {
  27 + "ads": "无",
  28 + "data": "插件不采集任何数据",
  29 + "permissions": "无"
  30 + },
  31 + "npmurl": ""
  32 + },
  33 + "uni_modules": {
  34 + "dependencies": [
  35 + "uv-ui-tools"
  36 + ],
  37 + "encrypt": [],
  38 + "platforms": {
  39 + "cloud": {
  40 + "tcb": "y",
  41 + "aliyun": "y"
  42 + },
  43 + "client": {
  44 + "Vue": {
  45 + "vue2": "y",
  46 + "vue3": "y"
  47 + },
  48 + "App": {
  49 + "app-vue": "y",
  50 + "app-nvue": "y"
  51 + },
  52 + "H5-mobile": {
  53 + "Safari": "y",
  54 + "Android Browser": "y",
  55 + "微信浏览器(Android)": "y",
  56 + "QQ浏览器(Android)": "y"
  57 + },
  58 + "H5-pc": {
  59 + "Chrome": "y",
  60 + "IE": "y",
  61 + "Edge": "y",
  62 + "Firefox": "y",
  63 + "Safari": "y"
  64 + },
  65 + "小程序": {
  66 + "微信": "y",
  67 + "阿里": "y",
  68 + "百度": "y",
  69 + "字节跳动": "y",
  70 + "QQ": "y",
  71 + "钉钉": "u",
  72 + "快手": "u",
  73 + "飞书": "u",
  74 + "京东": "u"
  75 + },
  76 + "快应用": {
  77 + "华为": "u",
  78 + "联盟": "u"
  79 + }
  80 + }
  81 + }
  82 + }
  83 +}
0 84 \ No newline at end of file
... ...
uni_modules/uv-icon/readme.md 0 → 100644
  1 +## uv-icon 图标库
  2 +
  3 +> **组件名:uv-icon**
  4 +
  5 +基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。
  6 +
  7 +# <a href="https://www.uvui.cn/components/icon.html" target="_blank">查看文档</a>
  8 +
  9 +## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  10 +
  11 +### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  12 +
  13 +![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
  14 +
  15 +#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
... ...
uni_modules/uv-sticky/changelog.md 0 → 100644
  1 +## 1.0.4(2023-12-20)
  2 +1. 优化
  3 +## 1.0.3(2023-10-13)
  4 +1. unmounted兼容vue3
  5 +## 1.0.2(2023-08-27)
  6 +1. 优化
  7 +## 1.0.1(2023-05-16)
  8 +1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
  9 +2. 优化部分功能
  10 +## 1.0.0(2023-05-10)
  11 +uv-sticky 吸顶
... ...
uni_modules/uv-sticky/components/uv-sticky/props.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + // 吸顶容器到顶部某个距离的时候,进行吸顶,在H5平台,NavigationBar为44px
  4 + offsetTop: {
  5 + type: [String, Number],
  6 + default: 0
  7 + },
  8 + // 自定义导航栏的高度
  9 + customNavHeight: {
  10 + type: [String, Number],
  11 + // #ifdef H5
  12 + // H5端的导航栏属于“自定义”导航栏的范畴,因为它是非原生的,与普通元素一致
  13 + default: 44,
  14 + // #endif
  15 + // #ifndef H5
  16 + default: 0
  17 + // #endif
  18 + },
  19 + // 是否禁用吸顶功能
  20 + disabled: {
  21 + type: Boolean,
  22 + default: false
  23 + },
  24 + // 吸顶区域的背景颜色
  25 + bgColor: {
  26 + type: String,
  27 + default: 'transparent'
  28 + },
  29 + // z-index值
  30 + zIndex: {
  31 + type: [String, Number],
  32 + default: ''
  33 + },
  34 + // 列表中的索引值
  35 + index: {
  36 + type: [String, Number],
  37 + default: ''
  38 + },
  39 + ...uni.$uv?.props?.sticky
  40 + }
  41 +}
0 42 \ No newline at end of file
... ...
uni_modules/uv-sticky/components/uv-sticky/uv-sticky.vue 0 → 100644
  1 +<template>
  2 + <view
  3 + class="uv-sticky"
  4 + :id="elId"
  5 + :style="[style]"
  6 + >
  7 + <view
  8 + :style="[stickyContent]"
  9 + class="uv-sticky__content"
  10 + >
  11 + <slot />
  12 + </view>
  13 + </view>
  14 +</template>
  15 +
  16 +<script>
  17 + import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
  18 + import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
  19 + import props from './props.js';;
  20 + /**
  21 + * sticky 吸顶
  22 + * @description 该组件与CSS中position: sticky属性实现的效果一致,当组件达到预设的到顶部距离时, 就会固定在指定位置,组件位置大于预设的顶部距离时,会重新按照正常的布局排列。
  23 + * @tutorial https://www.uvui.cn/components/sticky.html
  24 + * @property {String | Number} offsetTop 吸顶时与顶部的距离,单位px(默认 0 )
  25 + * @property {String | Number} customNavHeight 自定义导航栏的高度 (h5 默认44 其他默认 0 )
  26 + * @property {Boolean} disabled 是否开启吸顶功能 (默认 false )
  27 + * @property {String} bgColor 组件背景颜色(默认 '#ffffff' )
  28 + * @property {String | Number} zIndex 吸顶时的z-index值
  29 + * @property {String | Number} index 自定义标识,用于区分是哪一个组件
  30 + * @property {Object} customStyle 组件的样式,对象形式
  31 + * @example <uv-sticky offsetTop="200"><view>塞下秋来风景异,衡阳雁去无留意</view></uv-sticky>
  32 + */
  33 + export default {
  34 + name: 'uv-sticky',
  35 + mixins: [mpMixin, mixin, props],
  36 + data() {
  37 + return {
  38 + cssSticky: false, // 是否使用css的sticky实现
  39 + stickyTop: 0, // 吸顶的top值,因为可能受自定义导航栏影响,最终的吸顶值非offsetTop值
  40 + elId: '',
  41 + left: 0, // js模式时,吸顶的内容因为处于postition: fixed模式,为了和原来保持一致的样式,需要记录并重新设置它的left,height,width属性
  42 + width: 'auto',
  43 + height: 'auto',
  44 + fixed: false, // js模式时,是否处于吸顶模式
  45 + }
  46 + },
  47 + computed: {
  48 + style() {
  49 + const style = {}
  50 + if(!this.disabled) {
  51 + if (this.cssSticky) {
  52 + style.position = 'sticky'
  53 + style.zIndex = this.uZindex
  54 + style.top = this.$uv.addUnit(this.stickyTop)
  55 + } else {
  56 + style.height = this.fixed ? this.height + 'px' : 'auto'
  57 + }
  58 + } else {
  59 + // 无需吸顶时,设置会默认的relative(nvue)和非nvue的static静态模式即可
  60 + // #ifdef APP-NVUE
  61 + style.position = 'relative'
  62 + // #endif
  63 + // #ifndef APP-NVUE
  64 + style.position = 'static'
  65 + // #endif
  66 + }
  67 + style.backgroundColor = this.bgColor
  68 + return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
  69 + },
  70 + // 吸顶内容的样式
  71 + stickyContent() {
  72 + const style = {}
  73 + if (!this.cssSticky) {
  74 + style.position = this.fixed ? 'fixed' : 'static'
  75 + style.top = this.stickyTop + 'px'
  76 + style.left = this.left + 'px'
  77 + style.width = this.width == 'auto' ? 'auto' : this.width + 'px'
  78 + style.zIndex = this.uZindex
  79 + }
  80 + return style
  81 + },
  82 + uZindex() {
  83 + return this.zIndex ? this.zIndex : 970
  84 + }
  85 + },
  86 + created() {
  87 + this.elId = this.$uv.guid();
  88 + },
  89 + mounted() {
  90 + this.init()
  91 + },
  92 + methods: {
  93 + init() {
  94 + this.getStickyTop()
  95 + // 判断使用的模式
  96 + this.checkSupportCssSticky()
  97 + // 如果不支持css sticky,则使用js方案,此方案性能比不上css方案
  98 + if (!this.cssSticky) {
  99 + !this.disabled && this.initObserveContent()
  100 + }
  101 + },
  102 + initObserveContent() {
  103 + // 获取吸顶内容的高度,用于在js吸顶模式时,给父元素一个填充高度,防止"塌陷"
  104 + this.$uvGetRect('#' + this.elId).then((res) => {
  105 + this.height = res.height
  106 + this.left = res.left
  107 + this.width = res.width
  108 + this.$nextTick(() => {
  109 + this.observeContent()
  110 + })
  111 + })
  112 + },
  113 + observeContent() {
  114 + // 先断掉之前的观察
  115 + this.disconnectObserver('contentObserver')
  116 + const contentObserver = uni.createIntersectionObserver({
  117 + // 检测的区间范围
  118 + thresholds: [0.95, 0.98, 1]
  119 + })
  120 + // 到屏幕顶部的高度时触发
  121 + contentObserver.relativeToViewport({
  122 + top: -this.stickyTop
  123 + })
  124 + // 绑定观察的元素
  125 + contentObserver.observe(`#${this.elId}`, res => {
  126 + this.setFixed(res.boundingClientRect.top)
  127 + })
  128 + this.contentObserver = contentObserver
  129 + },
  130 + setFixed(top) {
  131 + // 判断是否出于吸顶条件范围
  132 + const fixed = top <= this.stickyTop
  133 + this.fixed = fixed
  134 + },
  135 + disconnectObserver(observerName) {
  136 + // 断掉观察,释放资源
  137 + const observer = this[observerName]
  138 + observer && observer.disconnect()
  139 + },
  140 + getStickyTop() {
  141 + this.stickyTop = this.$uv.getPx(this.offsetTop) + this.$uv.getPx(this.customNavHeight)
  142 + },
  143 + async checkSupportCssSticky() {
  144 + // #ifdef H5
  145 + // H5,一般都是现代浏览器,是支持css sticky的,这里使用创建元素嗅探的形式判断
  146 + if (this.checkCssStickyForH5()) {
  147 + this.cssSticky = true
  148 + }
  149 + // #endif
  150 +
  151 + // 如果安卓版本高于8.0,依然认为是支持css sticky的(因为安卓7在某些机型,可能不支持sticky)
  152 + if (this.$uv.os() === 'android' && Number(this.$uv.sys().system) > 8) {
  153 + this.cssSticky = true
  154 + }
  155 +
  156 + // APP-Vue和微信平台,通过computedStyle判断是否支持css sticky
  157 + // #ifdef APP-VUE || MP-WEIXIN
  158 + this.cssSticky = await this.checkComputedStyle()
  159 + // #endif
  160 +
  161 + // ios上,从ios6开始,都是支持css sticky的
  162 + if (this.$uv.os() === 'ios') {
  163 + this.cssSticky = true
  164 + }
  165 +
  166 + // nvue,是支持css sticky的
  167 + // #ifdef APP-NVUE
  168 + this.cssSticky = true
  169 + // #endif
  170 + },
  171 + // 在APP和微信小程序上,通过uni.createSelectorQuery可以判断是否支持css sticky
  172 + checkComputedStyle() {
  173 + // 方法内进行判断,避免在其他平台生成无用代码
  174 + // #ifdef APP-VUE || MP-WEIXIN
  175 + return new Promise(resolve => {
  176 + uni.createSelectorQuery().in(this).select('.uv-sticky').fields({
  177 + computedStyle: ["position"]
  178 + }).exec(e => {
  179 + resolve('sticky' === e[0].position)
  180 + })
  181 + })
  182 + // #endif
  183 + },
  184 + // H5通过创建元素的形式嗅探是否支持css sticky
  185 + // 判断浏览器是否支持sticky属性
  186 + checkCssStickyForH5() {
  187 + // 方法内进行判断,避免在其他平台生成无用代码
  188 + // #ifdef H5
  189 + const vendorList = ['', '-webkit-', '-ms-', '-moz-', '-o-'],
  190 + vendorListLength = vendorList.length,
  191 + stickyElement = document.createElement('div')
  192 + for (let i = 0; i < vendorListLength; i++) {
  193 + stickyElement.style.position = vendorList[i] + 'sticky'
  194 + if (stickyElement.style.position !== '') {
  195 + return true
  196 + }
  197 + }
  198 + return false;
  199 + // #endif
  200 + }
  201 + },
  202 + // #ifdef VUE2
  203 + beforeDestroy() {
  204 + this.disconnectObserver('contentObserver')
  205 + },
  206 + // #endif
  207 + // #ifdef VUE3
  208 + unmounted() {
  209 + this.disconnectObserver('contentObserver')
  210 + }
  211 + // #endif
  212 + }
  213 +</script>
  214 +
  215 +<style lang="scss" scoped>
  216 + @import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
  217 + .uv-sticky {
  218 + /* #ifdef APP-VUE || MP-WEIXIN */
  219 + // 此处默认写sticky属性,是为了给微信和APP通过uni.createSelectorQuery查询是否支持css sticky使用
  220 + position: sticky;
  221 + /* #endif */
  222 + }
  223 +</style>
... ...
uni_modules/uv-sticky/package.json 0 → 100644
  1 +{
  2 + "id": "uv-sticky",
  3 + "displayName": "uv-sticky 吸顶 全面兼容小程序、nvue、vue2、vue3等多端",
  4 + "version": "1.0.4",
  5 + "description": "吸顶组件与CSS中position: sticky属性实现的效果一致,当组件达到预设的到顶部距离时, 就会固定在指定位置,组件位置大于预设的顶部距离时,会重新按照正常的布局排列。",
  6 + "keywords": [
  7 + "uv-sticky",
  8 + "uvui",
  9 + "uv-ui",
  10 + "sticky",
  11 + "吸顶"
  12 +],
  13 + "repository": "",
  14 + "engines": {
  15 + "HBuilderX": "^3.1.0"
  16 + },
  17 + "dcloudext": {
  18 + "type": "component-vue",
  19 + "sale": {
  20 + "regular": {
  21 + "price": "0.00"
  22 + },
  23 + "sourcecode": {
  24 + "price": "0.00"
  25 + }
  26 + },
  27 + "contact": {
  28 + "qq": ""
  29 + },
  30 + "declaration": {
  31 + "ads": "无",
  32 + "data": "插件不采集任何数据",
  33 + "permissions": "无"
  34 + },
  35 + "npmurl": ""
  36 + },
  37 + "uni_modules": {
  38 + "dependencies": [
  39 + "uv-ui-tools"
  40 + ],
  41 + "encrypt": [],
  42 + "platforms": {
  43 + "cloud": {
  44 + "tcb": "y",
  45 + "aliyun": "y"
  46 + },
  47 + "client": {
  48 + "Vue": {
  49 + "vue2": "y",
  50 + "vue3": "y"
  51 + },
  52 + "App": {
  53 + "app-vue": "y",
  54 + "app-nvue": "y"
  55 + },
  56 + "H5-mobile": {
  57 + "Safari": "y",
  58 + "Android Browser": "y",
  59 + "微信浏览器(Android)": "y",
  60 + "QQ浏览器(Android)": "y"
  61 + },
  62 + "H5-pc": {
  63 + "Chrome": "y",
  64 + "IE": "y",
  65 + "Edge": "y",
  66 + "Firefox": "y",
  67 + "Safari": "y"
  68 + },
  69 + "小程序": {
  70 + "微信": "y",
  71 + "阿里": "y",
  72 + "百度": "y",
  73 + "字节跳动": "y",
  74 + "QQ": "y",
  75 + "钉钉": "u",
  76 + "快手": "u",
  77 + "飞书": "u",
  78 + "京东": "u"
  79 + },
  80 + "快应用": {
  81 + "华为": "u",
  82 + "联盟": "u"
  83 + }
  84 + }
  85 + }
  86 + }
  87 +}
0 88 \ No newline at end of file
... ...
uni_modules/uv-sticky/readme.md 0 → 100644
  1 +## Sticky 吸顶
  2 +
  3 +> **组件名:uv-sticky**
  4 +
  5 +该组件与CSS中position: sticky属性实现的效果一致,当组件达到预设的到顶部距离时, 就会固定在指定位置,组件位置大于预设的顶部距离时,会重新按照正常的布局排列。
  6 +
  7 +### <a href="https://www.uvui.cn/components/sticky.html" target="_blank">查看文档</a>
  8 +
  9 +### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  10 +
  11 +#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
... ...
uni_modules/uv-tabs/changelog.md 0 → 100644
  1 +## 1.0.9(2023-12-01)
  2 +1. 修复current为字符串activeStyle不生效的BUG
  3 +2. 优化文档
  4 +## 1.0.8(2023-10-13)
  5 +1. 优化点击一个选项,change事件重复派发的问题
  6 +## 1.0.7(2023-09-14)
  7 +1. 优化首次加载时,处理下划线会有左到右的过渡效果
  8 +## 1.0.6(2023-09-13)
  9 +1. 修复设置lineWidth未带单位产生的误差BUG
  10 +## 1.0.5(2023-06-23)
  11 +添加uv-icon依赖
  12 +## 1.0.4(2023-06-16)
  13 +1. 增加customStyle参数
  14 +## 1.0.3(2023-06-12)
  15 +1. activeStyle设置字体大小,导致下划线位置不对的BUG,增加this.$nextTick机制
  16 +## 1.0.2(2023-05-23)
  17 +1. 修复nvue中不滚动的BUG
  18 +## 1.0.1(2023-05-16)
  19 +1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
  20 +2. 优化部分功能
  21 +## 1.0.0(2023-05-10)
  22 +uv-tabs 标签选项卡
... ...
uni_modules/uv-tabs/components/uv-tabs/props.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + // 滑块的移动过渡时间,单位ms
  4 + duration: {
  5 + type: Number,
  6 + default: 300
  7 + },
  8 + // tabs标签数组
  9 + list: {
  10 + type: Array,
  11 + default: () => []
  12 + },
  13 + // 滑块颜色
  14 + lineColor: {
  15 + type: String,
  16 + default: '#3c9cff'
  17 + },
  18 + // 菜单选择中时的样式
  19 + activeStyle: {
  20 + type: [String, Object],
  21 + default: () => ({
  22 + color: '#303133'
  23 + })
  24 + },
  25 + // 菜单非选中时的样式
  26 + inactiveStyle: {
  27 + type: [String, Object],
  28 + default: () => ({
  29 + color: '#606266'
  30 + })
  31 + },
  32 + // 滑块长度
  33 + lineWidth: {
  34 + type: [String, Number],
  35 + default: 20
  36 + },
  37 + // 滑块高度
  38 + lineHeight: {
  39 + type: [String, Number],
  40 + default: 3
  41 + },
  42 + // 滑块背景显示大小,当滑块背景设置为图片时使用
  43 + lineBgSize: {
  44 + type: String,
  45 + default: 'cover'
  46 + },
  47 + // 菜单item的样式
  48 + itemStyle: {
  49 + type: [String, Object],
  50 + default: () => ({
  51 + height: '44px'
  52 + })
  53 + },
  54 + // 菜单是否可滚动
  55 + scrollable: {
  56 + type: Boolean,
  57 + default: true
  58 + },
  59 + // 当前选中标签的索引
  60 + current: {
  61 + type: [Number, String],
  62 + default: 0
  63 + },
  64 + // 默认读取的键名
  65 + keyName: {
  66 + type: String,
  67 + default: 'name'
  68 + },
  69 + ...uni.$uv?.props?.tabs
  70 + }
  71 +}
0 72 \ No newline at end of file
... ...
uni_modules/uv-tabs/components/uv-tabs/uv-tabs.vue 0 → 100644
  1 +<template>
  2 + <view class="uv-tabs" :style="[$uv.addStyle(customStyle)]">
  3 + <view class="uv-tabs__wrapper">
  4 + <slot name="left" />
  5 + <view class="uv-tabs__wrapper__scroll-view-wrapper">
  6 + <scroll-view
  7 + :scroll-x="scrollable"
  8 + :scroll-left="scrollLeft"
  9 + scroll-with-animation
  10 + class="uv-tabs__wrapper__scroll-view"
  11 + :show-scrollbar="false"
  12 + ref="uv-tabs__wrapper__scroll-view"
  13 + >
  14 + <view
  15 + class="uv-tabs__wrapper__nav"
  16 + ref="uv-tabs__wrapper__nav"
  17 + :style="{
  18 + flex: scrollable ? '' : 1
  19 + }"
  20 + >
  21 + <view
  22 + class="uv-tabs__wrapper__nav__item"
  23 + v-for="(item, index) in list"
  24 + :key="index"
  25 + @tap="clickHandler(item, index)"
  26 + :ref="`uv-tabs__wrapper__nav__item-${index}`"
  27 + :style="[{flex: scrollable ? '' : 1},$uv.addStyle(itemStyle)]"
  28 + :class="[`uv-tabs__wrapper__nav__item-${index}`, item.disabled && 'uv-tabs__wrapper__nav__item--disabled']"
  29 + >
  30 + <text
  31 + :class="[item.disabled && 'uv-tabs__wrapper__nav__item__text--disabled']"
  32 + class="uv-tabs__wrapper__nav__item__text"
  33 + :style="[textStyle(index)]"
  34 + >{{ item[keyName] }}</text>
  35 + <uv-badge
  36 + :show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))"
  37 + :isDot="item.badge && item.badge.isDot || propsBadge.isDot"
  38 + :value="item.badge && item.badge.value || propsBadge.value"
  39 + :max="item.badge && item.badge.max || propsBadge.max"
  40 + :type="item.badge && item.badge.type || propsBadge.type"
  41 + :showZero="item.badge && item.badge.showZero || propsBadge.showZero"
  42 + :bgColor="item.badge && item.badge.bgColor || propsBadge.bgColor"
  43 + :color="item.badge && item.badge.color || propsBadge.color"
  44 + :shape="item.badge && item.badge.shape || propsBadge.shape"
  45 + :numberType="item.badge && item.badge.numberType || propsBadge.numberType"
  46 + :inverted="item.badge && item.badge.inverted || propsBadge.inverted"
  47 + customStyle="margin-left: 4px;"
  48 + ></uv-badge>
  49 + </view>
  50 + <!-- #ifdef APP-NVUE -->
  51 + <view
  52 + class="uv-tabs__wrapper__nav__line"
  53 + ref="uv-tabs__wrapper__nav__line"
  54 + :style="[{
  55 + width: $uv.addUnit(lineWidth),
  56 + height: firstTime?0:$uv.addUnit(lineHeight),
  57 + background: lineColor,
  58 + backgroundSize: lineBgSize
  59 + }]"
  60 + >
  61 + <!-- #endif -->
  62 + <!-- #ifndef APP-NVUE -->
  63 + <view
  64 + class="uv-tabs__wrapper__nav__line"
  65 + ref="uv-tabs__wrapper__nav__line"
  66 + :style="[{
  67 + width: $uv.addUnit(lineWidth),
  68 + transform: `translate(${lineOffsetLeft}px)`,
  69 + transitionDuration: `${firstTime ? 0 : duration}ms`,
  70 + height: firstTime?0:$uv.addUnit(lineHeight),
  71 + background: lineColor,
  72 + backgroundSize: lineBgSize,
  73 + }]"
  74 + >
  75 + <!-- #endif -->
  76 + </view>
  77 + </view>
  78 + </scroll-view>
  79 + </view>
  80 + <slot name="right" />
  81 + </view>
  82 + </view>
  83 +</template>
  84 +
  85 +<script>
  86 + import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
  87 + import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
  88 + import uvBadgeProps from '@/uni_modules/uv-badge/components/uv-badge/props.js'
  89 + // #ifdef APP-NVUE
  90 + const animation = uni.requireNativePlugin('animation')
  91 + const dom = uni.requireNativePlugin('dom')
  92 + // #endif
  93 + import props from './props.js';
  94 + /**
  95 + * Tabs 标签
  96 + * @description tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。
  97 + * @tutorial https://www.uvui.cn/components/tabs.html
  98 + * @property {Array} list 标签数组,元素为对象,如[{name: '推荐'}]
  99 + * @property {String | Number} duration 滑块移动一次所需的时间,单位秒(默认 200 )
  100 + * @property {String | Object} activeStyle 菜单选择中时的样式(默认{ color: '#303133' })
  101 + * @property {String | Object} inactiveStyle 菜单非选择中时的样式(默认{ color: '#606266' })
  102 + * @property {String | Number} lineWidth 滑块长度(默认 20)
  103 + * @property {String | Number} lineHeight 滑块高度(默认 3)
  104 + * @property {String} lineColor 滑块颜色(默认:'#3c9cff')
  105 + * @property {String} lineBgSize 滑块背景显示大小,当滑块背景设置为图片时使用(默认 cover)
  106 + * @property {String | Number} itemStyle 菜单item的样式(默认 { height: '44px' })
  107 + * @property {String} scrollable 菜单是否可滚动,选项很少的时候设置为false整个tabs自动居中显示(默认:true)
  108 + * @property {String | Number} current 当前选中标签的索引(默认 0 )
  109 + * @property {String} keyName 从list元素对象中读取的键名(默认 'name' )
  110 + * @property {String | Number} swierWidth swiper的宽度(默认 '750rpx' )
  111 + * @property {String | Object} customStyle 自定义外部样式
  112 + *
  113 + * @event {Function(index)} change 标签改变时触发 index: 点击了第几个tab,索引从0开始
  114 + * @event {Function(index)} click 点击标签时触发 index: 点击了第几个tab,索引从0开始
  115 + * @example <uv-tabs :list="list" :is-scroll="false" :current="current" @change="change"></uv-tabs>
  116 + */
  117 + export default {
  118 + name: 'uv-tabs',
  119 + emits: ['click','change'],
  120 + mixins: [mpMixin, mixin, props],
  121 + data() {
  122 + return {
  123 + firstTime: true,
  124 + scrollLeft: 0,
  125 + scrollViewWidth: 0,
  126 + lineOffsetLeft: 0,
  127 + tabsRect: {
  128 + left: 0
  129 + },
  130 + innerCurrent: 0,
  131 + moving: false,
  132 + }
  133 + },
  134 + watch: {
  135 + current: {
  136 + immediate: true,
  137 + handler (newValue, oldValue) {
  138 + // 内外部值不相等时,才尝试移动滑块
  139 + if (newValue !== this.innerCurrent) {
  140 + this.innerCurrent = newValue
  141 + this.$nextTick(() => {
  142 + this.resize()
  143 + })
  144 + }
  145 + }
  146 + },
  147 + // list变化时,重新渲染list各项信息
  148 + list() {
  149 + this.$nextTick(() => {
  150 + this.resize()
  151 + })
  152 + }
  153 + },
  154 + computed: {
  155 + textStyle() {
  156 + return index => {
  157 + const style = {}
  158 + // 取当期是否激活的样式
  159 + const customeStyle = index == this.innerCurrent ? this.$uv.addStyle(this.activeStyle) : this.$uv
  160 + .addStyle(
  161 + this.inactiveStyle)
  162 + // 如果当前菜单被禁用,则加上对应颜色,需要在此做处理,是因为nvue下,无法在style样式中通过!import覆盖标签的内联样式
  163 + if (this.list[index].disabled) {
  164 + style.color = '#c8c9cc'
  165 + }
  166 + return this.$uv.deepMerge(customeStyle, style)
  167 + }
  168 + },
  169 + propsBadge() {
  170 + return uvBadgeProps
  171 + }
  172 + },
  173 + async mounted() {
  174 + this.init()
  175 + },
  176 + methods: {
  177 + setLineLeft() {
  178 + const tabItem = this.list[this.innerCurrent];
  179 + if (!tabItem) {
  180 + return;
  181 + }
  182 + // 获取滑块该移动的位置
  183 + let lineOffsetLeft = this.list
  184 + .slice(0, this.innerCurrent)
  185 + .reduce((total, curr) => total + curr.rect.width, 0);
  186 + // 获取下划线的数值px表示法
  187 + let lineWidth = this.$uv.getPx(this.lineWidth);
  188 + // 如果传的值未带单位+设置了全局单位,则带上单位计算,这样才没有误差
  189 + if (this.$uv.test.number(this.lineWidth) && this.$uv.unit) {
  190 + lineWidth = this.$uv.getPx(`${this.lineWidth}${this.$uv.unit}`);
  191 + }
  192 + this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2
  193 + // #ifdef APP-NVUE
  194 + // 第一次移动滑块,无需过渡时间
  195 + this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration))
  196 + // #endif
  197 +
  198 + // 如果是第一次执行此方法,让滑块在初始化时,瞬间滑动到第一个tab item的中间
  199 + // 这里需要一个定时器,因为在非nvue下,是直接通过style绑定过渡时间,需要等其过渡完成后,再设置为false(非第一次移动滑块)
  200 + if (this.firstTime) {
  201 + setTimeout(() => {
  202 + this.firstTime = false
  203 + }, 20);
  204 + }
  205 + },
  206 + // nvue下设置滑块的位置
  207 + animation(x, duration = 0) {
  208 + // #ifdef APP-NVUE
  209 + const ref = this.$refs['uv-tabs__wrapper__nav__line']
  210 + animation.transition(ref, {
  211 + styles: {
  212 + transform: `translateX(${x}px)`
  213 + },
  214 + duration
  215 + })
  216 + // #endif
  217 + },
  218 + // 点击某一个标签
  219 + clickHandler(item, index) {
  220 + // 因为标签可能为disabled状态,所以click是一定会发出的,但是change事件是需要可用的状态才发出
  221 + this.$emit('click', {
  222 + ...item,
  223 + index
  224 + })
  225 + // 如果disabled状态,返回
  226 + if (item.disabled) return
  227 + if(this.innerCurrent != index) {
  228 + this.$emit('change', {
  229 + ...item,
  230 + index
  231 + })
  232 + }
  233 + this.innerCurrent = index
  234 + // #ifndef APP-NVUE
  235 + this.$nextTick(()=>{
  236 + this.resize()
  237 + })
  238 + // #endif
  239 + // #ifdef APP-NVUE
  240 + this.$nextTick(()=>{
  241 + // nvue模式下再给点延时,确保万无一失
  242 + this.$uv.sleep(30).then(res=>{
  243 + this.resize()
  244 + });
  245 + })
  246 + // #endif
  247 + },
  248 + init() {
  249 + this.$uv.sleep().then(() => {
  250 + this.resize()
  251 + })
  252 + },
  253 + setScrollLeft() {
  254 + // 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
  255 + const tabRect = this.list[this.innerCurrent]
  256 + // 累加得到当前item到左边的距离
  257 + const offsetLeft = this.list
  258 + .slice(0, this.innerCurrent)
  259 + .reduce((total, curr) => {
  260 + return total + curr.rect.width
  261 + }, 0)
  262 + // 此处为屏幕宽度
  263 + const windowWidth = this.$uv.sys().windowWidth
  264 + // 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动
  265 + let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect
  266 + .right) / 2 + this.tabsRect.left / 2
  267 + // 这里做一个限制,限制scrollLeft的最大值为整个scroll-view宽度减去tabs组件的宽度
  268 + scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width)
  269 + this.scrollLeft = Math.max(0, scrollLeft)
  270 + },
  271 + // 获取所有标签的尺寸
  272 + resize() {
  273 + // 如果不存在list,则不处理
  274 + if(this.list.length === 0) {
  275 + return
  276 + }
  277 + Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => {
  278 + this.tabsRect = tabsRect
  279 + this.scrollViewWidth = 0
  280 + itemRect.map((item, index) => {
  281 + // 计算scroll-view的宽度,这里
  282 + this.scrollViewWidth += item.width
  283 + // 另外计算每一个item的中心点X轴坐标
  284 + this.list[index].rect = item
  285 + })
  286 + // 获取了tabs的尺寸之后,设置滑块的位置
  287 + this.setLineLeft()
  288 + this.setScrollLeft()
  289 + })
  290 + },
  291 + // 获取导航菜单的尺寸
  292 + getTabsRect() {
  293 + return new Promise(resolve => {
  294 + this.queryRect('uv-tabs__wrapper__scroll-view').then(size => resolve(size))
  295 + })
  296 + },
  297 + // 获取所有标签的尺寸
  298 + getAllItemRect() {
  299 + return new Promise(resolve => {
  300 + const promiseAllArr = this.list.map((item, index) => this.queryRect(
  301 + `uv-tabs__wrapper__nav__item-${index}`, true))
  302 + Promise.all(promiseAllArr).then(sizes => resolve(sizes))
  303 + })
  304 + },
  305 + // 获取各个标签的尺寸
  306 + queryRect(el, item) {
  307 + // #ifndef APP-NVUE
  308 + // $uvGetRect为uni-ui自带的节点查询简化方法,详见文档介绍:https://www.uvui.cn/js/getRect.html
  309 + // 组件内部一般用this.$uvGetRect,对外的为getRect,二者功能一致,名称不同
  310 + return new Promise(resolve => {
  311 + this.$uvGetRect(`.${el}`).then(size => {
  312 + resolve(size)
  313 + })
  314 + })
  315 + // #endif
  316 +
  317 + // #ifdef APP-NVUE
  318 + // nvue下,使用dom模块查询元素高度
  319 + // 返回一个promise,让调用此方法的主体能使用then回调
  320 + return new Promise(resolve => {
  321 + dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => {
  322 + resolve(res.size)
  323 + })
  324 + })
  325 + // #endif
  326 + },
  327 + },
  328 + }
  329 +</script>
  330 +<style lang="scss" scoped>
  331 + @import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
  332 + @import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
  333 + .uv-tabs {
  334 +
  335 + &__wrapper {
  336 + @include flex;
  337 + align-items: center;
  338 +
  339 + &__scroll-view-wrapper {
  340 + flex: 1;
  341 + /* #ifndef APP-NVUE */
  342 + overflow: auto hidden;
  343 + /* #endif */
  344 + }
  345 +
  346 + &__scroll-view {
  347 + @include flex;
  348 + flex: 1;
  349 + }
  350 +
  351 + &__nav {
  352 + @include flex;
  353 + position: relative;
  354 +
  355 + &__item {
  356 + padding: 0 11px;
  357 + @include flex;
  358 + align-items: center;
  359 + justify-content: center;
  360 +
  361 + &--disabled {
  362 + /* #ifndef APP-NVUE */
  363 + cursor: not-allowed;
  364 + /* #endif */
  365 + }
  366 +
  367 + &__text {
  368 + font-size: 15px;
  369 + color: $uv-content-color;
  370 +
  371 + &--disabled {
  372 + color: $uv-disabled-color !important;
  373 + }
  374 + }
  375 + }
  376 +
  377 + &__line {
  378 + height: 3px;
  379 + background: $uv-primary;
  380 + width: 30px;
  381 + position: absolute;
  382 + bottom: 2px;
  383 + border-radius: 100px;
  384 + transition-property: transform;
  385 + transition-duration: 300ms;
  386 + }
  387 + }
  388 + }
  389 + }
  390 +</style>
... ...
uni_modules/uv-tabs/package.json 0 → 100644
  1 +{
  2 + "id": "uv-tabs",
  3 + "displayName": "uv-tabs 标签选项卡 全面兼容vue3+2、app、h5、小程序等多端",
  4 + "version": "1.0.9",
  5 + "description": "标签选项卡组件,是一个tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。",
  6 + "keywords": [
  7 + "选项卡",
  8 + "uvui",
  9 + "uv-ui",
  10 + "tab",
  11 + "标签"
  12 +],
  13 + "repository": "",
  14 + "engines": {
  15 + "HBuilderX": "^3.1.0"
  16 + },
  17 + "dcloudext": {
  18 + "type": "component-vue",
  19 + "sale": {
  20 + "regular": {
  21 + "price": "0.00"
  22 + },
  23 + "sourcecode": {
  24 + "price": "0.00"
  25 + }
  26 + },
  27 + "contact": {
  28 + "qq": ""
  29 + },
  30 + "declaration": {
  31 + "ads": "无",
  32 + "data": "插件不采集任何数据",
  33 + "permissions": "无"
  34 + },
  35 + "npmurl": ""
  36 + },
  37 + "uni_modules": {
  38 + "dependencies": [
  39 + "uv-ui-tools",
  40 + "uv-badge",
  41 + "uv-sticky",
  42 + "uv-icon"
  43 + ],
  44 + "encrypt": [],
  45 + "platforms": {
  46 + "cloud": {
  47 + "tcb": "y",
  48 + "aliyun": "y"
  49 + },
  50 + "client": {
  51 + "Vue": {
  52 + "vue2": "y",
  53 + "vue3": "y"
  54 + },
  55 + "App": {
  56 + "app-vue": "y",
  57 + "app-nvue": "y"
  58 + },
  59 + "H5-mobile": {
  60 + "Safari": "y",
  61 + "Android Browser": "y",
  62 + "微信浏览器(Android)": "y",
  63 + "QQ浏览器(Android)": "y"
  64 + },
  65 + "H5-pc": {
  66 + "Chrome": "y",
  67 + "IE": "y",
  68 + "Edge": "y",
  69 + "Firefox": "y",
  70 + "Safari": "y"
  71 + },
  72 + "小程序": {
  73 + "微信": "y",
  74 + "阿里": "y",
  75 + "百度": "y",
  76 + "字节跳动": "y",
  77 + "QQ": "y",
  78 + "钉钉": "u",
  79 + "快手": "u",
  80 + "飞书": "u",
  81 + "京东": "u"
  82 + },
  83 + "快应用": {
  84 + "华为": "u",
  85 + "联盟": "u"
  86 + }
  87 + }
  88 + }
  89 + }
  90 +}
0 91 \ No newline at end of file
... ...
uni_modules/uv-tabs/readme.md 0 → 100644
  1 +## Tabs 标签选项卡
  2 +
  3 +> **组件名:uv-tabs**
  4 +
  5 +标签选项卡组件,是一个`tabs`标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的`tab`会自动移动到组件的中间位置。
  6 +
  7 +# <a href="https://www.uvui.cn/components/tabs.html" target="_blank">查看文档</a>
  8 +
  9 +## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
  10 +
  11 +### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  12 +
  13 +<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
  14 +
  15 +![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
  16 +
  17 +</a>
  18 +
  19 +#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
0 20 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/changelog.md 0 → 100644
  1 +## 1.1.25(2024-01-20)
  2 +1.1.20版本更新
  3 +## 1.1.24(2023-12-21)
  4 +1. luch-request更新
  5 +## 1.1.23(2023-12-12)
  6 +1. 1.1.19版本
  7 +## 1.1.22(2023-11-28)
  8 +1. 优化
  9 +## 1.1.21(2023-11-10)
  10 +1. 1.1.17版本
  11 +## 1.1.20(2023-10-30)
  12 +1. 1.1.16版本
  13 +## 1.1.19(2023-10-13)
  14 +1. 兼容vue3
  15 +## 1.1.18(2023-10-12)
  16 +1. 1.1.15版本
  17 +## 1.1.17(2023-09-27)
  18 +1. 1.1.14版本发布
  19 +## 1.1.16(2023-09-15)
  20 +1. 1.1.13版本发布
  21 +## 1.1.15(2023-09-15)
  22 +1. 更新button.js相关按钮支持open-type="agreePrivacyAuthorization"
  23 +## 1.1.14(2023-09-14)
  24 +1. 优化dayjs
  25 +## 1.1.13(2023-09-13)
  26 +1. 优化,$uv中增加unit参数,方便组件中使用
  27 +## 1.1.12(2023-09-10)
  28 +1. 升级版本
  29 +## 1.1.11(2023-09-04)
  30 +1. 1.1.11版本
  31 +## 1.1.10(2023-08-31)
  32 +1. 修复customStyle和customClass存在冲突的问题
  33 +## 1.1.9(2023-08-27)
  34 +1. 版本升级
  35 +2. 优化
  36 +## 1.1.8(2023-08-24)
  37 +1. 版本升级
  38 +## 1.1.7(2023-08-22)
  39 +1. 版本升级
  40 +## 1.1.6(2023-08-18)
  41 +uvui版本:1.1.6
  42 +## 1.0.15(2023-08-14)
  43 +1. 更新uvui版本号
  44 +## 1.0.13(2023-08-06)
  45 +1. 优化
  46 +## 1.0.12(2023-08-06)
  47 +1. 修改版本号
  48 +## 1.0.11(2023-08-06)
  49 +1. 路由增加events参数
  50 +2. 路由拦截修复
  51 +## 1.0.10(2023-08-01)
  52 +1. 优化
  53 +## 1.0.9(2023-06-28)
  54 +优化openType.js
  55 +## 1.0.8(2023-06-15)
  56 +1. 修改支付宝报错的BUG
  57 +## 1.0.7(2023-06-07)
  58 +1. 解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
  59 +2. 解决上述提示,需要在uni.scss配置$uvui-nvue-style: false; 然后在APP.vue下面引入uvui内置的基础样式:@import '@/uni_modules/uv-ui-tools/index.scss';
  60 +## 1.0.6(2023-06-04)
  61 +1. uv-ui-tools 优化工具组件,兼容更多功能
  62 +2. 小程序分享功能优化等
  63 +## 1.0.5(2023-06-02)
  64 +1. 修改扩展使用mixin中方法的问题
  65 +## 1.0.4(2023-05-23)
  66 +1. 兼容百度小程序修改bem函数
  67 +## 1.0.3(2023-05-16)
  68 +1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
  69 +2. 优化部分功能
  70 +## 1.0.2(2023-05-10)
  71 +1. 增加Http请求封装
  72 +2. 优化
  73 +## 1.0.1(2023-05-04)
  74 +1. 修改名称及备注
  75 +## 1.0.0(2023-05-04)
  76 +1. uv-ui工具集首次发布
... ...
uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue 0 → 100644
  1 +<template>
  2 +</template>
  3 +<script>
  4 +</script>
  5 +<style>
  6 +</style>
... ...
uni_modules/uv-ui-tools/index.js 0 → 100644
  1 +// 全局挂载引入http相关请求拦截插件
  2 +import Request from './libs/luch-request'
  3 +
  4 +// 引入全局mixin
  5 +import mixin from './libs/mixin/mixin.js'
  6 +// 小程序特有的mixin
  7 +import mpMixin from './libs/mixin/mpMixin.js'
  8 +// #ifdef MP
  9 +import mpShare from './libs/mixin/mpShare.js'
  10 +// #endif
  11 +
  12 +// 路由封装
  13 +import route from './libs/util/route.js'
  14 +// 公共工具函数
  15 +import * as index from './libs/function/index.js'
  16 +// 防抖方法
  17 +import debounce from './libs/function/debounce.js'
  18 +// 节流方法
  19 +import throttle from './libs/function/throttle.js'
  20 +// 规则检验
  21 +import * as test from './libs/function/test.js'
  22 +
  23 +// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
  24 +import * as colorGradient from './libs/function/colorGradient.js'
  25 +
  26 +// 配置信息
  27 +import config from './libs/config/config.js'
  28 +// 平台
  29 +import platform from './libs/function/platform'
  30 +
  31 +const $uv = {
  32 + route,
  33 + config,
  34 + test,
  35 + date: index.timeFormat, // 另名date
  36 + ...index,
  37 + colorGradient: colorGradient.colorGradient,
  38 + hexToRgb: colorGradient.hexToRgb,
  39 + rgbToHex: colorGradient.rgbToHex,
  40 + colorToRgba: colorGradient.colorToRgba,
  41 + http: new Request(),
  42 + debounce,
  43 + throttle,
  44 + platform,
  45 + mixin,
  46 + mpMixin
  47 +}
  48 +uni.$uv = $uv;
  49 +const install = (Vue,options={}) => {
  50 + // #ifndef APP-NVUE
  51 + const cloneMixin = index.deepClone(mixin);
  52 + delete cloneMixin?.props?.customClass;
  53 + delete cloneMixin?.props?.customStyle;
  54 + Vue.mixin(cloneMixin);
  55 + // #ifdef MP
  56 + if(options.mpShare){
  57 + Vue.mixin(mpShare);
  58 + }
  59 + // #endif
  60 + // #endif
  61 + // #ifdef VUE2
  62 + // 时间格式化,同时两个名称,date和timeFormat
  63 + Vue.filter('timeFormat', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
  64 + Vue.filter('date', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
  65 + // 将多久以前的方法,注入到全局过滤器
  66 + Vue.filter('timeFrom', (timestamp, format) => uni.$uv.timeFrom(timestamp, format));
  67 + // 同时挂载到uni和Vue.prototype中
  68 + // #ifndef APP-NVUE
  69 + // 只有vue,挂载到Vue.prototype才有意义,因为nvue中全局Vue.prototype和Vue.mixin是无效的
  70 + Vue.prototype.$uv = $uv;
  71 + // #endif
  72 + // #endif
  73 + // #ifdef VUE3
  74 + Vue.config.globalProperties.$uv = $uv;
  75 + // #endif
  76 +}
  77 +export default {
  78 + install
  79 +}
0 80 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/index.scss 0 → 100644
  1 +// 引入公共基础类
  2 +@import "./libs/css/common.scss";
  3 +
  4 +// 非nvue的样式
  5 +/* #ifndef APP-NVUE */
  6 +@import "./libs/css/vue.scss";
  7 +/* #endif */
0 8 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/libs/config/config.js 0 → 100644
  1 +// 此版本发布于2024-01-20
  2 +const version = '1.1.20'
  3 +
  4 +// 开发环境才提示,生产环境不会提示
  5 +if (process.env.NODE_ENV === 'development') {
  6 + console.log(`\n %c uvui V${version} https://www.uvui.cn/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;');
  7 +}
  8 +
  9 +export default {
  10 + v: version,
  11 + version,
  12 + // 主题名称
  13 + type: [
  14 + 'primary',
  15 + 'success',
  16 + 'info',
  17 + 'error',
  18 + 'warning'
  19 + ],
  20 + // 颜色部分,本来可以通过scss的:export导出供js使用,但是奈何nvue不支持
  21 + color: {
  22 + 'uv-primary': '#2979ff',
  23 + 'uv-warning': '#ff9900',
  24 + 'uv-success': '#19be6b',
  25 + 'uv-error': '#fa3534',
  26 + 'uv-info': '#909399',
  27 + 'uv-main-color': '#303133',
  28 + 'uv-content-color': '#606266',
  29 + 'uv-tips-color': '#909399',
  30 + 'uv-light-color': '#c0c4cc'
  31 + },
  32 + // 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
  33 + unit: 'px'
  34 +}
... ...
uni_modules/uv-ui-tools/libs/css/color.scss 0 → 100644
  1 +$uv-main-color: #303133 !default;
  2 +$uv-content-color: #606266 !default;
  3 +$uv-tips-color: #909193 !default;
  4 +$uv-light-color: #c0c4cc !default;
  5 +$uv-border-color: #dadbde !default;
  6 +$uv-bg-color: #f3f4f6 !default;
  7 +$uv-disabled-color: #c8c9cc !default;
  8 +
  9 +$uv-primary: #3c9cff !default;
  10 +$uv-primary-dark: #398ade !default;
  11 +$uv-primary-disabled: #9acafc !default;
  12 +$uv-primary-light: #ecf5ff !default;
  13 +
  14 +$uv-warning: #f9ae3d !default;
  15 +$uv-warning-dark: #f1a532 !default;
  16 +$uv-warning-disabled: #f9d39b !default;
  17 +$uv-warning-light: #fdf6ec !default;
  18 +
  19 +$uv-success: #5ac725 !default;
  20 +$uv-success-dark: #53c21d !default;
  21 +$uv-success-disabled: #a9e08f !default;
  22 +$uv-success-light: #f5fff0;
  23 +
  24 +$uv-error: #f56c6c !default;
  25 +$uv-error-dark: #e45656 !default;
  26 +$uv-error-disabled: #f7b2b2 !default;
  27 +$uv-error-light: #fef0f0 !default;
  28 +
  29 +$uv-info: #909399 !default;
  30 +$uv-info-dark: #767a82 !default;
  31 +$uv-info-disabled: #c4c6c9 !default;
  32 +$uv-info-light: #f4f4f5 !default;
... ...
uni_modules/uv-ui-tools/libs/css/common.scss 0 → 100644
  1 +// 超出行数,自动显示行尾省略号,最多5行
  2 +// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
  3 +@for $i from 1 through 5 {
  4 + .uv-line-#{$i} {
  5 + /* #ifdef APP-NVUE */
  6 + // nvue下,可以直接使用lines属性,这是weex特有样式
  7 + lines: $i;
  8 + text-overflow: ellipsis;
  9 + overflow: hidden;
  10 + flex: 1;
  11 + /* #endif */
  12 +
  13 + /* #ifndef APP-NVUE */
  14 + // vue下,单行和多行显示省略号需要单独处理
  15 + @if $i == '1' {
  16 + overflow: hidden;
  17 + white-space: nowrap;
  18 + text-overflow: ellipsis;
  19 + } @else {
  20 + display: -webkit-box!important;
  21 + overflow: hidden;
  22 + text-overflow: ellipsis;
  23 + word-break: break-all;
  24 + -webkit-line-clamp: $i;
  25 + -webkit-box-orient: vertical!important;
  26 + }
  27 + /* #endif */
  28 + }
  29 +}
  30 +$uv-bordercolor: #dadbde;
  31 +@if variable-exists(uv-border-color) {
  32 + $uv-bordercolor: $uv-border-color;
  33 +}
  34 +
  35 +// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
  36 +// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
  37 +// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
  38 +// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
  39 +.uv-border {
  40 + border-width: 0.5px!important;
  41 + border-color: $uv-bordercolor!important;
  42 + border-style: solid;
  43 +}
  44 +
  45 +.uv-border-top {
  46 + border-top-width: 0.5px!important;
  47 + border-color: $uv-bordercolor!important;
  48 + border-top-style: solid;
  49 +}
  50 +
  51 +.uv-border-left {
  52 + border-left-width: 0.5px!important;
  53 + border-color: $uv-bordercolor!important;
  54 + border-left-style: solid;
  55 +}
  56 +
  57 +.uv-border-right {
  58 + border-right-width: 0.5px!important;
  59 + border-color: $uv-bordercolor!important;
  60 + border-right-style: solid;
  61 +}
  62 +
  63 +.uv-border-bottom {
  64 + border-bottom-width: 0.5px!important;
  65 + border-color: $uv-bordercolor!important;
  66 + border-bottom-style: solid;
  67 +}
  68 +
  69 +.uv-border-top-bottom {
  70 + border-top-width: 0.5px!important;
  71 + border-bottom-width: 0.5px!important;
  72 + border-color: $uv-bordercolor!important;
  73 + border-top-style: solid;
  74 + border-bottom-style: solid;
  75 +}
  76 +
  77 +// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
  78 +.uv-reset-button {
  79 + padding: 0;
  80 + background-color: transparent;
  81 + /* #ifndef APP-PLUS */
  82 + font-size: inherit;
  83 + line-height: inherit;
  84 + color: inherit;
  85 + /* #endif */
  86 + /* #ifdef APP-NVUE */
  87 + border-width: 0;
  88 + /* #endif */
  89 +}
  90 +
  91 +/* #ifndef APP-NVUE */
  92 +.uv-reset-button::after {
  93 + border: none;
  94 +}
  95 +/* #endif */
  96 +
  97 +.uv-hover-class {
  98 + opacity: 0.7;
  99 +}
  100 +
... ...
uni_modules/uv-ui-tools/libs/css/components.scss 0 → 100644
  1 +@mixin flex($direction: row) {
  2 + /* #ifndef APP-NVUE */
  3 + display: flex;
  4 + /* #endif */
  5 + flex-direction: $direction;
  6 +}
  7 +
  8 +/* #ifndef APP-NVUE */
  9 +// 由于uvui是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
  10 +// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
  11 +$uvui-nvue-style: true !default;
  12 +@if $uvui-nvue-style == true {
  13 + view, scroll-view, swiper-item {
  14 + display: flex;
  15 + flex-direction: column;
  16 + flex-shrink: 0;
  17 + flex-grow: 0;
  18 + flex-basis: auto;
  19 + align-items: stretch;
  20 + align-content: flex-start;
  21 + }
  22 +}
  23 +/* #endif */
... ...
uni_modules/uv-ui-tools/libs/css/variable.scss 0 → 100644
  1 +// 超出行数,自动显示行尾省略号,最多5行
  2 +// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
  3 +@if variable-exists(show-lines) {
  4 + @for $i from 1 through 5 {
  5 + .uv-line-#{$i} {
  6 + /* #ifdef APP-NVUE */
  7 + // nvue下,可以直接使用lines属性,这是weex特有样式
  8 + lines: $i;
  9 + text-overflow: ellipsis;
  10 + overflow: hidden;
  11 + flex: 1;
  12 + /* #endif */
  13 +
  14 + /* #ifndef APP-NVUE */
  15 + // vue下,单行和多行显示省略号需要单独处理
  16 + @if $i == '1' {
  17 + overflow: hidden;
  18 + white-space: nowrap;
  19 + text-overflow: ellipsis;
  20 + } @else {
  21 + display: -webkit-box!important;
  22 + overflow: hidden;
  23 + text-overflow: ellipsis;
  24 + word-break: break-all;
  25 + -webkit-line-clamp: $i;
  26 + -webkit-box-orient: vertical!important;
  27 + }
  28 + /* #endif */
  29 + }
  30 + }
  31 +}
  32 +@if variable-exists(show-border) {
  33 + $uv-bordercolor: #dadbde;
  34 + @if variable-exists(uv-border-color) {
  35 + $uv-bordercolor: $uv-border-color;
  36 + }
  37 + // 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
  38 + // App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
  39 + // 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
  40 + // 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
  41 + @if variable-exists(show-border-surround) {
  42 + .uv-border {
  43 + border-width: 0.5px!important;
  44 + border-color: $uv-bordercolor!important;
  45 + border-style: solid;
  46 + }
  47 + }
  48 + @if variable-exists(show-border-top) {
  49 + .uv-border-top {
  50 + border-top-width: 0.5px!important;
  51 + border-color: $uv-bordercolor!important;
  52 + border-top-style: solid;
  53 + }
  54 + }
  55 + @if variable-exists(show-border-left) {
  56 + .uv-border-left {
  57 + border-left-width: 0.5px!important;
  58 + border-color: $uv-bordercolor!important;
  59 + border-left-style: solid;
  60 + }
  61 + }
  62 + @if variable-exists(show-border-right) {
  63 + .uv-border-right {
  64 + border-right-width: 0.5px!important;
  65 + border-color: $uv-bordercolor!important;
  66 + border-right-style: solid;
  67 + }
  68 + }
  69 + @if variable-exists(show-border-bottom) {
  70 + .uv-border-bottom {
  71 + border-bottom-width: 0.5px!important;
  72 + border-color: $uv-bordercolor!important;
  73 + border-bottom-style: solid;
  74 + }
  75 + }
  76 + @if variable-exists(show-border-top-bottom) {
  77 + .uv-border-top-bottom {
  78 + border-top-width: 0.5px!important;
  79 + border-bottom-width: 0.5px!important;
  80 + border-color: $uv-bordercolor!important;
  81 + border-top-style: solid;
  82 + border-bottom-style: solid;
  83 + }
  84 + }
  85 +}
  86 +@if variable-exists(show-reset-button) {
  87 + // 去除button的所有默认样式,让其表现跟普通的view、text元素一样
  88 + .uv-reset-button {
  89 + padding: 0;
  90 + background-color: transparent;
  91 + /* #ifndef APP-PLUS */
  92 + font-size: inherit;
  93 + line-height: inherit;
  94 + color: inherit;
  95 + /* #endif */
  96 + /* #ifdef APP-NVUE */
  97 + border-width: 0;
  98 + /* #endif */
  99 + }
  100 +
  101 + /* #ifndef APP-NVUE */
  102 + .uv-reset-button::after {
  103 + border: none;
  104 + }
  105 + /* #endif */
  106 +}
  107 +@if variable-exists(show-hover) {
  108 + .uv-hover-class {
  109 + opacity: 0.7;
  110 + }
  111 +}
... ...
uni_modules/uv-ui-tools/libs/css/vue.scss 0 → 100644
  1 +// 历遍生成4个方向的底部安全区
  2 +@each $d in top, right, bottom, left {
  3 + .uv-safe-area-inset-#{$d} {
  4 + padding-#{$d}: 0;
  5 + padding-#{$d}: constant(safe-area-inset-#{$d});
  6 + padding-#{$d}: env(safe-area-inset-#{$d});
  7 + }
  8 +}
  9 +
  10 +//提升H5端uni.toast()的层级,避免被uvui的modal等遮盖
  11 +/* #ifdef H5 */
  12 +uni-toast {
  13 + z-index: 10090;
  14 +}
  15 +uni-toast .uni-toast {
  16 + z-index: 10090;
  17 +}
  18 +/* #endif */
  19 +
  20 +// 隐藏scroll-view的滚动条
  21 +::-webkit-scrollbar {
  22 + display: none;
  23 + width: 0 !important;
  24 + height: 0 !important;
  25 + -webkit-appearance: none;
  26 + background: transparent;
  27 +}
  28 +
  29 +$uvui-nvue-style: true !default;
  30 +@if $uvui-nvue-style == false {
  31 + view, scroll-view, swiper-item {
  32 + display: flex;
  33 + flex-direction: column;
  34 + flex-shrink: 0;
  35 + flex-grow: 0;
  36 + flex-basis: auto;
  37 + align-items: stretch;
  38 + align-content: flex-start;
  39 + }
  40 +}
... ...
uni_modules/uv-ui-tools/libs/function/colorGradient.js 0 → 100644
  1 +/**
  2 + * 求两个颜色之间的渐变值
  3 + * @param {string} startColor 开始的颜色
  4 + * @param {string} endColor 结束的颜色
  5 + * @param {number} step 颜色等分的份额
  6 + * */
  7 +function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
  8 + const startRGB = hexToRgb(startColor, false) // 转换为rgb数组模式
  9 + const startR = startRGB[0]
  10 + const startG = startRGB[1]
  11 + const startB = startRGB[2]
  12 +
  13 + const endRGB = hexToRgb(endColor, false)
  14 + const endR = endRGB[0]
  15 + const endG = endRGB[1]
  16 + const endB = endRGB[2]
  17 +
  18 + const sR = (endR - startR) / step // 总差值
  19 + const sG = (endG - startG) / step
  20 + const sB = (endB - startB) / step
  21 + const colorArr = []
  22 + for (let i = 0; i < step; i++) {
  23 + // 计算每一步的hex值
  24 + let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
  25 + * i + startB))})`)
  26 + // 确保第一个颜色值为startColor的值
  27 + if (i === 0) hex = rgbToHex(startColor)
  28 + // 确保最后一个颜色值为endColor的值
  29 + if (i === step - 1) hex = rgbToHex(endColor)
  30 + colorArr.push(hex)
  31 + }
  32 + return colorArr
  33 +}
  34 +
  35 +// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
  36 +function hexToRgb(sColor, str = true) {
  37 + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
  38 + sColor = String(sColor).toLowerCase()
  39 + if (sColor && reg.test(sColor)) {
  40 + if (sColor.length === 4) {
  41 + let sColorNew = '#'
  42 + for (let i = 1; i < 4; i += 1) {
  43 + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
  44 + }
  45 + sColor = sColorNew
  46 + }
  47 + // 处理六位的颜色值
  48 + const sColorChange = []
  49 + for (let i = 1; i < 7; i += 2) {
  50 + sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
  51 + }
  52 + if (!str) {
  53 + return sColorChange
  54 + }
  55 + return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
  56 + } if (/^(rgb|RGB)/.test(sColor)) {
  57 + const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
  58 + return arr.map((val) => Number(val))
  59 + }
  60 + return sColor
  61 +}
  62 +
  63 +// 将rgb表示方式转换为hex表示方式
  64 +function rgbToHex(rgb) {
  65 + const _this = rgb
  66 + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
  67 + if (/^(rgb|RGB)/.test(_this)) {
  68 + const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
  69 + let strHex = '#'
  70 + for (let i = 0; i < aColor.length; i++) {
  71 + let hex = Number(aColor[i]).toString(16)
  72 + hex = String(hex).length == 1 ? `${0}${hex}` : hex // 保证每个rgb的值为2位
  73 + if (hex === '0') {
  74 + hex += hex
  75 + }
  76 + strHex += hex
  77 + }
  78 + if (strHex.length !== 7) {
  79 + strHex = _this
  80 + }
  81 + return strHex
  82 + } if (reg.test(_this)) {
  83 + const aNum = _this.replace(/#/, '').split('')
  84 + if (aNum.length === 6) {
  85 + return _this
  86 + } if (aNum.length === 3) {
  87 + let numHex = '#'
  88 + for (let i = 0; i < aNum.length; i += 1) {
  89 + numHex += (aNum[i] + aNum[i])
  90 + }
  91 + return numHex
  92 + }
  93 + } else {
  94 + return _this
  95 + }
  96 +}
  97 +
  98 +/**
  99 +* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
  100 +* sHex为传入的十六进制的色值
  101 +* alpha为rgba的透明度
  102 +*/
  103 +function colorToRgba(color, alpha) {
  104 + color = rgbToHex(color)
  105 + // 十六进制颜色值的正则表达式
  106 + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
  107 + /* 16进制颜色转为RGB格式 */
  108 + let sColor = String(color).toLowerCase()
  109 + if (sColor && reg.test(sColor)) {
  110 + if (sColor.length === 4) {
  111 + let sColorNew = '#'
  112 + for (let i = 1; i < 4; i += 1) {
  113 + sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
  114 + }
  115 + sColor = sColorNew
  116 + }
  117 + // 处理六位的颜色值
  118 + const sColorChange = []
  119 + for (let i = 1; i < 7; i += 2) {
  120 + sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
  121 + }
  122 + // return sColorChange.join(',')
  123 + return `rgba(${sColorChange.join(',')},${alpha})`
  124 + }
  125 +
  126 + return sColor
  127 +}
  128 +
  129 +export {
  130 + colorGradient,
  131 + hexToRgb,
  132 + rgbToHex,
  133 + colorToRgba
  134 +}
... ...
uni_modules/uv-ui-tools/libs/function/debounce.js 0 → 100644
  1 +let timeout = null
  2 +
  3 +/**
  4 + * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
  5 + *
  6 + * @param {Function} func 要执行的回调函数
  7 + * @param {Number} wait 延时的时间
  8 + * @param {Boolean} immediate 是否立即执行
  9 + * @return null
  10 + */
  11 +function debounce(func, wait = 500, immediate = false) {
  12 + // 清除定时器
  13 + if (timeout !== null) clearTimeout(timeout)
  14 + // 立即执行,此类情况一般用不到
  15 + if (immediate) {
  16 + const callNow = !timeout
  17 + timeout = setTimeout(() => {
  18 + timeout = null
  19 + }, wait)
  20 + if (callNow) typeof func === 'function' && func()
  21 + } else {
  22 + // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
  23 + timeout = setTimeout(() => {
  24 + typeof func === 'function' && func()
  25 + }, wait)
  26 + }
  27 +}
  28 +
  29 +export default debounce
... ...
uni_modules/uv-ui-tools/libs/function/digit.js 0 → 100644
  1 +let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
  2 +
  3 +/**
  4 + * 把错误的数据转正
  5 + * @private
  6 + * @example strip(0.09999999999999998)=0.1
  7 + */
  8 +function strip(num, precision = 15) {
  9 + return +parseFloat(Number(num).toPrecision(precision));
  10 +}
  11 +
  12 +/**
  13 + * Return digits length of a number
  14 + * @private
  15 + * @param {*number} num Input number
  16 + */
  17 +function digitLength(num) {
  18 + // Get digit length of e
  19 + const eSplit = num.toString().split(/[eE]/);
  20 + const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
  21 + return len > 0 ? len : 0;
  22 +}
  23 +
  24 +/**
  25 + * 把小数转成整数,如果是小数则放大成整数
  26 + * @private
  27 + * @param {*number} num 输入数
  28 + */
  29 +function float2Fixed(num) {
  30 + if (num.toString().indexOf('e') === -1) {
  31 + return Number(num.toString().replace('.', ''));
  32 + }
  33 + const dLen = digitLength(num);
  34 + return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
  35 +}
  36 +
  37 +/**
  38 + * 检测数字是否越界,如果越界给出提示
  39 + * @private
  40 + * @param {*number} num 输入数
  41 + */
  42 +function checkBoundary(num) {
  43 + if (_boundaryCheckingState) {
  44 + if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
  45 + console.warn(`${num} 超出了精度限制,结果可能不正确`);
  46 + }
  47 + }
  48 +}
  49 +
  50 +/**
  51 + * 把递归操作扁平迭代化
  52 + * @param {number[]} arr 要操作的数字数组
  53 + * @param {function} operation 迭代操作
  54 + * @private
  55 + */
  56 +function iteratorOperation(arr, operation) {
  57 + const [num1, num2, ...others] = arr;
  58 + let res = operation(num1, num2);
  59 +
  60 + others.forEach((num) => {
  61 + res = operation(res, num);
  62 + });
  63 +
  64 + return res;
  65 +}
  66 +
  67 +/**
  68 + * 高精度乘法
  69 + * @export
  70 + */
  71 +export function times(...nums) {
  72 + if (nums.length > 2) {
  73 + return iteratorOperation(nums, times);
  74 + }
  75 +
  76 + const [num1, num2] = nums;
  77 + const num1Changed = float2Fixed(num1);
  78 + const num2Changed = float2Fixed(num2);
  79 + const baseNum = digitLength(num1) + digitLength(num2);
  80 + const leftValue = num1Changed * num2Changed;
  81 +
  82 + checkBoundary(leftValue);
  83 +
  84 + return leftValue / Math.pow(10, baseNum);
  85 +}
  86 +
  87 +/**
  88 + * 高精度加法
  89 + * @export
  90 + */
  91 +export function plus(...nums) {
  92 + if (nums.length > 2) {
  93 + return iteratorOperation(nums, plus);
  94 + }
  95 +
  96 + const [num1, num2] = nums;
  97 + // 取最大的小数位
  98 + const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  99 + // 把小数都转为整数然后再计算
  100 + return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
  101 +}
  102 +
  103 +/**
  104 + * 高精度减法
  105 + * @export
  106 + */
  107 +export function minus(...nums) {
  108 + if (nums.length > 2) {
  109 + return iteratorOperation(nums, minus);
  110 + }
  111 +
  112 + const [num1, num2] = nums;
  113 + const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  114 + return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
  115 +}
  116 +
  117 +/**
  118 + * 高精度除法
  119 + * @export
  120 + */
  121 +export function divide(...nums) {
  122 + if (nums.length > 2) {
  123 + return iteratorOperation(nums, divide);
  124 + }
  125 +
  126 + const [num1, num2] = nums;
  127 + const num1Changed = float2Fixed(num1);
  128 + const num2Changed = float2Fixed(num2);
  129 + checkBoundary(num1Changed);
  130 + checkBoundary(num2Changed);
  131 + // 重要,这里必须用strip进行修正
  132 + return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
  133 +}
  134 +
  135 +/**
  136 + * 四舍五入
  137 + * @export
  138 + */
  139 +export function round(num, ratio) {
  140 + const base = Math.pow(10, ratio);
  141 + let result = divide(Math.round(Math.abs(times(num, base))), base);
  142 + if (num < 0 && result !== 0) {
  143 + result = times(result, -1);
  144 + }
  145 + // 位数不足则补0
  146 + return result;
  147 +}
  148 +
  149 +/**
  150 + * 是否进行边界检查,默认开启
  151 + * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
  152 + * @export
  153 + */
  154 +export function enableBoundaryChecking(flag = true) {
  155 + _boundaryCheckingState = flag;
  156 +}
  157 +
  158 +
  159 +export default {
  160 + times,
  161 + plus,
  162 + minus,
  163 + divide,
  164 + round,
  165 + enableBoundaryChecking,
  166 +};
  167 +
... ...
uni_modules/uv-ui-tools/libs/function/index.js 0 → 100644
  1 +import { number, empty } from './test.js'
  2 +import { round } from './digit.js'
  3 +/**
  4 + * @description 如果value小于min,取min;如果value大于max,取max
  5 + * @param {number} min
  6 + * @param {number} max
  7 + * @param {number} value
  8 + */
  9 +function range(min = 0, max = 0, value = 0) {
  10 + return Math.max(min, Math.min(max, Number(value)))
  11 +}
  12 +
  13 +/**
  14 + * @description 用于获取用户传递值的px值 如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
  15 + * @param {number|string} value 用户传递值的px值
  16 + * @param {boolean} unit
  17 + * @returns {number|string}
  18 + */
  19 +function getPx(value, unit = false) {
  20 + if (number(value)) {
  21 + return unit ? `${value}px` : Number(value)
  22 + }
  23 + // 如果带有rpx,先取出其数值部分,再转为px值
  24 + if (/(rpx|upx)$/.test(value)) {
  25 + return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)))
  26 + }
  27 + return unit ? `${parseInt(value)}px` : parseInt(value)
  28 +}
  29 +
  30 +/**
  31 + * @description 进行延时,以达到可以简写代码的目的 比如: await uni.$uv.sleep(20)将会阻塞20ms
  32 + * @param {number} value 堵塞时间 单位ms 毫秒
  33 + * @returns {Promise} 返回promise
  34 + */
  35 +function sleep(value = 30) {
  36 + return new Promise((resolve) => {
  37 + setTimeout(() => {
  38 + resolve()
  39 + }, value)
  40 + })
  41 +}
  42 +/**
  43 + * @description 运行期判断平台
  44 + * @returns {string} 返回所在平台(小写)
  45 + * @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
  46 + */
  47 +function os() {
  48 + return uni.getSystemInfoSync().platform.toLowerCase()
  49 +}
  50 +/**
  51 + * @description 获取系统信息同步接口
  52 + * @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
  53 + */
  54 +function sys() {
  55 + return uni.getSystemInfoSync()
  56 +}
  57 +
  58 +/**
  59 + * @description 取一个区间数
  60 + * @param {Number} min 最小值
  61 + * @param {Number} max 最大值
  62 + */
  63 +function random(min, max) {
  64 + if (min >= 0 && max > 0 && max >= min) {
  65 + const gab = max - min + 1
  66 + return Math.floor(Math.random() * gab + min)
  67 + }
  68 + return 0
  69 +}
  70 +
  71 +/**
  72 + * @param {Number} len uuid的长度
  73 + * @param {Boolean} firstU 将返回的首字母置为"u"
  74 + * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
  75 + */
  76 +function guid(len = 32, firstU = true, radix = null) {
  77 + const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  78 + const uuid = []
  79 + radix = radix || chars.length
  80 +
  81 + if (len) {
  82 + // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
  83 + for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
  84 + } else {
  85 + let r
  86 + // rfc4122标准要求返回的uuid中,某些位为固定的字符
  87 + uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
  88 + uuid[14] = '4'
  89 +
  90 + for (let i = 0; i < 36; i++) {
  91 + if (!uuid[i]) {
  92 + r = 0 | Math.random() * 16
  93 + uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
  94 + }
  95 + }
  96 + }
  97 + // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
  98 + if (firstU) {
  99 + uuid.shift()
  100 + return `u${uuid.join('')}`
  101 + }
  102 + return uuid.join('')
  103 +}
  104 +
  105 +/**
  106 +* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
  107 + this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
  108 + 这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
  109 + 值(默认为undefined),就是查找最顶层的$parent
  110 +* @param {string|undefined} name 父组件的参数名
  111 +*/
  112 +function $parent(name = undefined) {
  113 + let parent = this.$parent
  114 + // 通过while历遍,这里主要是为了H5需要多层解析的问题
  115 + while (parent) {
  116 + // 父组件
  117 + if (parent.$options && parent.$options.name !== name) {
  118 + // 如果组件的name不相等,继续上一级寻找
  119 + parent = parent.$parent
  120 + } else {
  121 + return parent
  122 + }
  123 + }
  124 + return false
  125 +}
  126 +
  127 +/**
  128 + * @description 样式转换
  129 + * 对象转字符串,或者字符串转对象
  130 + * @param {object | string} customStyle 需要转换的目标
  131 + * @param {String} target 转换的目的,object-转为对象,string-转为字符串
  132 + * @returns {object|string}
  133 + */
  134 +function addStyle(customStyle, target = 'object') {
  135 + // 字符串转字符串,对象转对象情形,直接返回
  136 + if (empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
  137 + typeof(customStyle) === 'string') {
  138 + return customStyle
  139 + }
  140 + // 字符串转对象
  141 + if (target === 'object') {
  142 + // 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
  143 + customStyle = trim(customStyle)
  144 + // 根据";"将字符串转为数组形式
  145 + const styleArray = customStyle.split(';')
  146 + const style = {}
  147 + // 历遍数组,拼接成对象
  148 + for (let i = 0; i < styleArray.length; i++) {
  149 + // 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
  150 + if (styleArray[i]) {
  151 + const item = styleArray[i].split(':')
  152 + style[trim(item[0])] = trim(item[1])
  153 + }
  154 + }
  155 + return style
  156 + }
  157 + // 这里为对象转字符串形式
  158 + let string = ''
  159 + for (const i in customStyle) {
  160 + // 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
  161 + const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
  162 + string += `${key}:${customStyle[i]};`
  163 + }
  164 + // 去除两端空格
  165 + return trim(string)
  166 +}
  167 +
  168 +/**
  169 + * @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
  170 + * @param {string|number} value 需要添加单位的值
  171 + * @param {string} unit 添加的单位名 比如px
  172 + */
  173 +function addUnit(value = 'auto', unit = uni?.$uv?.config?.unit ? uni?.$uv?.config?.unit : 'px') {
  174 + value = String(value)
  175 + // 用uvui内置验证规则中的number判断是否为数值
  176 + return number(value) ? `${value}${unit}` : value
  177 +}
  178 +
  179 +/**
  180 + * @description 深度克隆
  181 + * @param {object} obj 需要深度克隆的对象
  182 + * @param cache 缓存
  183 + * @returns {*} 克隆后的对象或者原值(不是对象)
  184 + */
  185 +function deepClone(obj, cache = new WeakMap()) {
  186 + if (obj === null || typeof obj !== 'object') return obj;
  187 + if (cache.has(obj)) return cache.get(obj);
  188 + let clone;
  189 + if (obj instanceof Date) {
  190 + clone = new Date(obj.getTime());
  191 + } else if (obj instanceof RegExp) {
  192 + clone = new RegExp(obj);
  193 + } else if (obj instanceof Map) {
  194 + clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
  195 + } else if (obj instanceof Set) {
  196 + clone = new Set(Array.from(obj, value => deepClone(value, cache)));
  197 + } else if (Array.isArray(obj)) {
  198 + clone = obj.map(value => deepClone(value, cache));
  199 + } else if (Object.prototype.toString.call(obj) === '[object Object]') {
  200 + clone = Object.create(Object.getPrototypeOf(obj));
  201 + cache.set(obj, clone);
  202 + for (const [key, value] of Object.entries(obj)) {
  203 + clone[key] = deepClone(value, cache);
  204 + }
  205 + } else {
  206 + clone = Object.assign({}, obj);
  207 + }
  208 + cache.set(obj, clone);
  209 + return clone;
  210 +}
  211 +
  212 +/**
  213 + * @description JS对象深度合并
  214 + * @param {object} target 需要拷贝的对象
  215 + * @param {object} source 拷贝的来源对象
  216 + * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
  217 + */
  218 +function deepMerge(target = {}, source = {}) {
  219 + target = deepClone(target)
  220 + if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
  221 + const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
  222 + for (const prop in source) {
  223 + if (!source.hasOwnProperty(prop)) continue;
  224 + const sourceValue = source[prop];
  225 + const targetValue = merged[prop];
  226 + if (sourceValue instanceof Date) {
  227 + merged[prop] = new Date(sourceValue);
  228 + } else if (sourceValue instanceof RegExp) {
  229 + merged[prop] = new RegExp(sourceValue);
  230 + } else if (sourceValue instanceof Map) {
  231 + merged[prop] = new Map(sourceValue);
  232 + } else if (sourceValue instanceof Set) {
  233 + merged[prop] = new Set(sourceValue);
  234 + } else if (typeof sourceValue === 'object' && sourceValue !== null) {
  235 + merged[prop] = deepMerge(targetValue, sourceValue);
  236 + } else {
  237 + merged[prop] = sourceValue;
  238 + }
  239 + }
  240 + return merged;
  241 +}
  242 +
  243 +/**
  244 + * @description error提示
  245 + * @param {*} err 错误内容
  246 + */
  247 +function error(err) {
  248 + // 开发环境才提示,生产环境不会提示
  249 + if (process.env.NODE_ENV === 'development') {
  250 + console.error(`uvui提示:${err}`)
  251 + }
  252 +}
  253 +
  254 +/**
  255 + * @description 打乱数组
  256 + * @param {array} array 需要打乱的数组
  257 + * @returns {array} 打乱后的数组
  258 + */
  259 +function randomArray(array = []) {
  260 + // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
  261 + return array.sort(() => Math.random() - 0.5)
  262 +}
  263 +
  264 +// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
  265 +// 所以这里做一个兼容polyfill的兼容处理
  266 +if (!String.prototype.padStart) {
  267 + // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
  268 + String.prototype.padStart = function(maxLength, fillString = ' ') {
  269 + if (Object.prototype.toString.call(fillString) !== '[object String]') {
  270 + throw new TypeError(
  271 + 'fillString must be String'
  272 + )
  273 + }
  274 + const str = this
  275 + // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
  276 + if (str.length >= maxLength) return String(str)
  277 +
  278 + const fillLength = maxLength - str.length
  279 + let times = Math.ceil(fillLength / fillString.length)
  280 + while (times >>= 1) {
  281 + fillString += fillString
  282 + if (times === 1) {
  283 + fillString += fillString
  284 + }
  285 + }
  286 + return fillString.slice(0, fillLength) + str
  287 + }
  288 +}
  289 +
  290 +/**
  291 + * @description 格式化时间
  292 + * @param {String|Number} dateTime 需要格式化的时间戳
  293 + * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
  294 + * @returns {string} 返回格式化后的字符串
  295 + */
  296 +function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
  297 + let date
  298 + // 若传入时间为假值,则取当前时间
  299 + if (!dateTime) {
  300 + date = new Date()
  301 + }
  302 + // 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
  303 + else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
  304 + date = new Date(dateTime * 1000)
  305 + }
  306 + // 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
  307 + else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
  308 + date = new Date(Number(dateTime))
  309 + }
  310 + // 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
  311 + // 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
  312 + else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
  313 + date = new Date(dateTime.replace(/-/g, '/'))
  314 + }
  315 + // 其他都认为符合 RFC 2822 规范
  316 + else {
  317 + date = new Date(dateTime)
  318 + }
  319 +
  320 + const timeSource = {
  321 + 'y': date.getFullYear().toString(), // 年
  322 + 'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
  323 + 'd': date.getDate().toString().padStart(2, '0'), // 日
  324 + 'h': date.getHours().toString().padStart(2, '0'), // 时
  325 + 'M': date.getMinutes().toString().padStart(2, '0'), // 分
  326 + 's': date.getSeconds().toString().padStart(2, '0') // 秒
  327 + // 有其他格式化字符需求可以继续添加,必须转化成字符串
  328 + }
  329 +
  330 + for (const key in timeSource) {
  331 + const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
  332 + if (ret) {
  333 + // 年可能只需展示两位
  334 + const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
  335 + formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
  336 + }
  337 + }
  338 +
  339 + return formatStr
  340 +}
  341 +
  342 +/**
  343 + * @description 时间戳转为多久之前
  344 + * @param {String|Number} timestamp 时间戳
  345 + * @param {String|Boolean} format
  346 + * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
  347 + * 如果为布尔值false,无论什么时间,都返回多久以前的格式
  348 + * @returns {string} 转化后的内容
  349 + */
  350 +function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
  351 + if (timestamp == null) timestamp = Number(new Date())
  352 + timestamp = parseInt(timestamp)
  353 + // 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
  354 + if (timestamp.toString().length == 10) timestamp *= 1000
  355 + let timer = (new Date()).getTime() - timestamp
  356 + timer = parseInt(timer / 1000)
  357 + // 如果小于5分钟,则返回"刚刚",其他以此类推
  358 + let tips = ''
  359 + switch (true) {
  360 + case timer < 300:
  361 + tips = '刚刚'
  362 + break
  363 + case timer >= 300 && timer < 3600:
  364 + tips = `${parseInt(timer / 60)}分钟前`
  365 + break
  366 + case timer >= 3600 && timer < 86400:
  367 + tips = `${parseInt(timer / 3600)}小时前`
  368 + break
  369 + case timer >= 86400 && timer < 2592000:
  370 + tips = `${parseInt(timer / 86400)}天前`
  371 + break
  372 + default:
  373 + // 如果format为false,则无论什么时间戳,都显示xx之前
  374 + if (format === false) {
  375 + if (timer >= 2592000 && timer < 365 * 86400) {
  376 + tips = `${parseInt(timer / (86400 * 30))}个月前`
  377 + } else {
  378 + tips = `${parseInt(timer / (86400 * 365))}年前`
  379 + }
  380 + } else {
  381 + tips = timeFormat(timestamp, format)
  382 + }
  383 + }
  384 + return tips
  385 +}
  386 +
  387 +/**
  388 + * @description 去除空格
  389 + * @param String str 需要去除空格的字符串
  390 + * @param String pos both(左右)|left|right|all 默认both
  391 + */
  392 +function trim(str, pos = 'both') {
  393 + str = String(str)
  394 + if (pos == 'both') {
  395 + return str.replace(/^\s+|\s+$/g, '')
  396 + }
  397 + if (pos == 'left') {
  398 + return str.replace(/^\s*/, '')
  399 + }
  400 + if (pos == 'right') {
  401 + return str.replace(/(\s*$)/g, '')
  402 + }
  403 + if (pos == 'all') {
  404 + return str.replace(/\s+/g, '')
  405 + }
  406 + return str
  407 +}
  408 +
  409 +/**
  410 + * @description 对象转url参数
  411 + * @param {object} data,对象
  412 + * @param {Boolean} isPrefix,是否自动加上"?"
  413 + * @param {string} arrayFormat 规则 indices|brackets|repeat|comma
  414 + */
  415 +function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
  416 + const prefix = isPrefix ? '?' : ''
  417 + const _result = []
  418 + if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
  419 + for (const key in data) {
  420 + const value = data[key]
  421 + // 去掉为空的参数
  422 + if (['', undefined, null].indexOf(value) >= 0) {
  423 + continue
  424 + }
  425 + // 如果值为数组,另行处理
  426 + if (value.constructor === Array) {
  427 + // e.g. {ids: [1, 2, 3]}
  428 + switch (arrayFormat) {
  429 + case 'indices':
  430 + // 结果: ids[0]=1&ids[1]=2&ids[2]=3
  431 + for (let i = 0; i < value.length; i++) {
  432 + _result.push(`${key}[${i}]=${value[i]}`)
  433 + }
  434 + break
  435 + case 'brackets':
  436 + // 结果: ids[]=1&ids[]=2&ids[]=3
  437 + value.forEach((_value) => {
  438 + _result.push(`${key}[]=${_value}`)
  439 + })
  440 + break
  441 + case 'repeat':
  442 + // 结果: ids=1&ids=2&ids=3
  443 + value.forEach((_value) => {
  444 + _result.push(`${key}=${_value}`)
  445 + })
  446 + break
  447 + case 'comma':
  448 + // 结果: ids=1,2,3
  449 + let commaStr = ''
  450 + value.forEach((_value) => {
  451 + commaStr += (commaStr ? ',' : '') + _value
  452 + })
  453 + _result.push(`${key}=${commaStr}`)
  454 + break
  455 + default:
  456 + value.forEach((_value) => {
  457 + _result.push(`${key}[]=${_value}`)
  458 + })
  459 + }
  460 + } else {
  461 + _result.push(`${key}=${value}`)
  462 + }
  463 + }
  464 + return _result.length ? prefix + _result.join('&') : ''
  465 +}
  466 +
  467 +/**
  468 + * 显示消息提示框
  469 + * @param {String} title 提示的内容,长度与 icon 取值有关。
  470 + * @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
  471 + */
  472 +function toast(title, duration = 2000) {
  473 + uni.showToast({
  474 + title: String(title),
  475 + icon: 'none',
  476 + duration
  477 + })
  478 +}
  479 +
  480 +/**
  481 + * @description 根据主题type值,获取对应的图标
  482 + * @param {String} type 主题名称,primary|info|error|warning|success
  483 + * @param {boolean} fill 是否使用fill填充实体的图标
  484 + */
  485 +function type2icon(type = 'success', fill = false) {
  486 + // 如果非预置值,默认为success
  487 + if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'
  488 + let iconName = ''
  489 + // 目前(2019-12-12),info和primary使用同一个图标
  490 + switch (type) {
  491 + case 'primary':
  492 + iconName = 'info-circle'
  493 + break
  494 + case 'info':
  495 + iconName = 'info-circle'
  496 + break
  497 + case 'error':
  498 + iconName = 'close-circle'
  499 + break
  500 + case 'warning':
  501 + iconName = 'error-circle'
  502 + break
  503 + case 'success':
  504 + iconName = 'checkmark-circle'
  505 + break
  506 + default:
  507 + iconName = 'checkmark-circle'
  508 + }
  509 + // 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
  510 + if (fill) iconName += '-fill'
  511 + return iconName
  512 +}
  513 +
  514 +/**
  515 + * @description 数字格式化
  516 + * @param {number|string} number 要格式化的数字
  517 + * @param {number} decimals 保留几位小数
  518 + * @param {string} decimalPoint 小数点符号
  519 + * @param {string} thousandsSeparator 千分位符号
  520 + * @returns {string} 格式化后的数字
  521 + */
  522 +function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
  523 + number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
  524 + const n = !isFinite(+number) ? 0 : +number
  525 + const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
  526 + const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
  527 + const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
  528 + let s = ''
  529 +
  530 + s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
  531 + const re = /(-?\d+)(\d{3})/
  532 + while (re.test(s[0])) {
  533 + s[0] = s[0].replace(re, `$1${sep}$2`)
  534 + }
  535 +
  536 + if ((s[1] || '').length < prec) {
  537 + s[1] = s[1] || ''
  538 + s[1] += new Array(prec - s[1].length + 1).join('0')
  539 + }
  540 + return s.join(dec)
  541 +}
  542 +
  543 +/**
  544 + * @description 获取duration值
  545 + * 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
  546 + * 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
  547 + * @param {String|number} value 比如: "1s"|"100ms"|1|100
  548 + * @param {boolean} unit 提示: 如果是false 默认返回number
  549 + * @return {string|number}
  550 + */
  551 +function getDuration(value, unit = true) {
  552 + const valueNum = parseInt(value)
  553 + if (unit) {
  554 + if (/s$/.test(value)) return value
  555 + return value > 30 ? `${value}ms` : `${value}s`
  556 + }
  557 + if (/ms$/.test(value)) return valueNum
  558 + if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000
  559 + return valueNum
  560 +}
  561 +
  562 +/**
  563 + * @description 日期的月或日补零操作
  564 + * @param {String} value 需要补零的值
  565 + */
  566 +function padZero(value) {
  567 + return `00${value}`.slice(-2)
  568 +}
  569 +
  570 +/**
  571 + * @description 在uv-form的子组件内容发生变化,或者失去焦点时,尝试通知uv-form执行校验方法
  572 + * @param {*} instance
  573 + * @param {*} event
  574 + */
  575 +function formValidate(instance, event) {
  576 + const formItem = $parent.call(instance, 'uv-form-item')
  577 + const form = $parent.call(instance, 'uv-form')
  578 + // 如果发生变化的input或者textarea等,其父组件中有uv-form-item或者uv-form等,就执行form的validate方法
  579 + // 同时将form-item的pros传递给form,让其进行精确对象验证
  580 + if (formItem && form) {
  581 + form.validateField(formItem.prop, () => {}, event)
  582 + }
  583 +}
  584 +
  585 +/**
  586 + * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
  587 + * @param {object} obj 对象
  588 + * @param {string} key 需要获取的属性字段
  589 + * @returns {*}
  590 + */
  591 +function getProperty(obj, key) {
  592 + if (!obj) {
  593 + return
  594 + }
  595 + if (typeof key !== 'string' || key === '') {
  596 + return ''
  597 + }
  598 + if (key.indexOf('.') !== -1) {
  599 + const keys = key.split('.')
  600 + let firstObj = obj[keys[0]] || {}
  601 +
  602 + for (let i = 1; i < keys.length; i++) {
  603 + if (firstObj) {
  604 + firstObj = firstObj[keys[i]]
  605 + }
  606 + }
  607 + return firstObj
  608 + }
  609 + return obj[key]
  610 +}
  611 +
  612 +/**
  613 + * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
  614 + * @param {object} obj 对象
  615 + * @param {string} key 需要设置的属性
  616 + * @param {string} value 设置的值
  617 + */
  618 +function setProperty(obj, key, value) {
  619 + if (!obj) {
  620 + return
  621 + }
  622 + // 递归赋值
  623 + const inFn = function(_obj, keys, v) {
  624 + // 最后一个属性key
  625 + if (keys.length === 1) {
  626 + _obj[keys[0]] = v
  627 + return
  628 + }
  629 + // 0~length-1个key
  630 + while (keys.length > 1) {
  631 + const k = keys[0]
  632 + if (!_obj[k] || (typeof _obj[k] !== 'object')) {
  633 + _obj[k] = {}
  634 + }
  635 + const key = keys.shift()
  636 + // 自调用判断是否存在属性,不存在则自动创建对象
  637 + inFn(_obj[k], keys, v)
  638 + }
  639 + }
  640 +
  641 + if (typeof key !== 'string' || key === '') {
  642 +
  643 + } else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
  644 + const keys = key.split('.')
  645 + inFn(obj, keys, value)
  646 + } else {
  647 + obj[key] = value
  648 + }
  649 +}
  650 +
  651 +/**
  652 + * @description 获取当前页面路径
  653 + */
  654 +function page() {
  655 + const pages = getCurrentPages();
  656 + const route = pages[pages.length - 1]?.route;
  657 + // 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
  658 + return `/${route ? route : ''}`
  659 +}
  660 +
  661 +/**
  662 + * @description 获取当前路由栈实例数组
  663 + */
  664 +function pages() {
  665 + const pages = getCurrentPages()
  666 + return pages
  667 +}
  668 +
  669 +/**
  670 + * 获取页面历史栈指定层实例
  671 + * @param back {number} [0] - 0或者负数,表示获取历史栈的哪一层,0表示获取当前页面实例,-1 表示获取上一个页面实例。默认0。
  672 + */
  673 +function getHistoryPage(back = 0) {
  674 + const pages = getCurrentPages()
  675 + const len = pages.length
  676 + return pages[len - 1 + back]
  677 +}
  678 +
  679 +
  680 +
  681 +/**
  682 + * @description 修改uvui内置属性值
  683 + * @param {object} props 修改内置props属性
  684 + * @param {object} config 修改内置config属性
  685 + * @param {object} color 修改内置color属性
  686 + * @param {object} zIndex 修改内置zIndex属性
  687 + */
  688 +function setConfig({
  689 + props = {},
  690 + config = {},
  691 + color = {},
  692 + zIndex = {}
  693 +}) {
  694 + const {
  695 + deepMerge,
  696 + } = uni.$uv
  697 + uni.$uv.config = deepMerge(uni.$uv.config, config)
  698 + uni.$uv.props = deepMerge(uni.$uv.props, props)
  699 + uni.$uv.color = deepMerge(uni.$uv.color, color)
  700 + uni.$uv.zIndex = deepMerge(uni.$uv.zIndex, zIndex)
  701 +}
  702 +
  703 +export {
  704 + range,
  705 + getPx,
  706 + sleep,
  707 + os,
  708 + sys,
  709 + random,
  710 + guid,
  711 + $parent,
  712 + addStyle,
  713 + addUnit,
  714 + deepClone,
  715 + deepMerge,
  716 + error,
  717 + randomArray,
  718 + timeFormat,
  719 + timeFrom,
  720 + trim,
  721 + queryParams,
  722 + toast,
  723 + type2icon,
  724 + priceFormat,
  725 + getDuration,
  726 + padZero,
  727 + formValidate,
  728 + getProperty,
  729 + setProperty,
  730 + page,
  731 + pages,
  732 + getHistoryPage,
  733 + setConfig
  734 +}
0 735 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/libs/function/platform.js 0 → 100644
  1 +/**
  2 + * 注意:
  3 + * 此部分内容,在vue-cli模式下,需要在vue.config.js加入如下内容才有效:
  4 + * module.exports = {
  5 + * transpileDependencies: ['uview-v2']
  6 + * }
  7 + */
  8 +
  9 +let platform = 'none'
  10 +
  11 +// #ifdef VUE3
  12 +platform = 'vue3'
  13 +// #endif
  14 +
  15 +// #ifdef VUE2
  16 +platform = 'vue2'
  17 +// #endif
  18 +
  19 +// #ifdef APP-PLUS
  20 +platform = 'plus'
  21 +// #endif
  22 +
  23 +// #ifdef APP-NVUE
  24 +platform = 'nvue'
  25 +// #endif
  26 +
  27 +// #ifdef H5
  28 +platform = 'h5'
  29 +// #endif
  30 +
  31 +// #ifdef MP-WEIXIN
  32 +platform = 'weixin'
  33 +// #endif
  34 +
  35 +// #ifdef MP-ALIPAY
  36 +platform = 'alipay'
  37 +// #endif
  38 +
  39 +// #ifdef MP-BAIDU
  40 +platform = 'baidu'
  41 +// #endif
  42 +
  43 +// #ifdef MP-TOUTIAO
  44 +platform = 'toutiao'
  45 +// #endif
  46 +
  47 +// #ifdef MP-QQ
  48 +platform = 'qq'
  49 +// #endif
  50 +
  51 +// #ifdef MP-KUAISHOU
  52 +platform = 'kuaishou'
  53 +// #endif
  54 +
  55 +// #ifdef MP-360
  56 +platform = '360'
  57 +// #endif
  58 +
  59 +// #ifdef MP
  60 +platform = 'mp'
  61 +// #endif
  62 +
  63 +// #ifdef QUICKAPP-WEBVIEW
  64 +platform = 'quickapp-webview'
  65 +// #endif
  66 +
  67 +// #ifdef QUICKAPP-WEBVIEW-HUAWEI
  68 +platform = 'quickapp-webview-huawei'
  69 +// #endif
  70 +
  71 +// #ifdef QUICKAPP-WEBVIEW-UNION
  72 +platform = 'quckapp-webview-union'
  73 +// #endif
  74 +
  75 +export default platform
... ...
uni_modules/uv-ui-tools/libs/function/test.js 0 → 100644
  1 +/**
  2 + * 验证电子邮箱格式
  3 + */
  4 +function email(value) {
  5 + return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
  6 +}
  7 +
  8 +/**
  9 + * 验证手机格式
  10 + */
  11 +function mobile(value) {
  12 + return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
  13 +}
  14 +
  15 +/**
  16 + * 验证URL格式
  17 + */
  18 +function url(value) {
  19 + return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
  20 + .test(value)
  21 +}
  22 +
  23 +/**
  24 + * 验证日期格式
  25 + */
  26 +function date(value) {
  27 + if (!value) return false
  28 + // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
  29 + if (number(value)) value = +value
  30 + return !/Invalid|NaN/.test(new Date(value).toString())
  31 +}
  32 +
  33 +/**
  34 + * 验证ISO类型的日期格式
  35 + */
  36 +function dateISO(value) {
  37 + return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
  38 +}
  39 +
  40 +/**
  41 + * 验证十进制数字
  42 + */
  43 +function number(value) {
  44 + return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
  45 +}
  46 +
  47 +/**
  48 + * 验证字符串
  49 + */
  50 +function string(value) {
  51 + return typeof value === 'string'
  52 +}
  53 +
  54 +/**
  55 + * 验证整数
  56 + */
  57 +function digits(value) {
  58 + return /^\d+$/.test(value)
  59 +}
  60 +
  61 +/**
  62 + * 验证身份证号码
  63 + */
  64 +function idCard(value) {
  65 + return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
  66 + value
  67 + )
  68 +}
  69 +
  70 +/**
  71 + * 是否车牌号
  72 + */
  73 +function carNo(value) {
  74 + // 新能源车牌
  75 + const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
  76 + // 旧车牌
  77 + const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
  78 + if (value.length === 7) {
  79 + return creg.test(value)
  80 + } if (value.length === 8) {
  81 + return xreg.test(value)
  82 + }
  83 + return false
  84 +}
  85 +
  86 +/**
  87 + * 金额,只允许2位小数
  88 + */
  89 +function amount(value) {
  90 + // 金额,只允许保留两位小数
  91 + return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
  92 +}
  93 +
  94 +/**
  95 + * 中文
  96 + */
  97 +function chinese(value) {
  98 + const reg = /^[\u4e00-\u9fa5]+$/gi
  99 + return reg.test(value)
  100 +}
  101 +
  102 +/**
  103 + * 只能输入字母
  104 + */
  105 +function letter(value) {
  106 + return /^[a-zA-Z]*$/.test(value)
  107 +}
  108 +
  109 +/**
  110 + * 只能是字母或者数字
  111 + */
  112 +function enOrNum(value) {
  113 + // 英文或者数字
  114 + const reg = /^[0-9a-zA-Z]*$/g
  115 + return reg.test(value)
  116 +}
  117 +
  118 +/**
  119 + * 验证是否包含某个值
  120 + */
  121 +function contains(value, param) {
  122 + return value.indexOf(param) >= 0
  123 +}
  124 +
  125 +/**
  126 + * 验证一个值范围[min, max]
  127 + */
  128 +function range(value, param) {
  129 + return value >= param[0] && value <= param[1]
  130 +}
  131 +
  132 +/**
  133 + * 验证一个长度范围[min, max]
  134 + */
  135 +function rangeLength(value, param) {
  136 + return value.length >= param[0] && value.length <= param[1]
  137 +}
  138 +
  139 +/**
  140 + * 是否固定电话
  141 + */
  142 +function landline(value) {
  143 + const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
  144 + return reg.test(value)
  145 +}
  146 +
  147 +/**
  148 + * 判断是否为空
  149 + */
  150 +function empty(value) {
  151 + switch (typeof value) {
  152 + case 'undefined':
  153 + return true
  154 + case 'string':
  155 + if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
  156 + break
  157 + case 'boolean':
  158 + if (!value) return true
  159 + break
  160 + case 'number':
  161 + if (value === 0 || isNaN(value)) return true
  162 + break
  163 + case 'object':
  164 + if (value === null || value.length === 0) return true
  165 + for (const i in value) {
  166 + return false
  167 + }
  168 + return true
  169 + }
  170 + return false
  171 +}
  172 +
  173 +/**
  174 + * 是否json字符串
  175 + */
  176 +function jsonString(value) {
  177 + if (typeof value === 'string') {
  178 + try {
  179 + const obj = JSON.parse(value)
  180 + if (typeof obj === 'object' && obj) {
  181 + return true
  182 + }
  183 + return false
  184 + } catch (e) {
  185 + return false
  186 + }
  187 + }
  188 + return false
  189 +}
  190 +
  191 +/**
  192 + * 是否数组
  193 + */
  194 +function array(value) {
  195 + if (typeof Array.isArray === 'function') {
  196 + return Array.isArray(value)
  197 + }
  198 + return Object.prototype.toString.call(value) === '[object Array]'
  199 +}
  200 +
  201 +/**
  202 + * 是否对象
  203 + */
  204 +function object(value) {
  205 + return Object.prototype.toString.call(value) === '[object Object]'
  206 +}
  207 +
  208 +/**
  209 + * 是否短信验证码
  210 + */
  211 +function code(value, len = 6) {
  212 + return new RegExp(`^\\d{${len}}$`).test(value)
  213 +}
  214 +
  215 +/**
  216 + * 是否函数方法
  217 + * @param {Object} value
  218 + */
  219 +function func(value) {
  220 + return typeof value === 'function'
  221 +}
  222 +
  223 +/**
  224 + * 是否promise对象
  225 + * @param {Object} value
  226 + */
  227 +function promise(value) {
  228 + return object(value) && func(value.then) && func(value.catch)
  229 +}
  230 +
  231 +/** 是否图片格式
  232 + * @param {Object} value
  233 + */
  234 +function image(value) {
  235 + const newValue = value.split('?')[0]
  236 + const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
  237 + return IMAGE_REGEXP.test(newValue)
  238 +}
  239 +
  240 +/**
  241 + * 是否视频格式
  242 + * @param {Object} value
  243 + */
  244 +function video(value) {
  245 + const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
  246 + return VIDEO_REGEXP.test(value)
  247 +}
  248 +
  249 +/**
  250 + * 是否为正则对象
  251 + * @param {Object}
  252 + * @return {Boolean}
  253 + */
  254 +function regExp(o) {
  255 + return o && Object.prototype.toString.call(o) === '[object RegExp]'
  256 +}
  257 +
  258 +export {
  259 + email,
  260 + mobile,
  261 + url,
  262 + date,
  263 + dateISO,
  264 + number,
  265 + digits,
  266 + idCard,
  267 + carNo,
  268 + amount,
  269 + chinese,
  270 + letter,
  271 + enOrNum,
  272 + contains,
  273 + range,
  274 + rangeLength,
  275 + empty,
  276 + jsonString,
  277 + landline,
  278 + object,
  279 + array,
  280 + code,
  281 + func,
  282 + promise,
  283 + video,
  284 + image,
  285 + regExp,
  286 + string
  287 +}
... ...
uni_modules/uv-ui-tools/libs/function/throttle.js 0 → 100644
  1 +let timer; let
  2 + flag
  3 +/**
  4 + * 节流原理:在一定时间内,只能触发一次
  5 + *
  6 + * @param {Function} func 要执行的回调函数
  7 + * @param {Number} wait 延时的时间
  8 + * @param {Boolean} immediate 是否立即执行
  9 + * @return null
  10 + */
  11 +function throttle(func, wait = 500, immediate = true) {
  12 + if (immediate) {
  13 + if (!flag) {
  14 + flag = true
  15 + // 如果是立即执行,则在wait毫秒内开始时执行
  16 + typeof func === 'function' && func()
  17 + timer = setTimeout(() => {
  18 + flag = false
  19 + }, wait)
  20 + }
  21 + } else if (!flag) {
  22 + flag = true
  23 + // 如果是非立即执行,则在wait毫秒内的结束处执行
  24 + timer = setTimeout(() => {
  25 + flag = false
  26 + typeof func === 'function' && func()
  27 + }, wait)
  28 + }
  29 +}
  30 +export default throttle
... ...
uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js 0 → 100644
  1 +import buildURL from '../helpers/buildURL'
  2 +import buildFullPath from '../core/buildFullPath'
  3 +import settle from '../core/settle'
  4 +import {isUndefined} from "../utils"
  5 +
  6 +/**
  7 + * 返回可选值存在的配置
  8 + * @param {Array} keys - 可选值数组
  9 + * @param {Object} config2 - 配置
  10 + * @return {{}} - 存在的配置项
  11 + */
  12 +const mergeKeys = (keys, config2) => {
  13 + let config = {}
  14 + keys.forEach(prop => {
  15 + if (!isUndefined(config2[prop])) {
  16 + config[prop] = config2[prop]
  17 + }
  18 + })
  19 + return config
  20 +}
  21 +export default (config) => {
  22 + return new Promise((resolve, reject) => {
  23 + let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
  24 + const _config = {
  25 + url: fullPath,
  26 + header: config.header,
  27 + complete: (response) => {
  28 + config.fullPath = fullPath
  29 + response.config = config
  30 + response.rawData = response.data
  31 + try {
  32 + let jsonParseHandle = false
  33 + const forcedJSONParsingType = typeof config.forcedJSONParsing
  34 + if (forcedJSONParsingType === 'boolean') {
  35 + jsonParseHandle = config.forcedJSONParsing
  36 + } else if (forcedJSONParsingType === 'object') {
  37 + const includesMethod = config.forcedJSONParsing.include || []
  38 + jsonParseHandle = includesMethod.includes(config.method)
  39 + }
  40 +
  41 + // 对可能字符串不是json 的情况容错
  42 + if (jsonParseHandle && typeof response.data === 'string') {
  43 + response.data = JSON.parse(response.data)
  44 + }
  45 + // eslint-disable-next-line no-empty
  46 + } catch (e) {
  47 + }
  48 + settle(resolve, reject, response)
  49 + }
  50 + }
  51 + let requestTask
  52 + if (config.method === 'UPLOAD') {
  53 + delete _config.header['content-type']
  54 + delete _config.header['Content-Type']
  55 + let otherConfig = {
  56 + // #ifdef MP-ALIPAY
  57 + fileType: config.fileType,
  58 + // #endif
  59 + filePath: config.filePath,
  60 + name: config.name
  61 + }
  62 + const optionalKeys = [
  63 + // #ifdef APP-PLUS || H5
  64 + 'files',
  65 + // #endif
  66 + // #ifdef H5
  67 + 'file',
  68 + // #endif
  69 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  70 + 'timeout',
  71 + // #endif
  72 + 'formData'
  73 + ]
  74 + requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
  75 + } else if (config.method === 'DOWNLOAD') {
  76 + const optionalKeys = [
  77 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  78 + 'timeout',
  79 + // #endif
  80 + // #ifdef MP
  81 + 'filePath',
  82 + // #endif
  83 + ]
  84 + requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
  85 + } else {
  86 + const optionalKeys = [
  87 + 'data',
  88 + 'method',
  89 + // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
  90 + 'timeout',
  91 + // #endif
  92 + 'dataType',
  93 + // #ifndef MP-ALIPAY
  94 + 'responseType',
  95 + // #endif
  96 + // #ifdef APP-PLUS
  97 + 'sslVerify',
  98 + // #endif
  99 + // #ifdef H5
  100 + 'withCredentials',
  101 + // #endif
  102 + // #ifdef APP-PLUS
  103 + 'firstIpv4',
  104 + // #endif
  105 + // #ifdef MP-WEIXIN
  106 + 'enableHttp2',
  107 + 'enableQuic',
  108 + // #endif
  109 + // #ifdef MP-TOUTIAO || MP-WEIXIN
  110 + 'enableCache',
  111 + // #endif
  112 + // #ifdef MP-WEIXIN
  113 + 'enableHttpDNS',
  114 + 'httpDNSServiceId',
  115 + 'enableChunked',
  116 + 'forceCellularNetwork',
  117 + // #endif
  118 + // #ifdef MP-ALIPAY
  119 + 'enableCookie',
  120 + // #endif
  121 + // #ifdef MP-BAIDU
  122 + 'cloudCache',
  123 + 'defer'
  124 + // #endif
  125 + ]
  126 + requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
  127 + }
  128 + if (config.getTask) {
  129 + config.getTask(requestTask, config)
  130 + }
  131 + })
  132 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js 0 → 100644
  1 +'use strict'
  2 +
  3 +
  4 +function InterceptorManager() {
  5 + this.handlers = []
  6 +}
  7 +
  8 +/**
  9 + * Add a new interceptor to the stack
  10 + *
  11 + * @param {Function} fulfilled The function to handle `then` for a `Promise`
  12 + * @param {Function} rejected The function to handle `reject` for a `Promise`
  13 + *
  14 + * @return {Number} An ID used to remove interceptor later
  15 + */
  16 +InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  17 + this.handlers.push({
  18 + fulfilled: fulfilled,
  19 + rejected: rejected
  20 + })
  21 + return this.handlers.length - 1
  22 +}
  23 +
  24 +/**
  25 + * Remove an interceptor from the stack
  26 + *
  27 + * @param {Number} id The ID that was returned by `use`
  28 + */
  29 +InterceptorManager.prototype.eject = function eject(id) {
  30 + if (this.handlers[id]) {
  31 + this.handlers[id] = null
  32 + }
  33 +}
  34 +
  35 +/**
  36 + * Iterate over all the registered interceptors
  37 + *
  38 + * This method is particularly useful for skipping over any
  39 + * interceptors that may have become `null` calling `eject`.
  40 + *
  41 + * @param {Function} fn The function to call for each interceptor
  42 + */
  43 +InterceptorManager.prototype.forEach = function forEach(fn) {
  44 + this.handlers.forEach(h => {
  45 + if (h !== null) {
  46 + fn(h)
  47 + }
  48 + })
  49 +}
  50 +
  51 +export default InterceptorManager
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/Request.js 0 → 100644
  1 +/**
  2 + * @Class Request
  3 + * @description luch-request http请求插件
  4 + * @Author lu-ch
  5 + * @Email webwork.s@qq.com
  6 + * 文档: https://www.quanzhan.co/luch-request/
  7 + * github: https://github.com/lei-mu/luch-request
  8 + * DCloud: http://ext.dcloud.net.cn/plugin?id=392
  9 + */
  10 +
  11 +
  12 +import dispatchRequest from './dispatchRequest'
  13 +import InterceptorManager from './InterceptorManager'
  14 +import mergeConfig from './mergeConfig'
  15 +import defaults from './defaults'
  16 +import { isPlainObject } from '../utils'
  17 +import clone from '../utils/clone'
  18 +
  19 +export default class Request {
  20 + /**
  21 + * @param {Object} arg - 全局配置
  22 + * @param {String} arg.baseURL - 全局根路径
  23 + * @param {Object} arg.header - 全局header
  24 + * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
  25 + * @param {String} arg.dataType = [json] - 全局默认的dataType
  26 + * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
  27 + * @param {Object} arg.custom - 全局默认的自定义参数
  28 + * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
  29 + * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
  30 + * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
  31 + * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
  32 + * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
  33 + */
  34 + constructor(arg = {}) {
  35 + if (!isPlainObject(arg)) {
  36 + arg = {}
  37 + console.warn('设置全局参数必须接收一个Object')
  38 + }
  39 + this.config = clone({...defaults, ...arg})
  40 + this.interceptors = {
  41 + request: new InterceptorManager(),
  42 + response: new InterceptorManager()
  43 + }
  44 + }
  45 +
  46 + /**
  47 + * @Function
  48 + * @param {Request~setConfigCallback} f - 设置全局默认配置
  49 + */
  50 + setConfig(f) {
  51 + this.config = f(this.config)
  52 + }
  53 +
  54 + middleware(config) {
  55 + config = mergeConfig(this.config, config)
  56 + let chain = [dispatchRequest, undefined]
  57 + let promise = Promise.resolve(config)
  58 +
  59 + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
  60 + chain.unshift(interceptor.fulfilled, interceptor.rejected)
  61 + })
  62 +
  63 + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
  64 + chain.push(interceptor.fulfilled, interceptor.rejected)
  65 + })
  66 +
  67 + while (chain.length) {
  68 + promise = promise.then(chain.shift(), chain.shift())
  69 + }
  70 +
  71 + return promise
  72 + }
  73 +
  74 + /**
  75 + * @Function
  76 + * @param {Object} config - 请求配置项
  77 + * @prop {String} options.url - 请求路径
  78 + * @prop {Object} options.data - 请求参数
  79 + * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
  80 + * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
  81 + * @prop {Object} [options.header = config.header] - 请求header
  82 + * @prop {Object} [options.method = config.method] - 请求方法
  83 + * @returns {Promise<unknown>}
  84 + */
  85 + request(config = {}) {
  86 + return this.middleware(config)
  87 + }
  88 +
  89 + get(url, options = {}) {
  90 + return this.middleware({
  91 + url,
  92 + method: 'GET',
  93 + ...options
  94 + })
  95 + }
  96 +
  97 + post(url, data, options = {}) {
  98 + return this.middleware({
  99 + url,
  100 + data,
  101 + method: 'POST',
  102 + ...options
  103 + })
  104 + }
  105 +
  106 + // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
  107 + put(url, data, options = {}) {
  108 + return this.middleware({
  109 + url,
  110 + data,
  111 + method: 'PUT',
  112 + ...options
  113 + })
  114 + }
  115 +
  116 + // #endif
  117 +
  118 + // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
  119 + delete(url, data, options = {}) {
  120 + return this.middleware({
  121 + url,
  122 + data,
  123 + method: 'DELETE',
  124 + ...options
  125 + })
  126 + }
  127 +
  128 + // #endif
  129 +
  130 + // #ifdef H5 || MP-WEIXIN
  131 + connect(url, data, options = {}) {
  132 + return this.middleware({
  133 + url,
  134 + data,
  135 + method: 'CONNECT',
  136 + ...options
  137 + })
  138 + }
  139 +
  140 + // #endif
  141 +
  142 + // #ifdef H5 || MP-WEIXIN || MP-BAIDU
  143 + head(url, data, options = {}) {
  144 + return this.middleware({
  145 + url,
  146 + data,
  147 + method: 'HEAD',
  148 + ...options
  149 + })
  150 + }
  151 +
  152 + // #endif
  153 +
  154 + // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
  155 + options(url, data, options = {}) {
  156 + return this.middleware({
  157 + url,
  158 + data,
  159 + method: 'OPTIONS',
  160 + ...options
  161 + })
  162 + }
  163 +
  164 + // #endif
  165 +
  166 + // #ifdef H5 || MP-WEIXIN
  167 + trace(url, data, options = {}) {
  168 + return this.middleware({
  169 + url,
  170 + data,
  171 + method: 'TRACE',
  172 + ...options
  173 + })
  174 + }
  175 +
  176 + // #endif
  177 +
  178 + upload(url, config = {}) {
  179 + config.url = url
  180 + config.method = 'UPLOAD'
  181 + return this.middleware(config)
  182 + }
  183 +
  184 + download(url, config = {}) {
  185 + config.url = url
  186 + config.method = 'DOWNLOAD'
  187 + return this.middleware(config)
  188 + }
  189 +
  190 + get version () {
  191 + return '3.1.0'
  192 + }
  193 +}
  194 +
  195 +
  196 +/**
  197 + * setConfig回调
  198 + * @return {Object} - 返回操作后的config
  199 + * @callback Request~setConfigCallback
  200 + * @param {Object} config - 全局默认config
  201 + */
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js 0 → 100644
  1 +'use strict'
  2 +
  3 +import isAbsoluteURL from '../helpers/isAbsoluteURL'
  4 +import combineURLs from '../helpers/combineURLs'
  5 +
  6 +/**
  7 + * Creates a new URL by combining the baseURL with the requestedURL,
  8 + * only when the requestedURL is not already an absolute URL.
  9 + * If the requestURL is absolute, this function returns the requestedURL untouched.
  10 + *
  11 + * @param {string} baseURL The base URL
  12 + * @param {string} requestedURL Absolute or relative URL to combine
  13 + * @returns {string} The combined full path
  14 + */
  15 +export default function buildFullPath(baseURL, requestedURL) {
  16 + if (baseURL && !isAbsoluteURL(requestedURL)) {
  17 + return combineURLs(baseURL, requestedURL)
  18 + }
  19 + return requestedURL
  20 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js 0 → 100644
  1 +/**
  2 + * 默认的全局配置
  3 + */
  4 +
  5 +
  6 +export default {
  7 + baseURL: '',
  8 + header: {},
  9 + method: 'GET',
  10 + dataType: 'json',
  11 + paramsSerializer: null,
  12 + // #ifndef MP-ALIPAY
  13 + responseType: 'text',
  14 + // #endif
  15 + custom: {},
  16 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  17 + timeout: 60000,
  18 + // #endif
  19 + // #ifdef APP-PLUS
  20 + sslVerify: true,
  21 + // #endif
  22 + // #ifdef H5
  23 + withCredentials: false,
  24 + // #endif
  25 + // #ifdef APP-PLUS
  26 + firstIpv4: false,
  27 + // #endif
  28 + validateStatus: function validateStatus(status) {
  29 + return status >= 200 && status < 300
  30 + },
  31 + // 是否尝试将响应数据json化
  32 + forcedJSONParsing: true
  33 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js 0 → 100644
  1 +import adapter from '../adapters/index'
  2 +
  3 +
  4 +export default (config) => {
  5 + return adapter(config)
  6 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js 0 → 100644
  1 +import {deepMerge, isUndefined} from '../utils'
  2 +
  3 +/**
  4 + * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
  5 + * @param {Array} keys - 配置项
  6 + * @param {Object} globalsConfig - 当前的全局配置
  7 + * @param {Object} config2 - 局部配置
  8 + * @return {{}}
  9 + */
  10 +const mergeKeys = (keys, globalsConfig, config2) => {
  11 + let config = {}
  12 + keys.forEach(prop => {
  13 + if (!isUndefined(config2[prop])) {
  14 + config[prop] = config2[prop]
  15 + } else if (!isUndefined(globalsConfig[prop])) {
  16 + config[prop] = globalsConfig[prop]
  17 + }
  18 + })
  19 + return config
  20 +}
  21 +/**
  22 + *
  23 + * @param globalsConfig - 当前实例的全局配置
  24 + * @param config2 - 当前的局部配置
  25 + * @return - 合并后的配置
  26 + */
  27 +export default (globalsConfig, config2 = {}) => {
  28 + const method = config2.method || globalsConfig.method || 'GET'
  29 + let config = {
  30 + baseURL: config2.baseURL || globalsConfig.baseURL || '',
  31 + method: method,
  32 + url: config2.url || '',
  33 + params: config2.params || {},
  34 + custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
  35 + header: deepMerge(globalsConfig.header || {}, config2.header || {})
  36 + }
  37 + const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
  38 + config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
  39 +
  40 + // eslint-disable-next-line no-empty
  41 + if (method === 'DOWNLOAD') {
  42 + const downloadKeys = [
  43 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  44 + 'timeout',
  45 + // #endif
  46 + // #ifdef MP
  47 + 'filePath',
  48 + // #endif
  49 + ]
  50 + config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
  51 + } else if (method === 'UPLOAD') {
  52 + delete config.header['content-type']
  53 + delete config.header['Content-Type']
  54 + const uploadKeys = [
  55 + // #ifdef APP-PLUS || H5
  56 + 'files',
  57 + // #endif
  58 + // #ifdef MP-ALIPAY
  59 + 'fileType',
  60 + // #endif
  61 + // #ifdef H5
  62 + 'file',
  63 + // #endif
  64 + 'filePath',
  65 + 'name',
  66 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  67 + 'timeout',
  68 + // #endif
  69 + 'formData',
  70 + ]
  71 + uploadKeys.forEach(prop => {
  72 + if (!isUndefined(config2[prop])) {
  73 + config[prop] = config2[prop]
  74 + }
  75 + })
  76 + // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
  77 + if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
  78 + config['timeout'] = globalsConfig['timeout']
  79 + }
  80 + // #endif
  81 + } else {
  82 + const defaultsKeys = [
  83 + 'data',
  84 + // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
  85 + 'timeout',
  86 + // #endif
  87 + 'dataType',
  88 + // #ifndef MP-ALIPAY
  89 + 'responseType',
  90 + // #endif
  91 + // #ifdef APP-PLUS
  92 + 'sslVerify',
  93 + // #endif
  94 + // #ifdef H5
  95 + 'withCredentials',
  96 + // #endif
  97 + // #ifdef APP-PLUS
  98 + 'firstIpv4',
  99 + // #endif
  100 + // #ifdef MP-WEIXIN
  101 + 'enableHttp2',
  102 + 'enableQuic',
  103 + // #endif
  104 + // #ifdef MP-TOUTIAO || MP-WEIXIN
  105 + 'enableCache',
  106 + // #endif
  107 + // #ifdef MP-WEIXIN
  108 + 'enableHttpDNS',
  109 + 'httpDNSServiceId',
  110 + 'enableChunked',
  111 + 'forceCellularNetwork',
  112 + // #endif
  113 + // #ifdef MP-ALIPAY
  114 + 'enableCookie',
  115 + // #endif
  116 + // #ifdef MP-BAIDU
  117 + 'cloudCache',
  118 + 'defer'
  119 + // #endif
  120 +
  121 + ]
  122 + config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
  123 + }
  124 +
  125 + return config
  126 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/core/settle.js 0 → 100644
  1 +/**
  2 + * Resolve or reject a Promise based on response status.
  3 + *
  4 + * @param {Function} resolve A function that resolves the promise.
  5 + * @param {Function} reject A function that rejects the promise.
  6 + * @param {object} response The response.
  7 + */
  8 +export default function settle(resolve, reject, response) {
  9 + const validateStatus = response.config.validateStatus
  10 + const status = response.statusCode
  11 + if (status && (!validateStatus || validateStatus(status))) {
  12 + resolve(response)
  13 + } else {
  14 + reject(response)
  15 + }
  16 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js 0 → 100644
  1 +'use strict'
  2 +
  3 +import * as utils from './../utils'
  4 +
  5 +function encode(val) {
  6 + return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
  7 +}
  8 +
  9 +/**
  10 + * Build a URL by appending params to the end
  11 + *
  12 + * @param {string} url The base of the url (e.g., http://www.google.com)
  13 + * @param {object} [params] The params to be appended
  14 + * @returns {string} The formatted url
  15 + */
  16 +export default function buildURL(url, params, paramsSerializer) {
  17 + /*eslint no-param-reassign:0*/
  18 + if (!params) {
  19 + return url
  20 + }
  21 +
  22 + var serializedParams
  23 + if (paramsSerializer) {
  24 + serializedParams = paramsSerializer(params)
  25 + } else if (utils.isURLSearchParams(params)) {
  26 + serializedParams = params.toString()
  27 + } else {
  28 + var parts = []
  29 +
  30 + utils.forEach(params, function serialize(val, key) {
  31 + if (val === null || typeof val === 'undefined') {
  32 + return
  33 + }
  34 +
  35 + if (utils.isArray(val)) {
  36 + key = key + '[]'
  37 + } else {
  38 + val = [val]
  39 + }
  40 +
  41 + utils.forEach(val, function parseValue(v) {
  42 + if (utils.isDate(v)) {
  43 + v = v.toISOString()
  44 + } else if (utils.isObject(v)) {
  45 + v = JSON.stringify(v)
  46 + }
  47 + parts.push(encode(key) + '=' + encode(v))
  48 + })
  49 + })
  50 +
  51 + serializedParams = parts.join('&')
  52 + }
  53 +
  54 + if (serializedParams) {
  55 + var hashmarkIndex = url.indexOf('#')
  56 + if (hashmarkIndex !== -1) {
  57 + url = url.slice(0, hashmarkIndex)
  58 + }
  59 +
  60 + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
  61 + }
  62 +
  63 + return url
  64 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js 0 → 100644
  1 +'use strict'
  2 +
  3 +/**
  4 + * Creates a new URL by combining the specified URLs
  5 + *
  6 + * @param {string} baseURL The base URL
  7 + * @param {string} relativeURL The relative URL
  8 + * @returns {string} The combined URL
  9 + */
  10 +export default function combineURLs(baseURL, relativeURL) {
  11 + return relativeURL
  12 + ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
  13 + : baseURL
  14 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js 0 → 100644
  1 +'use strict'
  2 +
  3 +/**
  4 + * Determines whether the specified URL is absolute
  5 + *
  6 + * @param {string} url The URL to test
  7 + * @returns {boolean} True if the specified URL is absolute, otherwise false
  8 + */
  9 +export default function isAbsoluteURL(url) {
  10 + // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
  11 + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
  12 + // by any combination of letters, digits, plus, period, or hyphen.
  13 + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
  14 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/index.d.ts 0 → 100644
  1 +export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
  2 +
  3 +export type HttpRequestTask = UniApp.RequestTask;
  4 +
  5 +export type HttpUploadTask = UniApp.UploadTask;
  6 +
  7 +export type HttpDownloadTask = UniApp.DownloadTask;
  8 +
  9 +export type HttpMethod =
  10 + "GET"
  11 + | "POST"
  12 + | "PUT"
  13 + | "DELETE"
  14 + | "CONNECT"
  15 + | "HEAD"
  16 + | "OPTIONS"
  17 + | "TRACE"
  18 + | "UPLOAD"
  19 + | "DOWNLOAD";
  20 +
  21 +export type HttpRequestHeader = Record<string, string>;
  22 +
  23 +export type HttpParams = Record<string, any>;
  24 +
  25 +export type HttpData = Record<string, any>;
  26 +
  27 +export type HttpResponseType = 'arraybuffer' | 'text';
  28 +
  29 +export type HttpCustom = Record<string, any>;
  30 +
  31 +export type HttpFileType = 'image' | 'video' | 'audio';
  32 +
  33 +export type HttpFormData = Record<string, any>;
  34 +
  35 +export type HttpResponseHeader = Record<string, string> & {
  36 + "set-cookie"?: string[]
  37 +};
  38 +
  39 +export interface HttpRequestConfig<T = HttpTask> {
  40 + /** @desc 请求服务器接口地址 */
  41 + url?: string;
  42 + /** @desc 请求方式,默认为 GET */
  43 + method?: HttpMethod;
  44 + /** @desc 请求基地址 */
  45 + baseURL?: string;
  46 + /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
  47 + header?: HttpRequestHeader;
  48 + /** @desc 请求查询参数,自动拼接为查询字符串 */
  49 + params?: HttpParams;
  50 + /** @desc 请求体参数 */
  51 + data?: HttpData;
  52 + /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
  53 + timeout?: number;
  54 + /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
  55 + withCredentials?: boolean;
  56 + /** @desc 设置响应的数据类型,支付宝小程序不支持 */
  57 + responseType?: HttpResponseType;
  58 + /** @desc 全局自定义验证器 */
  59 + validateStatus?: ((statusCode: number) => boolean) | null;
  60 +
  61 +
  62 + /** params 参数自定义处理 */
  63 + paramsSerializer?: (params: AnyObject) => string | void;
  64 +
  65 + /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
  66 + dataType?: string;
  67 + /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
  68 + firstIpv4?: boolean;
  69 + /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
  70 + sslVerify?: boolean;
  71 +
  72 + /** @desc 开启 http2;微信小程序 */
  73 + enableHttp2?: boolean;
  74 +
  75 + /** @desc 开启 quic;微信小程序 */
  76 + enableQuic?: boolean;
  77 + /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
  78 + enableCache?: boolean;
  79 + /** @desc 开启 httpDNS;微信小程序 */
  80 + enableHttpDNS?: boolean;
  81 + /** @desc httpDNS 服务商;微信小程序 */
  82 + httpDNSServiceId?: string;
  83 + /** @desc 开启 transfer-encoding chunked;微信小程序 */
  84 + enableChunked?: boolean;
  85 + /** @desc wifi下使用移动网络发送请求;微信小程序 */
  86 + forceCellularNetwork?: boolean;
  87 + /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
  88 + enableCookie?: boolean;
  89 + /** @desc 是否开启云加速;百度小程序 3.310.11+ */
  90 + cloudCache?: boolean | object;
  91 + /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
  92 + defer?: boolean;
  93 +
  94 + /** @desc 自定义参数 */
  95 + custom?: HttpCustom;
  96 +
  97 + /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
  98 + getTask?: (task: T, options: HttpRequestConfig<T>) => void;
  99 +
  100 + /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
  101 + files?: { name?: string; file?: File; uri: string; }[];
  102 + /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
  103 + fileType?: HttpFileType;
  104 + /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
  105 + file?: File;
  106 + /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
  107 + filePath?: string;
  108 + /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
  109 + name?: string;
  110 + /** @desc 请求中其他额外的 form data */
  111 + formData?: HttpFormData;
  112 +}
  113 +
  114 +export interface HttpResponse<T = any, D = HttpTask> {
  115 + data: T;
  116 + statusCode: number;
  117 + header: HttpResponseHeader;
  118 + config: HttpRequestConfig<D>;
  119 + cookies: string[];
  120 + errMsg: string;
  121 + rawData: any;
  122 +}
  123 +
  124 +export interface HttpUploadResponse<T = any, D = HttpTask> {
  125 + data: T;
  126 + statusCode: number;
  127 + config: HttpRequestConfig<D>;
  128 + errMsg: string;
  129 + rawData: any;
  130 +}
  131 +
  132 +export interface HttpDownloadResponse extends HttpResponse {
  133 + tempFilePath: string;
  134 + apFilePath?: string;
  135 + filePath?: string;
  136 + fileContent?: string;
  137 +}
  138 +
  139 +export interface HttpError<T = any, D = HttpTask> {
  140 + data?: T;
  141 + statusCode?: number;
  142 + header?: HttpResponseHeader;
  143 + config: HttpRequestConfig<D>;
  144 + cookies?: string[];
  145 + errMsg: string;
  146 +}
  147 +
  148 +export interface HttpPromise<T = any> extends Promise<HttpResponse<T>> {
  149 +}
  150 +
  151 +export interface HttpInterceptorManager<V, E = V> {
  152 + use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: E) => T | Promise<E>): void;
  153 +
  154 + eject(id: number): void;
  155 +}
  156 +
  157 +export abstract class HttpRequestAbstract {
  158 + constructor(config?: HttpRequestConfig);
  159 +
  160 + interceptors: {
  161 + request: HttpInterceptorManager<HttpRequestConfig>;
  162 + response: HttpInterceptorManager<HttpResponse, HttpError>;
  163 + }
  164 +
  165 + request<T = any, R = HttpResponse<T>, D = HttpRequestTask>(config: HttpRequestConfig<D>): Promise<R>;
  166 +
  167 + get<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
  168 +
  169 + delete<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  170 +
  171 + head<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  172 +
  173 + options<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  174 +
  175 + post<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  176 +
  177 + put<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  178 +
  179 + config: HttpRequestConfig;
  180 +
  181 + setConfig<D = HttpTask>(onSend: (config: HttpRequestConfig<D>) => HttpRequestConfig<D>): void;
  182 +
  183 + connect<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  184 +
  185 + trace<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
  186 +
  187 + upload<T = any, R = HttpUploadResponse<T>, D = HttpUploadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
  188 +
  189 + download<T = any, R = HttpDownloadResponse<T>, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
  190 +
  191 + middleware<T = any, R = HttpResponse<T>, D = HttpTask>(config: HttpRequestConfig<D>): Promise<R>;
  192 +}
  193 +
  194 +declare class HttpRequest extends HttpRequestAbstract {
  195 +}
  196 +
  197 +export default HttpRequest;
... ...
uni_modules/uv-ui-tools/libs/luch-request/index.js 0 → 100644
  1 +import Request from './core/Request'
  2 +export default Request
... ...
uni_modules/uv-ui-tools/libs/luch-request/utils.js 0 → 100644
  1 +'use strict'
  2 +
  3 +// utils is a library of generic helper functions non-specific to axios
  4 +
  5 +var toString = Object.prototype.toString
  6 +
  7 +/**
  8 + * Determine if a value is an Array
  9 + *
  10 + * @param {Object} val The value to test
  11 + * @returns {boolean} True if value is an Array, otherwise false
  12 + */
  13 +export function isArray (val) {
  14 + return toString.call(val) === '[object Array]'
  15 +}
  16 +
  17 +
  18 +/**
  19 + * Determine if a value is an Object
  20 + *
  21 + * @param {Object} val The value to test
  22 + * @returns {boolean} True if value is an Object, otherwise false
  23 + */
  24 +export function isObject (val) {
  25 + return val !== null && typeof val === 'object'
  26 +}
  27 +
  28 +/**
  29 + * Determine if a value is a Date
  30 + *
  31 + * @param {Object} val The value to test
  32 + * @returns {boolean} True if value is a Date, otherwise false
  33 + */
  34 +export function isDate (val) {
  35 + return toString.call(val) === '[object Date]'
  36 +}
  37 +
  38 +/**
  39 + * Determine if a value is a URLSearchParams object
  40 + *
  41 + * @param {Object} val The value to test
  42 + * @returns {boolean} True if value is a URLSearchParams object, otherwise false
  43 + */
  44 +export function isURLSearchParams (val) {
  45 + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
  46 +}
  47 +
  48 +
  49 +/**
  50 + * Iterate over an Array or an Object invoking a function for each item.
  51 + *
  52 + * If `obj` is an Array callback will be called passing
  53 + * the value, index, and complete array for each item.
  54 + *
  55 + * If 'obj' is an Object callback will be called passing
  56 + * the value, key, and complete object for each property.
  57 + *
  58 + * @param {Object|Array} obj The object to iterate
  59 + * @param {Function} fn The callback to invoke for each item
  60 + */
  61 +export function forEach (obj, fn) {
  62 + // Don't bother if no value provided
  63 + if (obj === null || typeof obj === 'undefined') {
  64 + return
  65 + }
  66 +
  67 + // Force an array if not already something iterable
  68 + if (typeof obj !== 'object') {
  69 + /*eslint no-param-reassign:0*/
  70 + obj = [obj]
  71 + }
  72 +
  73 + if (isArray(obj)) {
  74 + // Iterate over array values
  75 + for (var i = 0, l = obj.length; i < l; i++) {
  76 + fn.call(null, obj[i], i, obj)
  77 + }
  78 + } else {
  79 + // Iterate over object keys
  80 + for (var key in obj) {
  81 + if (Object.prototype.hasOwnProperty.call(obj, key)) {
  82 + fn.call(null, obj[key], key, obj)
  83 + }
  84 + }
  85 + }
  86 +}
  87 +
  88 +/**
  89 + * 是否为boolean 值
  90 + * @param val
  91 + * @returns {boolean}
  92 + */
  93 +export function isBoolean(val) {
  94 + return typeof val === 'boolean'
  95 +}
  96 +
  97 +/**
  98 + * 是否为真正的对象{} new Object
  99 + * @param {any} obj - 检测的对象
  100 + * @returns {boolean}
  101 + */
  102 +export function isPlainObject(obj) {
  103 + return Object.prototype.toString.call(obj) === '[object Object]'
  104 +}
  105 +
  106 +
  107 +
  108 +/**
  109 + * Function equal to merge with the difference being that no reference
  110 + * to original objects is kept.
  111 + *
  112 + * @see merge
  113 + * @param {Object} obj1 Object to merge
  114 + * @returns {Object} Result of all merge properties
  115 + */
  116 +export function deepMerge(/* obj1, obj2, obj3, ... */) {
  117 + let result = {}
  118 + function assignValue(val, key) {
  119 + if (typeof result[key] === 'object' && typeof val === 'object') {
  120 + result[key] = deepMerge(result[key], val)
  121 + } else if (typeof val === 'object') {
  122 + result[key] = deepMerge({}, val)
  123 + } else {
  124 + result[key] = val
  125 + }
  126 + }
  127 + for (let i = 0, l = arguments.length; i < l; i++) {
  128 + forEach(arguments[i], assignValue)
  129 + }
  130 + return result
  131 +}
  132 +
  133 +export function isUndefined (val) {
  134 + return typeof val === 'undefined'
  135 +}
... ...
uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js 0 → 100644
  1 +/* eslint-disable */
  2 +var clone = (function() {
  3 + 'use strict';
  4 +
  5 + function _instanceof(obj, type) {
  6 + return type != null && obj instanceof type;
  7 + }
  8 +
  9 + var nativeMap;
  10 + try {
  11 + nativeMap = Map;
  12 + } catch(_) {
  13 + // maybe a reference error because no `Map`. Give it a dummy value that no
  14 + // value will ever be an instanceof.
  15 + nativeMap = function() {};
  16 + }
  17 +
  18 + var nativeSet;
  19 + try {
  20 + nativeSet = Set;
  21 + } catch(_) {
  22 + nativeSet = function() {};
  23 + }
  24 +
  25 + var nativePromise;
  26 + try {
  27 + nativePromise = Promise;
  28 + } catch(_) {
  29 + nativePromise = function() {};
  30 + }
  31 +
  32 + /**
  33 + * Clones (copies) an Object using deep copying.
  34 + *
  35 + * This function supports circular references by default, but if you are certain
  36 + * there are no circular references in your object, you can save some CPU time
  37 + * by calling clone(obj, false).
  38 + *
  39 + * Caution: if `circular` is false and `parent` contains circular references,
  40 + * your program may enter an infinite loop and crash.
  41 + *
  42 + * @param `parent` - the object to be cloned
  43 + * @param `circular` - set to true if the object to be cloned may contain
  44 + * circular references. (optional - true by default)
  45 + * @param `depth` - set to a number if the object is only to be cloned to
  46 + * a particular depth. (optional - defaults to Infinity)
  47 + * @param `prototype` - sets the prototype to be used when cloning an object.
  48 + * (optional - defaults to parent prototype).
  49 + * @param `includeNonEnumerable` - set to true if the non-enumerable properties
  50 + * should be cloned as well. Non-enumerable properties on the prototype
  51 + * chain will be ignored. (optional - false by default)
  52 + */
  53 + function clone(parent, circular, depth, prototype, includeNonEnumerable) {
  54 + if (typeof circular === 'object') {
  55 + depth = circular.depth;
  56 + prototype = circular.prototype;
  57 + includeNonEnumerable = circular.includeNonEnumerable;
  58 + circular = circular.circular;
  59 + }
  60 + // maintain two arrays for circular references, where corresponding parents
  61 + // and children have the same index
  62 + var allParents = [];
  63 + var allChildren = [];
  64 +
  65 + var useBuffer = typeof Buffer != 'undefined';
  66 +
  67 + if (typeof circular == 'undefined')
  68 + circular = true;
  69 +
  70 + if (typeof depth == 'undefined')
  71 + depth = Infinity;
  72 +
  73 + // recurse this function so we don't reset allParents and allChildren
  74 + function _clone(parent, depth) {
  75 + // cloning null always returns null
  76 + if (parent === null)
  77 + return null;
  78 +
  79 + if (depth === 0)
  80 + return parent;
  81 +
  82 + var child;
  83 + var proto;
  84 + if (typeof parent != 'object') {
  85 + return parent;
  86 + }
  87 +
  88 + if (_instanceof(parent, nativeMap)) {
  89 + child = new nativeMap();
  90 + } else if (_instanceof(parent, nativeSet)) {
  91 + child = new nativeSet();
  92 + } else if (_instanceof(parent, nativePromise)) {
  93 + child = new nativePromise(function (resolve, reject) {
  94 + parent.then(function(value) {
  95 + resolve(_clone(value, depth - 1));
  96 + }, function(err) {
  97 + reject(_clone(err, depth - 1));
  98 + });
  99 + });
  100 + } else if (clone.__isArray(parent)) {
  101 + child = [];
  102 + } else if (clone.__isRegExp(parent)) {
  103 + child = new RegExp(parent.source, __getRegExpFlags(parent));
  104 + if (parent.lastIndex) child.lastIndex = parent.lastIndex;
  105 + } else if (clone.__isDate(parent)) {
  106 + child = new Date(parent.getTime());
  107 + } else if (useBuffer && Buffer.isBuffer(parent)) {
  108 + if (Buffer.from) {
  109 + // Node.js >= 5.10.0
  110 + child = Buffer.from(parent);
  111 + } else {
  112 + // Older Node.js versions
  113 + child = new Buffer(parent.length);
  114 + parent.copy(child);
  115 + }
  116 + return child;
  117 + } else if (_instanceof(parent, Error)) {
  118 + child = Object.create(parent);
  119 + } else {
  120 + if (typeof prototype == 'undefined') {
  121 + proto = Object.getPrototypeOf(parent);
  122 + child = Object.create(proto);
  123 + }
  124 + else {
  125 + child = Object.create(prototype);
  126 + proto = prototype;
  127 + }
  128 + }
  129 +
  130 + if (circular) {
  131 + var index = allParents.indexOf(parent);
  132 +
  133 + if (index != -1) {
  134 + return allChildren[index];
  135 + }
  136 + allParents.push(parent);
  137 + allChildren.push(child);
  138 + }
  139 +
  140 + if (_instanceof(parent, nativeMap)) {
  141 + parent.forEach(function(value, key) {
  142 + var keyChild = _clone(key, depth - 1);
  143 + var valueChild = _clone(value, depth - 1);
  144 + child.set(keyChild, valueChild);
  145 + });
  146 + }
  147 + if (_instanceof(parent, nativeSet)) {
  148 + parent.forEach(function(value) {
  149 + var entryChild = _clone(value, depth - 1);
  150 + child.add(entryChild);
  151 + });
  152 + }
  153 +
  154 + for (var i in parent) {
  155 + var attrs = Object.getOwnPropertyDescriptor(parent, i);
  156 + if (attrs) {
  157 + child[i] = _clone(parent[i], depth - 1);
  158 + }
  159 +
  160 + try {
  161 + var objProperty = Object.getOwnPropertyDescriptor(parent, i);
  162 + if (objProperty.set === 'undefined') {
  163 + // no setter defined. Skip cloning this property
  164 + continue;
  165 + }
  166 + child[i] = _clone(parent[i], depth - 1);
  167 + } catch(e){
  168 + if (e instanceof TypeError) {
  169 + // when in strict mode, TypeError will be thrown if child[i] property only has a getter
  170 + // we can't do anything about this, other than inform the user that this property cannot be set.
  171 + continue
  172 + } else if (e instanceof ReferenceError) {
  173 + //this may happen in non strict mode
  174 + continue
  175 + }
  176 + }
  177 +
  178 + }
  179 +
  180 + if (Object.getOwnPropertySymbols) {
  181 + var symbols = Object.getOwnPropertySymbols(parent);
  182 + for (var i = 0; i < symbols.length; i++) {
  183 + // Don't need to worry about cloning a symbol because it is a primitive,
  184 + // like a number or string.
  185 + var symbol = symbols[i];
  186 + var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
  187 + if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
  188 + continue;
  189 + }
  190 + child[symbol] = _clone(parent[symbol], depth - 1);
  191 + Object.defineProperty(child, symbol, descriptor);
  192 + }
  193 + }
  194 +
  195 + if (includeNonEnumerable) {
  196 + var allPropertyNames = Object.getOwnPropertyNames(parent);
  197 + for (var i = 0; i < allPropertyNames.length; i++) {
  198 + var propertyName = allPropertyNames[i];
  199 + var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
  200 + if (descriptor && descriptor.enumerable) {
  201 + continue;
  202 + }
  203 + child[propertyName] = _clone(parent[propertyName], depth - 1);
  204 + Object.defineProperty(child, propertyName, descriptor);
  205 + }
  206 + }
  207 +
  208 + return child;
  209 + }
  210 +
  211 + return _clone(parent, depth);
  212 + }
  213 +
  214 + /**
  215 + * Simple flat clone using prototype, accepts only objects, usefull for property
  216 + * override on FLAT configuration object (no nested props).
  217 + *
  218 + * USE WITH CAUTION! This may not behave as you wish if you do not know how this
  219 + * works.
  220 + */
  221 + clone.clonePrototype = function clonePrototype(parent) {
  222 + if (parent === null)
  223 + return null;
  224 +
  225 + var c = function () {};
  226 + c.prototype = parent;
  227 + return new c();
  228 + };
  229 +
  230 +// private utility functions
  231 +
  232 + function __objToStr(o) {
  233 + return Object.prototype.toString.call(o);
  234 + }
  235 + clone.__objToStr = __objToStr;
  236 +
  237 + function __isDate(o) {
  238 + return typeof o === 'object' && __objToStr(o) === '[object Date]';
  239 + }
  240 + clone.__isDate = __isDate;
  241 +
  242 + function __isArray(o) {
  243 + return typeof o === 'object' && __objToStr(o) === '[object Array]';
  244 + }
  245 + clone.__isArray = __isArray;
  246 +
  247 + function __isRegExp(o) {
  248 + return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
  249 + }
  250 + clone.__isRegExp = __isRegExp;
  251 +
  252 + function __getRegExpFlags(re) {
  253 + var flags = '';
  254 + if (re.global) flags += 'g';
  255 + if (re.ignoreCase) flags += 'i';
  256 + if (re.multiline) flags += 'm';
  257 + return flags;
  258 + }
  259 + clone.__getRegExpFlags = __getRegExpFlags;
  260 +
  261 + return clone;
  262 +})();
  263 +
  264 +export default clone
... ...
uni_modules/uv-ui-tools/libs/mixin/button.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + lang: String,
  4 + sessionFrom: String,
  5 + sendMessageTitle: String,
  6 + sendMessagePath: String,
  7 + sendMessageImg: String,
  8 + showMessageCard: Boolean,
  9 + appParameter: String,
  10 + formType: String,
  11 + openType: String
  12 + }
  13 +}
... ...
uni_modules/uv-ui-tools/libs/mixin/mixin.js 0 → 100644
  1 +import * as index from '../function/index.js';
  2 +import * as test from '../function/test.js';
  3 +import route from '../util/route.js';
  4 +import debounce from '../function/debounce.js';
  5 +import throttle from '../function/throttle.js';
  6 +export default {
  7 + // 定义每个组件都可能需要用到的外部样式以及类名
  8 + props: {
  9 + // 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
  10 + customStyle: {
  11 + type: [Object, String],
  12 + default: () => ({})
  13 + },
  14 + customClass: {
  15 + type: String,
  16 + default: ''
  17 + },
  18 + // 跳转的页面路径
  19 + url: {
  20 + type: String,
  21 + default: ''
  22 + },
  23 + // 页面跳转的类型
  24 + linkType: {
  25 + type: String,
  26 + default: 'navigateTo'
  27 + }
  28 + },
  29 + data() {
  30 + return {}
  31 + },
  32 + onLoad() {
  33 + // getRect挂载到$uv上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
  34 + this.$uv.getRect = this.$uvGetRect
  35 + },
  36 + created() {
  37 + // 组件当中,只有created声明周期,为了能在组件使用,故也在created中将方法挂载到$uv
  38 + this.$uv.getRect = this.$uvGetRect
  39 + },
  40 + computed: {
  41 + $uv() {
  42 + return {
  43 + ...index,
  44 + test,
  45 + route,
  46 + debounce,
  47 + throttle,
  48 + unit: uni?.$uv?.config?.unit
  49 + }
  50 + },
  51 + /**
  52 + * 生成bem规则类名
  53 + * 由于微信小程序,H5,nvue之间绑定class的差异,无法通过:class="[bem()]"的形式进行同用
  54 + * 故采用如下折中做法,最后返回的是数组(一般平台)或字符串(支付宝和字节跳动平台),类似['a', 'b', 'c']或'a b c'的形式
  55 + * @param {String} name 组件名称
  56 + * @param {Array} fixed 一直会存在的类名
  57 + * @param {Array} change 会根据变量值为true或者false而出现或者隐藏的类名
  58 + * @returns {Array|string}
  59 + */
  60 + bem() {
  61 + return function(name, fixed, change) {
  62 + // 类名前缀
  63 + const prefix = `uv-${name}--`
  64 + const classes = {}
  65 + if (fixed) {
  66 + fixed.map((item) => {
  67 + // 这里的类名,会一直存在
  68 + classes[prefix + this[item]] = true
  69 + })
  70 + }
  71 + if (change) {
  72 + change.map((item) => {
  73 + // 这里的类名,会根据this[item]的值为true或者false,而进行添加或者移除某一个类
  74 + this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item])
  75 + })
  76 + }
  77 + return Object.keys(classes)
  78 + // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
  79 + // #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK || MP-BAIDU
  80 + .join(' ')
  81 + // #endif
  82 + }
  83 + }
  84 + },
  85 + methods: {
  86 + // 跳转某一个页面
  87 + openPage(urlKey = 'url') {
  88 + const url = this[urlKey]
  89 + if (url) {
  90 + // 执行类似uni.navigateTo的方法
  91 + uni[this.linkType]({
  92 + url
  93 + })
  94 + }
  95 + },
  96 + // 查询节点信息
  97 + // 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
  98 + // 解决办法为在组件根部再套一个没有任何作用的view元素
  99 + $uvGetRect(selector, all) {
  100 + return new Promise((resolve) => {
  101 + uni.createSelectorQuery()
  102 + .in(this)[all ? 'selectAll' : 'select'](selector)
  103 + .boundingClientRect((rect) => {
  104 + if (all && Array.isArray(rect) && rect.length) {
  105 + resolve(rect)
  106 + }
  107 + if (!all && rect) {
  108 + resolve(rect)
  109 + }
  110 + })
  111 + .exec()
  112 + })
  113 + },
  114 + getParentData(parentName = '') {
  115 + // 避免在created中去定义parent变量
  116 + if (!this.parent) this.parent = {}
  117 + // 这里的本质原理是,通过获取父组件实例(也即类似uv-radio的父组件uv-radio-group的this)
  118 + // 将父组件this中对应的参数,赋值给本组件(uv-radio的this)的parentData对象中对应的属性
  119 + // 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
  120 + // 此处并不会自动更新子组件的数据,而是依赖父组件uv-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
  121 + this.parent = this.$uv.$parent.call(this, parentName)
  122 + if (this.parent.children) {
  123 + // 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
  124 + this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
  125 + }
  126 + if (this.parent && this.parentData) {
  127 + // 历遍parentData中的属性,将parent中的同名属性赋值给parentData
  128 + Object.keys(this.parentData).map((key) => {
  129 + this.parentData[key] = this.parent[key]
  130 + })
  131 + }
  132 + },
  133 + // 阻止事件冒泡
  134 + preventEvent(e) {
  135 + e && typeof(e.stopPropagation) === 'function' && e.stopPropagation()
  136 + },
  137 + // 空操作
  138 + noop(e) {
  139 + this.preventEvent(e)
  140 + }
  141 + },
  142 + onReachBottom() {
  143 + uni.$emit('uvOnReachBottom')
  144 + },
  145 + beforeDestroy() {
  146 + // 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
  147 + // 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
  148 + if (this.parent && test.array(this.parent.children)) {
  149 + // 组件销毁时,移除父组件中的children数组中对应的实例
  150 + const childrenList = this.parent.children
  151 + childrenList.map((child, index) => {
  152 + // 如果相等,则移除
  153 + if (child === this) {
  154 + childrenList.splice(index, 1)
  155 + }
  156 + })
  157 + }
  158 + },
  159 + // 兼容vue3
  160 + unmounted() {
  161 + if (this.parent && test.array(this.parent.children)) {
  162 + // 组件销毁时,移除父组件中的children数组中对应的实例
  163 + const childrenList = this.parent.children
  164 + childrenList.map((child, index) => {
  165 + // 如果相等,则移除
  166 + if (child === this) {
  167 + childrenList.splice(index, 1)
  168 + }
  169 + })
  170 + }
  171 + }
  172 +}
0 173 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/libs/mixin/mpMixin.js 0 → 100644
  1 +export default {
  2 + // #ifdef MP-WEIXIN
  3 + // 将自定义节点设置成虚拟的(去掉自定义组件包裹层),更加接近Vue组件的表现,能更好的使用flex属性
  4 + options: {
  5 + virtualHost: true
  6 + }
  7 + // #endif
  8 +}
0 9 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/libs/mixin/mpShare.js 0 → 100644
  1 +export default {
  2 + onLoad() {
  3 + // 设置默认的转发参数
  4 + uni.$uv.mpShare = {
  5 + title: '', // 默认为小程序名称
  6 + path: '', // 默认为当前页面路径
  7 + imageUrl: '' // 默认为当前页面的截图
  8 + }
  9 + },
  10 + onShareAppMessage() {
  11 + return uni.$uv.mpShare
  12 + }
  13 +}
0 14 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/libs/mixin/openType.js 0 → 100644
  1 +export default {
  2 + props: {
  3 + openType: String
  4 + },
  5 + emits: ['getphonenumber','getuserinfo','error','opensetting','launchapp','contact','chooseavatar','addgroupapp','chooseaddress','subscribe','login','im'],
  6 + methods: {
  7 + onGetPhoneNumber(event) {
  8 + this.$emit('getphonenumber', event.detail)
  9 + },
  10 + onGetUserInfo(event) {
  11 + this.$emit('getuserinfo', event.detail)
  12 + },
  13 + onError(event) {
  14 + this.$emit('error', event.detail)
  15 + },
  16 + onOpenSetting(event) {
  17 + this.$emit('opensetting', event.detail)
  18 + },
  19 + onLaunchApp(event) {
  20 + this.$emit('launchapp', event.detail)
  21 + },
  22 + onContact(event) {
  23 + this.$emit('contact', event.detail)
  24 + },
  25 + onChooseavatar(event) {
  26 + this.$emit('chooseavatar', event.detail)
  27 + },
  28 + onAgreeprivacyauthorization(event) {
  29 + this.$emit('agreeprivacyauthorization', event.detail)
  30 + },
  31 + onAddgroupapp(event) {
  32 + this.$emit('addgroupapp', event.detail)
  33 + },
  34 + onChooseaddress(event) {
  35 + this.$emit('chooseaddress', event.detail)
  36 + },
  37 + onSubscribe(event) {
  38 + this.$emit('subscribe', event.detail)
  39 + },
  40 + onLogin(event) {
  41 + this.$emit('login', event.detail)
  42 + },
  43 + onIm(event) {
  44 + this.$emit('im', event.detail)
  45 + }
  46 + }
  47 +}
... ...
uni_modules/uv-ui-tools/libs/mixin/touch.js 0 → 100644
  1 +const MIN_DISTANCE = 10
  2 +
  3 +function getDirection(x, y) {
  4 + if (x > y && x > MIN_DISTANCE) {
  5 + return 'horizontal'
  6 + }
  7 + if (y > x && y > MIN_DISTANCE) {
  8 + return 'vertical'
  9 + }
  10 + return ''
  11 +}
  12 +
  13 +export default {
  14 + methods: {
  15 + getTouchPoint(e) {
  16 + if (!e) {
  17 + return {
  18 + x: 0,
  19 + y: 0
  20 + }
  21 + } if (e.touches && e.touches[0]) {
  22 + return {
  23 + x: e.touches[0].pageX,
  24 + y: e.touches[0].pageY
  25 + }
  26 + } if (e.changedTouches && e.changedTouches[0]) {
  27 + return {
  28 + x: e.changedTouches[0].pageX,
  29 + y: e.changedTouches[0].pageY
  30 + }
  31 + }
  32 + return {
  33 + x: e.clientX || 0,
  34 + y: e.clientY || 0
  35 + }
  36 + },
  37 + resetTouchStatus() {
  38 + this.direction = ''
  39 + this.deltaX = 0
  40 + this.deltaY = 0
  41 + this.offsetX = 0
  42 + this.offsetY = 0
  43 + },
  44 + touchStart(event) {
  45 + this.resetTouchStatus()
  46 + const touch = this.getTouchPoint(event)
  47 + this.startX = touch.x
  48 + this.startY = touch.y
  49 + },
  50 + touchMove(event) {
  51 + const touch = this.getTouchPoint(event)
  52 + this.deltaX = touch.x - this.startX
  53 + this.deltaY = touch.y - this.startY
  54 + this.offsetX = Math.abs(this.deltaX)
  55 + this.offsetY = Math.abs(this.deltaY)
  56 + this.direction = this.direction || getDirection(this.offsetX, this.offsetY)
  57 + }
  58 + }
  59 +}
... ...
uni_modules/uv-ui-tools/libs/util/dayjs.js 0 → 100644
  1 +var __getOwnPropNames = Object.getOwnPropertyNames;
  2 +var __commonJS = (cb, mod) => function __require() {
  3 + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  4 +};
  5 +
  6 +var require_dayjs_min = __commonJS({
  7 + "uvuidayjs"(exports, module) {
  8 + !function(t, e) {
  9 + "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
  10 + }(exports, function() {
  11 + "use strict";
  12 + var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", f = "month", h = "quarter", c = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
  13 + var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
  14 + return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
  15 + } }, m = function(t2, e2, n2) {
  16 + var r2 = String(t2);
  17 + return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
  18 + }, v = { s: m, z: function(t2) {
  19 + var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
  20 + return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
  21 + }, m: function t2(e2, n2) {
  22 + if (e2.date() < n2.date())
  23 + return -t2(n2, e2);
  24 + var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, f), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), f);
  25 + return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
  26 + }, a: function(t2) {
  27 + return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
  28 + }, p: function(t2) {
  29 + return { M: f, y: c, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: h }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
  30 + }, u: function(t2) {
  31 + return void 0 === t2;
  32 + } }, g = "en", D = {};
  33 + D[g] = M;
  34 + var p = function(t2) {
  35 + return t2 instanceof _;
  36 + }, S = function t2(e2, n2, r2) {
  37 + var i2;
  38 + if (!e2)
  39 + return g;
  40 + if ("string" == typeof e2) {
  41 + var s2 = e2.toLowerCase();
  42 + D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
  43 + var u2 = e2.split("-");
  44 + if (!i2 && u2.length > 1)
  45 + return t2(u2[0]);
  46 + } else {
  47 + var a2 = e2.name;
  48 + D[a2] = e2, i2 = a2;
  49 + }
  50 + return !r2 && i2 && (g = i2), i2 || !r2 && g;
  51 + }, w = function(t2, e2) {
  52 + if (p(t2))
  53 + return t2.clone();
  54 + var n2 = "object" == typeof e2 ? e2 : {};
  55 + return n2.date = t2, n2.args = arguments, new _(n2);
  56 + }, O = v;
  57 + O.l = S, O.i = p, O.w = function(t2, e2) {
  58 + return w(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
  59 + };
  60 + var _ = function() {
  61 + function M2(t2) {
  62 + this.$L = S(t2.locale, null, true), this.parse(t2);
  63 + }
  64 + var m2 = M2.prototype;
  65 + return m2.parse = function(t2) {
  66 + this.$d = function(t3) {
  67 + var e2 = t3.date, n2 = t3.utc;
  68 + if (null === e2)
  69 + return new Date(NaN);
  70 + if (O.u(e2))
  71 + return new Date();
  72 + if (e2 instanceof Date)
  73 + return new Date(e2);
  74 + if ("string" == typeof e2 && !/Z$/i.test(e2)) {
  75 + var r2 = e2.match($);
  76 + if (r2) {
  77 + var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
  78 + return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
  79 + }
  80 + }
  81 + return new Date(e2);
  82 + }(t2), this.$x = t2.x || {}, this.init();
  83 + }, m2.init = function() {
  84 + var t2 = this.$d;
  85 + this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
  86 + }, m2.$utils = function() {
  87 + return O;
  88 + }, m2.isValid = function() {
  89 + return !(this.$d.toString() === l);
  90 + }, m2.isSame = function(t2, e2) {
  91 + var n2 = w(t2);
  92 + return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
  93 + }, m2.isAfter = function(t2, e2) {
  94 + return w(t2) < this.startOf(e2);
  95 + }, m2.isBefore = function(t2, e2) {
  96 + return this.endOf(e2) < w(t2);
  97 + }, m2.$g = function(t2, e2, n2) {
  98 + return O.u(t2) ? this[e2] : this.set(n2, t2);
  99 + }, m2.unix = function() {
  100 + return Math.floor(this.valueOf() / 1e3);
  101 + }, m2.valueOf = function() {
  102 + return this.$d.getTime();
  103 + }, m2.startOf = function(t2, e2) {
  104 + var n2 = this, r2 = !!O.u(e2) || e2, h2 = O.p(t2), l2 = function(t3, e3) {
  105 + var i2 = O.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
  106 + return r2 ? i2 : i2.endOf(a);
  107 + }, $2 = function(t3, e3) {
  108 + return O.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
  109 + }, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
  110 + switch (h2) {
  111 + case c:
  112 + return r2 ? l2(1, 0) : l2(31, 11);
  113 + case f:
  114 + return r2 ? l2(1, M3) : l2(0, M3 + 1);
  115 + case o:
  116 + var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
  117 + return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
  118 + case a:
  119 + case d:
  120 + return $2(v2 + "Hours", 0);
  121 + case u:
  122 + return $2(v2 + "Minutes", 1);
  123 + case s:
  124 + return $2(v2 + "Seconds", 2);
  125 + case i:
  126 + return $2(v2 + "Milliseconds", 3);
  127 + default:
  128 + return this.clone();
  129 + }
  130 + }, m2.endOf = function(t2) {
  131 + return this.startOf(t2, false);
  132 + }, m2.$set = function(t2, e2) {
  133 + var n2, o2 = O.p(t2), h2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = h2 + "Date", n2[d] = h2 + "Date", n2[f] = h2 + "Month", n2[c] = h2 + "FullYear", n2[u] = h2 + "Hours", n2[s] = h2 + "Minutes", n2[i] = h2 + "Seconds", n2[r] = h2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
  134 + if (o2 === f || o2 === c) {
  135 + var y2 = this.clone().set(d, 1);
  136 + y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
  137 + } else
  138 + l2 && this.$d[l2]($2);
  139 + return this.init(), this;
  140 + }, m2.set = function(t2, e2) {
  141 + return this.clone().$set(t2, e2);
  142 + }, m2.get = function(t2) {
  143 + return this[O.p(t2)]();
  144 + }, m2.add = function(r2, h2) {
  145 + var d2, l2 = this;
  146 + r2 = Number(r2);
  147 + var $2 = O.p(h2), y2 = function(t2) {
  148 + var e2 = w(l2);
  149 + return O.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
  150 + };
  151 + if ($2 === f)
  152 + return this.set(f, this.$M + r2);
  153 + if ($2 === c)
  154 + return this.set(c, this.$y + r2);
  155 + if ($2 === a)
  156 + return y2(1);
  157 + if ($2 === o)
  158 + return y2(7);
  159 + var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
  160 + return O.w(m3, this);
  161 + }, m2.subtract = function(t2, e2) {
  162 + return this.add(-1 * t2, e2);
  163 + }, m2.format = function(t2) {
  164 + var e2 = this, n2 = this.$locale();
  165 + if (!this.isValid())
  166 + return n2.invalidDate || l;
  167 + var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = O.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, f2 = n2.months, h2 = function(t3, n3, i3, s3) {
  168 + return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
  169 + }, c2 = function(t3) {
  170 + return O.s(s2 % 12 || 12, t3, "0");
  171 + }, d2 = n2.meridiem || function(t3, e3, n3) {
  172 + var r3 = t3 < 12 ? "AM" : "PM";
  173 + return n3 ? r3.toLowerCase() : r3;
  174 + }, $2 = { YY: String(this.$y).slice(-2), YYYY: this.$y, M: a2 + 1, MM: O.s(a2 + 1, 2, "0"), MMM: h2(n2.monthsShort, a2, f2, 3), MMMM: h2(f2, a2), D: this.$D, DD: O.s(this.$D, 2, "0"), d: String(this.$W), dd: h2(n2.weekdaysMin, this.$W, o2, 2), ddd: h2(n2.weekdaysShort, this.$W, o2, 3), dddd: o2[this.$W], H: String(s2), HH: O.s(s2, 2, "0"), h: c2(1), hh: c2(2), a: d2(s2, u2, true), A: d2(s2, u2, false), m: String(u2), mm: O.s(u2, 2, "0"), s: String(this.$s), ss: O.s(this.$s, 2, "0"), SSS: O.s(this.$ms, 3, "0"), Z: i2 };
  175 + return r2.replace(y, function(t3, e3) {
  176 + return e3 || $2[t3] || i2.replace(":", "");
  177 + });
  178 + }, m2.utcOffset = function() {
  179 + return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
  180 + }, m2.diff = function(r2, d2, l2) {
  181 + var $2, y2 = O.p(d2), M3 = w(r2), m3 = (M3.utcOffset() - this.utcOffset()) * e, v2 = this - M3, g2 = O.m(this, M3);
  182 + return g2 = ($2 = {}, $2[c] = g2 / 12, $2[f] = g2, $2[h] = g2 / 3, $2[o] = (v2 - m3) / 6048e5, $2[a] = (v2 - m3) / 864e5, $2[u] = v2 / n, $2[s] = v2 / e, $2[i] = v2 / t, $2)[y2] || v2, l2 ? g2 : O.a(g2);
  183 + }, m2.daysInMonth = function() {
  184 + return this.endOf(f).$D;
  185 + }, m2.$locale = function() {
  186 + return D[this.$L];
  187 + }, m2.locale = function(t2, e2) {
  188 + if (!t2)
  189 + return this.$L;
  190 + var n2 = this.clone(), r2 = S(t2, e2, true);
  191 + return r2 && (n2.$L = r2), n2;
  192 + }, m2.clone = function() {
  193 + return O.w(this.$d, this);
  194 + }, m2.toDate = function() {
  195 + return new Date(this.valueOf());
  196 + }, m2.toJSON = function() {
  197 + return this.isValid() ? this.toISOString() : null;
  198 + }, m2.toISOString = function() {
  199 + return this.$d.toISOString();
  200 + }, m2.toString = function() {
  201 + return this.$d.toUTCString();
  202 + }, M2;
  203 + }(), T = _.prototype;
  204 + return w.prototype = T, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", f], ["$y", c], ["$D", d]].forEach(function(t2) {
  205 + T[t2[1]] = function(e2) {
  206 + return this.$g(e2, t2[0], t2[1]);
  207 + };
  208 + }), w.extend = function(t2, e2) {
  209 + return t2.$i || (t2(e2, _, w), t2.$i = true), w;
  210 + }, w.locale = S, w.isDayjs = p, w.unix = function(t2) {
  211 + return w(1e3 * t2);
  212 + }, w.en = D[g], w.Ls = D, w.p = {}, w;
  213 + });
  214 + }
  215 +});
  216 +export default require_dayjs_min();
... ...
uni_modules/uv-ui-tools/libs/util/route.js 0 → 100644
  1 +/**
  2 + * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
  3 + * 并且带有路由拦截功能
  4 + */
  5 +import { queryParams, deepMerge, page } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
  6 +class Router {
  7 + constructor() {
  8 + // 原始属性定义
  9 + this.config = {
  10 + type: 'navigateTo',
  11 + url: '',
  12 + delta: 1, // navigateBack页面后退时,回退的层数
  13 + params: {}, // 传递的参数
  14 + animationType: 'pop-in', // 窗口动画,只在APP有效
  15 + animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
  16 + intercept: false ,// 是否需要拦截
  17 + events: {} // 页面间通信接口,用于监听被打开页面发送到当前页面的数据。hbuilderx 2.8.9+ 开始支持。
  18 + }
  19 + // 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
  20 + // 这里在构造函数中进行this绑定
  21 + this.route = this.route.bind(this)
  22 + }
  23 +
  24 + // 判断url前面是否有"/",如果没有则加上,否则无法跳转
  25 + addRootPath(url) {
  26 + return url[0] === '/' ? url : `/${url}`
  27 + }
  28 +
  29 + // 整合路由参数
  30 + mixinParam(url, params) {
  31 + url = url && this.addRootPath(url)
  32 +
  33 + // 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
  34 + // 如果有url中有get参数,转换后无需带上"?"
  35 + let query = ''
  36 + if (/.*\/.*\?.*=.*/.test(url)) {
  37 + // object对象转为get类型的参数
  38 + query = queryParams(params, false)
  39 + // 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
  40 + return url += `&${query}`
  41 + }
  42 + // 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
  43 + query = queryParams(params)
  44 + return url += query
  45 + }
  46 +
  47 + // 对外的方法名称
  48 + async route(options = {}, params = {}) {
  49 + // 合并用户的配置和内部的默认配置
  50 + let mergeConfig = {}
  51 +
  52 + if (typeof options === 'string') {
  53 + // 如果options为字符串,则为route(url, params)的形式
  54 + mergeConfig.url = this.mixinParam(options, params)
  55 + mergeConfig.type = 'navigateTo'
  56 + } else {
  57 + mergeConfig = deepMerge(this.config, options)
  58 + // 否则正常使用mergeConfig中的url和params进行拼接
  59 + mergeConfig.url = this.mixinParam(options.url, options.params)
  60 + }
  61 + // 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
  62 + if (mergeConfig.url === page()) return
  63 +
  64 + if (params.intercept) {
  65 + mergeConfig.intercept = params.intercept
  66 + }
  67 + // params参数也带给拦截器
  68 + mergeConfig.params = params
  69 + // 合并内外部参数
  70 + mergeConfig = deepMerge(this.config, mergeConfig)
  71 + // 判断用户是否定义了拦截器
  72 + if (typeof mergeConfig.intercept === 'function') {
  73 + // 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
  74 + const isNext = await new Promise((resolve, reject) => {
  75 + mergeConfig.intercept(mergeConfig, resolve)
  76 + })
  77 + // 如果isNext为true,则执行路由跳转
  78 + isNext && this.openPage(mergeConfig)
  79 + } else {
  80 + this.openPage(mergeConfig)
  81 + }
  82 + }
  83 +
  84 + // 执行路由跳转
  85 + openPage(config) {
  86 + // 解构参数
  87 + const {
  88 + url,
  89 + type,
  90 + delta,
  91 + animationType,
  92 + animationDuration,
  93 + events
  94 + } = config
  95 + if (config.type == 'navigateTo' || config.type == 'to') {
  96 + uni.navigateTo({
  97 + url,
  98 + animationType,
  99 + animationDuration,
  100 + events
  101 + })
  102 + }
  103 + if (config.type == 'redirectTo' || config.type == 'redirect') {
  104 + uni.redirectTo({
  105 + url
  106 + })
  107 + }
  108 + if (config.type == 'switchTab' || config.type == 'tab') {
  109 + uni.switchTab({
  110 + url
  111 + })
  112 + }
  113 + if (config.type == 'reLaunch' || config.type == 'launch') {
  114 + uni.reLaunch({
  115 + url
  116 + })
  117 + }
  118 + if (config.type == 'navigateBack' || config.type == 'back') {
  119 + uni.navigateBack({
  120 + delta
  121 + })
  122 + }
  123 + }
  124 +}
  125 +
  126 +export default (new Router()).route
0 127 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/package.json 0 → 100644
  1 +{
  2 + "id": "uv-ui-tools",
  3 + "displayName": "uv-ui-tools 工具集 全面兼容vue3+2、app、h5、小程序等多端",
  4 + "version": "1.1.25",
  5 + "description": "uv-ui-tools,集成工具库,强大的Http请求封装,清晰的文档说明,开箱即用。方便使用,可以全局使用",
  6 + "keywords": [
  7 + "uv-ui-tools,uv-ui组件库,工具集,uvui,uView2.x"
  8 +],
  9 + "repository": "",
  10 + "engines": {
  11 + "HBuilderX": "^3.1.0"
  12 + },
  13 + "dcloudext": {
  14 + "type": "component-vue",
  15 + "sale": {
  16 + "regular": {
  17 + "price": "0.00"
  18 + },
  19 + "sourcecode": {
  20 + "price": "0.00"
  21 + }
  22 + },
  23 + "contact": {
  24 + "qq": ""
  25 + },
  26 + "declaration": {
  27 + "ads": "无",
  28 + "data": "插件不采集任何数据",
  29 + "permissions": "无"
  30 + },
  31 + "npmurl": ""
  32 + },
  33 + "uni_modules": {
  34 + "dependencies": [],
  35 + "encrypt": [],
  36 + "platforms": {
  37 + "cloud": {
  38 + "tcb": "y",
  39 + "aliyun": "y"
  40 + },
  41 + "client": {
  42 + "Vue": {
  43 + "vue2": "y",
  44 + "vue3": "y"
  45 + },
  46 + "App": {
  47 + "app-vue": "y",
  48 + "app-nvue": "y"
  49 + },
  50 + "H5-mobile": {
  51 + "Safari": "y",
  52 + "Android Browser": "y",
  53 + "微信浏览器(Android)": "y",
  54 + "QQ浏览器(Android)": "y"
  55 + },
  56 + "H5-pc": {
  57 + "Chrome": "y",
  58 + "IE": "y",
  59 + "Edge": "y",
  60 + "Firefox": "y",
  61 + "Safari": "y"
  62 + },
  63 + "小程序": {
  64 + "微信": "y",
  65 + "阿里": "y",
  66 + "百度": "y",
  67 + "字节跳动": "y",
  68 + "QQ": "y",
  69 + "钉钉": "y",
  70 + "快手": "y",
  71 + "飞书": "y",
  72 + "京东": "y"
  73 + },
  74 + "快应用": {
  75 + "华为": "y",
  76 + "联盟": "y"
  77 + }
  78 + }
  79 + }
  80 + }
  81 +}
0 82 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/readme.md 0 → 100644
  1 +## uv-ui-tools 工具集
  2 +
  3 +> **组件名:uv-ui-tools**
  4 +
  5 +uv-ui工具集成,包括网络Http请求、便捷工具、节流防抖、对象操作、时间格式化、路由跳转、全局唯一标识符、规则校验等等。
  6 +
  7 +该组件推荐配合[uv-ui组件库](https://www.uvui.cn/components/intro.html)使用,单独下载也可以在自己项目中使用,需要做相应的配置,可查看文档。强烈推荐使用[uv-ui组件库](https://www.uvui.cn/components/intro.html),导入组件都会自动导入`uv-ui-tools`。需要在自己的项目中使用请参考[扩展配置](https://www.uvui.cn/components/setting.html)。
  8 +
  9 +uv-ui破釜沉舟之兼容vue3+2、app、h5、多端小程序的uni-app生态框架,大部分组件基于uView2.x,在经过改进后全面支持vue3,部分组件做了进一步的优化,修复大量BUG,支持单独导入,方便开发者选择导入需要的组件。开箱即用,灵活配置。
  10 +
  11 +# <a href="https://www.uvui.cn/js/intro.html" target="_blank">查看文档</a>
  12 +
  13 +## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
  14 +
  15 +### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
  16 +
  17 +<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
  18 +
  19 +![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
  20 +
  21 +</a>
  22 +
  23 +#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
0 24 \ No newline at end of file
... ...
uni_modules/uv-ui-tools/theme.scss 0 → 100644
  1 +// 此文件为uvUI的主题变量,这些变量目前只能通过uni.scss引入才有效,另外由于
  2 +// uni.scss中引入的样式会同时混入到全局样式文件和单独每一个页面的样式中,造成微信程序包太大,
  3 +// 故uni.scss只建议放scss变量名相关样式,其他的样式可以通过main.js或者App.vue引入
  4 +
  5 +$uv-main-color: #303133;
  6 +$uv-content-color: #606266;
  7 +$uv-tips-color: #909193;
  8 +$uv-light-color: #c0c4cc;
  9 +$uv-border-color: #dadbde;
  10 +$uv-bg-color: #f3f4f6;
  11 +$uv-disabled-color: #c8c9cc;
  12 +
  13 +$uv-primary: #3c9cff;
  14 +$uv-primary-dark: #398ade;
  15 +$uv-primary-disabled: #9acafc;
  16 +$uv-primary-light: #ecf5ff;
  17 +
  18 +$uv-warning: #f9ae3d;
  19 +$uv-warning-dark: #f1a532;
  20 +$uv-warning-disabled: #f9d39b;
  21 +$uv-warning-light: #fdf6ec;
  22 +
  23 +$uv-success: #5ac725;
  24 +$uv-success-dark: #53c21d;
  25 +$uv-success-disabled: #a9e08f;
  26 +$uv-success-light: #f5fff0;
  27 +
  28 +$uv-error: #f56c6c;
  29 +$uv-error-dark: #e45656;
  30 +$uv-error-disabled: #f7b2b2;
  31 +$uv-error-light: #fef0f0;
  32 +
  33 +$uv-info: #909399;
  34 +$uv-info-dark: #767a82;
  35 +$uv-info-disabled: #c4c6c9;
  36 +$uv-info-light: #f4f4f5;
  37 +
  38 +@mixin flex($direction: row) {
  39 + /* #ifndef APP-NVUE */
  40 + display: flex;
  41 + /* #endif */
  42 + flex-direction: $direction;
  43 +}
0 44 \ No newline at end of file
... ...