feat:初始提交uni-app项目
18
App.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<script>
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
console.log('App Launch')
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/*每个页面公共css */
|
||||
@import "common/style/common-sytle.scss";
|
||||
</style>
|
||||
96
api/apis.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import {request} from "@/utils/request.js"
|
||||
|
||||
//获取首页banner栏内容
|
||||
export function apiGetBanner(){
|
||||
return request({
|
||||
url:"/homeBanner",
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//获取首页每日推荐栏内容
|
||||
export function apiGetDayRandom(){
|
||||
return request({url:"/randomWall"})
|
||||
|
||||
}
|
||||
|
||||
//获取首页公告栏内容
|
||||
export function apiGetNotice(data={}){
|
||||
return request({
|
||||
url:"/wallNewsList",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取tabBar的“分类”里面的列表内容
|
||||
export function apiGetClassify(data={}){
|
||||
return request({
|
||||
url:"/classify",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取tabBar的“分类”栏里面给一个板块的具体图片内容
|
||||
export function apiGetClassList(data={}){
|
||||
return request({
|
||||
url:"/wallList",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//为每一个壁纸评分
|
||||
export function apiGetSetScore(data={}){
|
||||
return request({
|
||||
url:"/setupScore",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//下载壁纸
|
||||
export function apiWriteDownload(data={}){
|
||||
return request({
|
||||
url:"/downloadWall",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 判断用户是不是通过别人分享进来的,从而获取被分享壁纸的详情信息。只有一张
|
||||
export function apiDetailWall(data={}){
|
||||
return request({
|
||||
url:"/detailWall",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取 “我的” 页面的个人信息
|
||||
export function apiUserInfo(data={}){
|
||||
return request({
|
||||
url:"/userInfo",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取 “我的” 页面中"我的下载"和"我的评分"的区分信息
|
||||
export function apiGetHistoryList(data={}){
|
||||
return request({
|
||||
url:"/userWallList",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取 “我的” 页面中"我的下载"和"我的评分"的区分信息
|
||||
export function apiNoticeDetail(data={}){
|
||||
return request({
|
||||
url:"/wallNewsDetail",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//获取 “搜索”页面 壁纸信息
|
||||
export function apiSearchData(data={}){
|
||||
return request({
|
||||
url:"/searchWall",
|
||||
data
|
||||
})
|
||||
}
|
||||
BIN
common/images/banner1.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
common/images/banner2.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
common/images/banner3.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
common/images/classify1.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
common/images/classify2.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
common/images/more.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
common/images/preview1.jpg
Normal file
|
After Width: | Height: | Size: 335 KiB |
BIN
common/images/preview2.jpg
Normal file
|
After Width: | Height: | Size: 288 KiB |
BIN
common/images/preview_small.webp
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
9
common/style/base-style.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
$brand-theme-color:#28B389; //品牌主题绿色
|
||||
|
||||
$border-color:#e0e0e0; //边框颜色
|
||||
$border-color-light:#efefef; //边框亮色
|
||||
|
||||
$text-font-color-1:#000; //文字主色
|
||||
$text-font-color-2:#676767; //副标题颜色
|
||||
$text-font-color-3:#a7a7a7; //浅色
|
||||
$text-font-color-4:#e4e4e4; //更浅色
|
||||
25
common/style/common-sytle.scss
Normal file
@@ -0,0 +1,25 @@
|
||||
view,swiper,swiper-item{
|
||||
// 将盒子全部换成奇异盒,而不是普通盒
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
//页面的背景
|
||||
.pageBg{
|
||||
background:
|
||||
// 这个百分比控制的是颜色占的广度,越小表示从页面的百分之几开始融合
|
||||
//transparent 透明 = rgba(0,0,0,0)
|
||||
linear-gradient(to bottom,transparent 0%,#fff 400rpx),
|
||||
linear-gradient(to right,#beecd8 20%,#F4E2D8);
|
||||
// 加一个最小高度,保证全部覆盖
|
||||
|
||||
min-height: 80vh;
|
||||
}
|
||||
|
||||
|
||||
.loadingLayout{
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.safe-area-inset-bottom{
|
||||
height: env(safe-area-inset-bottom);
|
||||
}
|
||||
28
components/common-title/common-title.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<view class="content-title">
|
||||
<view class="name">
|
||||
<slot name="name"></slot>
|
||||
</view>
|
||||
<view class="custom">
|
||||
<slot name="custom"></slot>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content-title{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 30rpx;
|
||||
.name{
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
11
components/components.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
93
components/custom-nav-bar/custom-nav-bar.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<view class="layout">
|
||||
<view class="navbar">
|
||||
<!-- 占位用的,用于展示手机状态栏 -->
|
||||
<view class="statusBar" :style="{height:getStatusBarHeight() + 'px'}"></view>
|
||||
|
||||
<!-- 使titleBar的高度等于胶囊的高度就可以解决标题和胶囊不在同一直线的问题 -->
|
||||
<view class="titleBar" :style="{height:getTitleBarHeight() + 'px'}">
|
||||
<view class="title">{{title}}</view>
|
||||
<navigator url="/pages/search/search" class="search">
|
||||
<uni-icons class="icon" type="search" size="18" color="#888"></uni-icons>
|
||||
<text class="text">搜索</text>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 占位符,解决图片遮挡问题 -->
|
||||
<view class="fill" :style="{height:getNavBarHeight() + 'px'}">
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
getStatusBarHeight,
|
||||
getTitleBarHeight,
|
||||
getNavBarHeight
|
||||
} from "@/utils/system.js"
|
||||
|
||||
//接收一个对象
|
||||
defineProps({
|
||||
title:{
|
||||
type:String,
|
||||
default:"壁纸"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout{
|
||||
.navbar{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
// 防止被遮挡
|
||||
z-index: 10;
|
||||
// background: ;
|
||||
background:
|
||||
// 这个百分比控制的是颜色占的广度,越小表示从页面的百分之几开始融合
|
||||
//transparent 透明 = rgba(0,0,0,0)
|
||||
linear-gradient(to bottom,transparent 0%,#fff 400rpx),
|
||||
linear-gradient(to right,#beecd8 20%,#F4E2D8);
|
||||
|
||||
// .statusBar{border: 1px solid red;}
|
||||
.titleBar{
|
||||
display: flex;
|
||||
padding: 0 30rpx;
|
||||
align-items: center;
|
||||
.title{
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: $text-font-color-1;
|
||||
}
|
||||
.search{
|
||||
width:200rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 60rpx;
|
||||
background: rgba(255,255,255,0.4);
|
||||
margin-left: 30rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon{
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
.text{
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
112
components/theme-item/theme-item.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<view class="themeItem">
|
||||
<navigator :url="'/pages/classlist/classlist?id='+item._id + '&name='+item.name"
|
||||
class="box"
|
||||
v-if="!isMore">
|
||||
<!-- 组件里面使用组件名,小程序要报警告 -->
|
||||
<image class="pic" :src="item.picurl" mode="aspectFill"></image>
|
||||
<!-- 遮罩层 -->
|
||||
<view class="mask">{{item.name}}</view>
|
||||
<!-- 标签 -->
|
||||
<!-- 父元素里面有发布时间的时间戳 -->
|
||||
|
||||
<!--
|
||||
这里如果更新时间超过3个月了,就返回一个null。
|
||||
如果返回null的话就不会有“xx月/xx日前更新”这个标签了
|
||||
-->
|
||||
<view class="tab" v-if="compareTimestamp(item.updateTime)">{{compareTimestamp(item.updateTime)}}前更新</view>
|
||||
</navigator>
|
||||
|
||||
<navigator url="/pages/classify/classify" open-type="reLaunch" class="box more" v-else>
|
||||
<!-- 组件里面使用组件名,小程序要报警告 -->
|
||||
<image class="pic" src="/common/images/more.jpg" mode="aspectFill"></image>
|
||||
<!-- 遮罩层 -->
|
||||
<view class="mask">
|
||||
<uni-icons type="more-filled" size="34" color="#fff"></uni-icons>
|
||||
<view class="text">更多</view>
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {compareTimestamp} from "@/utils/common.js"
|
||||
defineProps({
|
||||
isMore:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
item:{
|
||||
type:Object,
|
||||
default(){
|
||||
return {
|
||||
name:"默认名称",
|
||||
picurl:"/common/images/classify1.jpg",
|
||||
updateTime:Date.now()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.themeItem {
|
||||
.box {
|
||||
height: 340rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
// 让要布局的子元素相对于这个 class=box 的元素进行操作
|
||||
position: relative;
|
||||
|
||||
.pic {
|
||||
// 图片会有默认的宽度,你不让它继承父级的宽度,原本图片的宽度会将方框撑开
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mask {
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
position: absolute;
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(20rpx);
|
||||
}
|
||||
|
||||
.tab {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: rgba(250, 129, 90, 0.7);
|
||||
backdrop-filter: blur(20rpx);
|
||||
color: #fff;
|
||||
// 浏览器最小就是11px了,22rpx = 11px
|
||||
font-size: 22rpx;
|
||||
border-radius: 0 0 20rpx 0;
|
||||
padding: 6rpx 12rpx;
|
||||
transform: scale(0.8);
|
||||
transform-origin: left top;
|
||||
}
|
||||
}
|
||||
.box.more{
|
||||
.mask{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
.text{
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
20
index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
22
main.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import App from './App'
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import { createSSRApp } from 'vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
73
manifest.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name" : "wallpaper-kt",
|
||||
"appid" : "__UNI__CDCE98F",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wxd0cd1606ac6a1936",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"minified" : true
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
102
pages.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "uni-app",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "components/components",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/classify/classify",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "分类",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/user",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "我的",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/classlist/classlist",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "分类列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/preview/preview",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "预览",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/notice/notice",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "公告"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/notice/detail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "公告详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/search/search",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "搜索"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "咸虾米壁纸",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#9799a5",
|
||||
"selectedColor": "#28b389",
|
||||
"list": [
|
||||
{
|
||||
"text": "推荐",
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "/static/images/tabBar/home.png",
|
||||
"selectedIconPath": "/static/images/tabBar/home-h.png"
|
||||
},
|
||||
{
|
||||
"text": "分类",
|
||||
"pagePath": "pages/classify/classify",
|
||||
"iconPath": "/static/images/tabBar/classify.png",
|
||||
"selectedIconPath": "/static/images/tabBar/classify-h.png"
|
||||
},
|
||||
{
|
||||
"text": "我的",
|
||||
"pagePath": "pages/user/user",
|
||||
"iconPath": "/static/images/tabBar/user.png",
|
||||
"selectedIconPath": "/static/images/tabBar/user-h.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniIdRouter": {}
|
||||
}
|
||||
60
pages/classify/classify.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<view class="classLayout pageBg">
|
||||
<custom-nav-bar title="分类"></custom-nav-bar>
|
||||
<view class="classify">
|
||||
<theme-item v-for="item in classifyList"
|
||||
:key="item._id"
|
||||
:item="item">
|
||||
</theme-item>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {apiGetClassify} from "@/api/apis.js"
|
||||
import {onShareAppMessage,onShareTimeline} from "@dcloudio/uni-app"
|
||||
const classifyList = ref([])
|
||||
const getClassify = async ()=>{
|
||||
let res = await apiGetClassify({
|
||||
// select:true
|
||||
pageSize:15
|
||||
});
|
||||
// console.log(res);
|
||||
classifyList.value = res.data
|
||||
}
|
||||
|
||||
getClassify();
|
||||
|
||||
//分享给好友
|
||||
onShareAppMessage((e)=>{
|
||||
//分享这里是需要有一个 “return” 的
|
||||
return{
|
||||
title:"hzb壁纸,精选分类",
|
||||
path:"/pages/classfy/classfy"
|
||||
}
|
||||
})
|
||||
|
||||
//分享到朋友圈
|
||||
onShareTimeline(()=>{
|
||||
return{
|
||||
// 标题
|
||||
title:"hzb壁纸,精选分类",
|
||||
// 分享时候的图片地址。可以本地也可以网络图
|
||||
imageUrl:"/static/images/logo2.jpg"
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.classLayout{
|
||||
.classify{
|
||||
padding: 30rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3,1fr);
|
||||
gap: 15rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
269
pages/classlist/classlist.vue
Normal file
@@ -0,0 +1,269 @@
|
||||
<template>
|
||||
<view class="classlist">
|
||||
<!--
|
||||
有图片的情况:图片加载出来之后,我们就要取消这个动画
|
||||
没有图片的话:我们也不能要这个加载动画,然后还要显示“没有更多了
|
||||
刚进入页面时,noData是false
|
||||
classList.length也是0(转换传给你false)
|
||||
然后请求完之后,根据请求的内容当中有没有数据,才改变noData的值
|
||||
|
||||
重点是页面执行的顺序问题。有疑惑就思考这个
|
||||
|
||||
noData原本是false,有数据之后就变成了true'”
|
||||
|
||||
|
||||
-->
|
||||
<view class="loadingLayout" v-if="!classList.length && !noData">
|
||||
<uni-load-more status="loading"></uni-load-more>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
|
||||
<navigator :url="'/pages/preview/preview?id=' + item._id" class="item"
|
||||
v-for="item in classList"
|
||||
:key="item._id">
|
||||
<image :src="item.smallPicurl" mode="aspectFill"></image>
|
||||
</navigator>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 避免出现两个加载框的情况,需要考虑这个v-if的条件
|
||||
classList有值 或者 没有更多数据了(noData变成true) 之后,这个框 才可以出现
|
||||
所以是或者关系 用 ||(或) -->
|
||||
|
||||
|
||||
<!--
|
||||
刚进入页面时,noData是false
|
||||
classList.length也是0(转换传给你false)
|
||||
然后请求完之后,根据请求的内容当中有没有数据,才改变noData的值
|
||||
|
||||
重点是页面执行的顺序问题。有疑惑就思考这个
|
||||
|
||||
没有数据noData就变成了true显示“noMore”,
|
||||
有数据noDatashi false显示“loading” -->
|
||||
<!-- <view class="loadingLayout" v-if="classList.length || noData">
|
||||
<uni-load-more :status="noData?'noMore':'loading'"> </uni-load-more>
|
||||
</view> -->
|
||||
|
||||
<!-- 或 表示 现在的页面有数据,但是点击的另一个标签没有数据 -->
|
||||
<view class="loadingLayout bottom" v-if="classList.length || noData">
|
||||
<uni-load-more :status="noData?'noMore':'loading'"> </uni-load-more>
|
||||
<!-- <zero-loading type="sword" position="absolute"></zero-loading> -->
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 程序使用时增加安全高度,防止被home键挡住,提高用户使用 -->
|
||||
<view class="safe-area-inset-bottom"></view>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {apiGetClassList,apiGetHistoryList} from "@/api/apis.js"
|
||||
import {onLoad,onUnload,onReachBottom,onPullDownRefresh} from "@dcloudio/uni-app"
|
||||
// import {zero-loading} from "@/uni_modeules"
|
||||
|
||||
import {onShareAppMessage,onShareTimeline} from "@dcloudio/uni-app"
|
||||
import { gotoHome } from "../../utils/common"
|
||||
|
||||
const classList = ref([])
|
||||
const noData = ref(false)
|
||||
//为了方便后期传入参数,将queryParams方面外面,要加属性的话直接一个 点方法(.) 就可以了
|
||||
|
||||
//定义data参数
|
||||
const queryParams = {
|
||||
pageNum:1,
|
||||
pageSize:12
|
||||
}
|
||||
|
||||
let pageName;
|
||||
|
||||
//onLoad可以接收上个页面传入的参数
|
||||
onLoad((e)=>{
|
||||
// console.log(e);
|
||||
//这里的type联系的是user页面的"我的下载""我的评分"这两个页面
|
||||
let {id=null,name=null,type=null} =e;
|
||||
// id是必定有的,但是这里的type是只有user页面的"我的下载""我的评分"传进来的
|
||||
|
||||
//如果页面没有传入id的话,让让其返回主页面去
|
||||
// if(!id){
|
||||
// return gotoHome();
|
||||
// }
|
||||
|
||||
// 如果上个页面传入的东西包含id的话,就给queryParams加一个id属性,另其等于上个页面传入的id
|
||||
// 除了这两个判断外,其他东西都是不需要改变的
|
||||
|
||||
if(id){
|
||||
//给queryParams加一个id属性
|
||||
queryParams.id = id
|
||||
}
|
||||
if(type){
|
||||
// 给查询参数queryParams添加一个type属性,令其等于这个其他页面传入的type(就是 download 或者 score )
|
||||
queryParams.type = type
|
||||
}
|
||||
|
||||
|
||||
pageName = name
|
||||
|
||||
// console.log(id,name);
|
||||
|
||||
// 传入名字是为了动态改变导航栏标题
|
||||
uni.setNavigationBarTitle({
|
||||
title:name
|
||||
})
|
||||
getClassList();
|
||||
})
|
||||
|
||||
//onUnload表示的是撤销页面时需要做的事情。撤销当前看的页面,就remove掉缓存。提高性能
|
||||
onUnload(() =>{
|
||||
uni.removeStorageSync("storgClassList")
|
||||
})
|
||||
|
||||
|
||||
//下拉刷新
|
||||
// onPullDownRefresh(()=>{
|
||||
// queryParams.pageNum++;
|
||||
// // getClassList();
|
||||
// apiGetClassList({
|
||||
// classid:queryParams.id,
|
||||
// pageNum:queryParams.pageNum,
|
||||
// pageSize:queryParams.pageSize
|
||||
// // classid:"6524ace7213929cbcee72e4d"
|
||||
// }).then(res =>{
|
||||
// if (res.data.errCode === 0) {
|
||||
// // 将新数据放在原有数据的前面(最新的内容在顶部)
|
||||
// //这里res就是res,图片是存在res.data.data里面,与下面的用res接收Promise对象是不一样的
|
||||
// classList.value = [...res.data.data, ...classList.value]
|
||||
|
||||
// // 显示成功提示
|
||||
// uni.showToast({
|
||||
// title: "刷新成功",
|
||||
// icon: "success"
|
||||
// })
|
||||
// } else {
|
||||
// uni.showToast({
|
||||
// title: res.data.errMsg,
|
||||
// icon: "none"
|
||||
// })
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// uni.showToast({
|
||||
// title: "刷新失败",
|
||||
// icon: "none"
|
||||
// })
|
||||
// }).finally(() => {
|
||||
// // 停止下拉刷新动画
|
||||
// uni.stopPullDownRefresh()
|
||||
// })
|
||||
// })
|
||||
|
||||
//触底刷新的时候需要加载新的图片出来,因此需要传入一个新的参数pageNum
|
||||
onReachBottom(()=>{
|
||||
//如果后面没有数据了,再触底就不发送网络请求了
|
||||
if(noData.value){
|
||||
return
|
||||
}
|
||||
queryParams.pageNum++;
|
||||
getClassList();
|
||||
// console.log(res);
|
||||
// <uni-load-more :status="more"/>
|
||||
|
||||
})
|
||||
|
||||
const getClassList = async ()=>{
|
||||
//需要先在外面声明一个res
|
||||
let res;
|
||||
//id参数由上面的queryParams.id提供,如果有id就进行有id的操作
|
||||
if(queryParams.id){
|
||||
res = await apiGetClassList({
|
||||
// queryParams
|
||||
classid:queryParams.id,
|
||||
pageNum:queryParams.pageNum,
|
||||
pageSize:queryParams.pageSize
|
||||
// classid:"6524ace7213929cbcee72e4d"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//type参数由上面的queryParams.type提供,如果有type,就进行有type的操作
|
||||
if(queryParams.type){
|
||||
res = await apiGetHistoryList({
|
||||
// queryParams
|
||||
type:queryParams.type,
|
||||
pageNum:queryParams.pageNum,
|
||||
pageSize:queryParams.pageSize
|
||||
});
|
||||
}
|
||||
|
||||
classList.value = [...classList.value,...res.data]
|
||||
|
||||
//比较发送的长度 和 返回数据的长度。如果原来的大于发送来的,说明后面没数据了,所以将
|
||||
if(queryParams.pageSize > res.data.length){
|
||||
noData.value = true
|
||||
}
|
||||
|
||||
//将数据保存到缓存里面
|
||||
uni.setStorageSync("storgClassList",classList.value)
|
||||
|
||||
// console.log(res);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//分享给好友
|
||||
onShareAppMessage((e)=>{
|
||||
//分享这里是需要有一个 “return” 的
|
||||
|
||||
//在上面的onLoad中,已经将列表的id赋给了queryParams的id属性
|
||||
return{
|
||||
title:"hzb壁纸-"+pageName,
|
||||
// 必须传递id进去,否则进不去内部页面
|
||||
path:"/pages/classlist/classlist?id="+queryParams.id+"&name="+pageName
|
||||
}
|
||||
})
|
||||
|
||||
//分享到朋友圈
|
||||
onShareTimeline(()=>{
|
||||
return{
|
||||
// 标题
|
||||
title:"hzb壁纸~~~",
|
||||
// 分享时候的图片地址。可以本地也可以网络图
|
||||
// imageUrl:"/static/images/logo2.jpg"
|
||||
//要想看朋友圈这个,需要带的query参数
|
||||
query:"id="+queryParams.id+"&name="+pageName
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.classlist{
|
||||
.content{
|
||||
display: grid;
|
||||
// position: relative;
|
||||
grid-template-columns: repeat(3,1fr);
|
||||
gap: 5rpx;
|
||||
padding: 5rpx;
|
||||
.item{
|
||||
// 没有加高度的话没有效果
|
||||
height:440rpx ;
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
//保证图片之间的空格是一致的。不然你行级块元素有空格
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
370
pages/index/index.vue
Normal file
@@ -0,0 +1,370 @@
|
||||
<template>
|
||||
<view class="homeLayout pageBg">
|
||||
|
||||
<custom-nav-bar title="推荐"></custom-nav-bar>
|
||||
|
||||
<view class="banner">
|
||||
<swiper :indicator-dots="true" :circular="true"
|
||||
indicator-color="rgba(255,255,255,0.5)" indicator-active-color="#fff"
|
||||
:autoplay="true">
|
||||
<swiper-item v-for="item in bannerList" :key="item._id">
|
||||
<!-- 这是跳转到小程序时的情况 -->
|
||||
<!--
|
||||
需要添加 target 和 app-id
|
||||
小程序的url时这样的: url: "/pages/index/index"
|
||||
是其他小程序的主页
|
||||
-->
|
||||
<navigator v-if="item.target == 'miniProgram'"
|
||||
class="like"
|
||||
:url="item.url"
|
||||
target="miniProgram"
|
||||
:app-id="item.appid"
|
||||
>
|
||||
<image :src="item.picurl" mode="aspectFill"></image>
|
||||
</navigator>
|
||||
|
||||
<!-- 这里的url是这种形式的: url: "id=6524adaffe975f09c72ce896&name=色彩艺术"-->
|
||||
<!-- 这是跳转到“分类”页面的情况 -->
|
||||
<navigator v-else
|
||||
:url="`/pages/classlist/classlist?${item.url}`"
|
||||
class="like">
|
||||
<image :src="item.picurl" mode="aspectFill"></image>
|
||||
</navigator>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="notice">
|
||||
<view class="left">
|
||||
<uni-icons type="sound-filled" size="20" color="#28b389"></uni-icons>
|
||||
<text class="text">公告</text>
|
||||
</view>
|
||||
<view class="center">
|
||||
<swiper :vertical="true" :autoplay="true" interval="1500"duration="300":circular="true">
|
||||
<swiper-item v-for="item in noticeList" :key="item._id">
|
||||
<!-- 这里需要传入id,表明是哪个具体的公告 -->
|
||||
<navigator :url="'/pages/notice/detail?id='+item._id">
|
||||
{{item.title}}
|
||||
</navigator>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons type="forward" size="20" color="#28b389"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="select">
|
||||
<common-title>
|
||||
<template #name>每日推荐</template>
|
||||
<template #custom>
|
||||
<view class="date">
|
||||
<uni-icons type="calendar" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text">
|
||||
<uni-dateformat :date="Date.now()" format="dd日"></uni-dateformat>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
</common-title>
|
||||
<view class="content">
|
||||
<scroll-view :scroll-x="true" >
|
||||
<view class="box" v-for="item in randomList" :key="item._id"
|
||||
@click="goPreview(item._id)">
|
||||
<!-- mode = aspectFill 显示最短边 -->
|
||||
<image :src="item.smallPicurl" mode="aspectFill"></image>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="theme">
|
||||
<common-title>
|
||||
<template #name>专题精选</template>
|
||||
<template #custom>
|
||||
<!--
|
||||
注意,这里跳转的是tabBar页面。
|
||||
因此需要搭配open-type = “switchbar/relaunch”
|
||||
-->
|
||||
<navigator
|
||||
url="/pages/classify/classify"
|
||||
class="more"
|
||||
open-type="reLaunch"
|
||||
>More+</navigator>
|
||||
</template>
|
||||
</common-title>
|
||||
|
||||
<view class="content">
|
||||
<theme-item :isMore="false" v-for="item in classifyList"
|
||||
:key="item._id"
|
||||
:item="item"></theme-item>
|
||||
<theme-item :isMore="true"></theme-item>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {onShareAppMessage,onShareTimeline} from "@dcloudio/uni-app"
|
||||
import {apiGetBanner,apiGetDayRandom,apiGetNotice,apiGetClassify} from "@/api/apis.js"
|
||||
const bannerList = ref([])
|
||||
const randomList = ref([])
|
||||
const noticeList = ref([])
|
||||
const classifyList = ref([])
|
||||
// 获取Banner的图片
|
||||
const getBanner = async ()=>{
|
||||
//apiGetBanner()返回的结果是一个Promise对象,需要用await接收
|
||||
let res = await apiGetBanner();
|
||||
// console.log(res);
|
||||
bannerList.value = res.data
|
||||
}
|
||||
|
||||
// const getBanner = async () => {
|
||||
// try {
|
||||
// let res = await apiGetBanner();
|
||||
// console.log(res);
|
||||
// if (res.data.errCode === 0) {
|
||||
// bannerList.value = res.data.data;
|
||||
// } else {
|
||||
// handleApiError(res.data.errMsg, '获取 Banner 失败');
|
||||
// }
|
||||
// } catch (error) {
|
||||
// handleApiError(error, '获取 Banner 出现异常');
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
// 获取每日推荐的内容
|
||||
const getDayRandom = async ()=>{
|
||||
let res = await apiGetDayRandom();
|
||||
// console.log(res);
|
||||
randomList.value = res.data
|
||||
}
|
||||
|
||||
|
||||
// const getDayRandom = async () => {
|
||||
// try {
|
||||
// let res = await apiGetDayRandom();
|
||||
// console.log(res);
|
||||
// if (res.data.errCode === 0) {
|
||||
// randomList.value = res.data.data;
|
||||
// } else {
|
||||
// console.error('获取每日推荐失败:', res.data.errMsg);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error('获取每日推荐出现异常:', error);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
//获取公告的内容
|
||||
const getNotice = async ()=>{
|
||||
let res = await apiGetNotice({select:true});
|
||||
// console.log(res);
|
||||
noticeList.value = res.data
|
||||
}
|
||||
|
||||
// const getNotice = async () => {
|
||||
// try {
|
||||
// let res = await apiGetNotice();
|
||||
// console.log(res);
|
||||
// if (res.data.errCode === 0) {
|
||||
// noticeList.value = res.data;
|
||||
// } else {
|
||||
// console.error('获取公告失败:', res.data.errMsg);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error('获取公告出现异常:', error);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
//预览大图
|
||||
const goPreview = (id)=>{
|
||||
//如果没有加下面这个东西,就会导致“每日推荐”的图片是看不了的。因为没有缓存.要缓存的数据randomList列表
|
||||
uni.setStorageSync("storgClassList",randomList.value)
|
||||
uni.navigateTo({
|
||||
url:"/pages/preview/preview?id="+id
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//分类列表内容
|
||||
const getClassify = async ()=>{
|
||||
let res = await apiGetClassify({
|
||||
select:true
|
||||
});
|
||||
// console.log(res);
|
||||
classifyList.value = res.data
|
||||
}
|
||||
|
||||
//分享给好友
|
||||
onShareAppMessage((e)=>{
|
||||
//分享这里是需要有一个 “return” 的
|
||||
return{
|
||||
title:"hzb壁纸",
|
||||
path:"/pages/index/index"
|
||||
}
|
||||
})
|
||||
|
||||
//分享到朋友圈
|
||||
onShareTimeline(()=>{
|
||||
return{
|
||||
// 标题
|
||||
title:"hzb壁纸~~~",
|
||||
// 分享时候的图片地址。可以本地也可以网络图
|
||||
imageUrl:"/static/images/logo2.jpg"
|
||||
}
|
||||
})
|
||||
|
||||
getBanner();
|
||||
getDayRandom();
|
||||
getNotice();
|
||||
getClassify();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.homeLayout{
|
||||
.banner{
|
||||
width: 750rpx;
|
||||
padding: 30rpx 0;
|
||||
|
||||
swiper{
|
||||
width: 750rpx;
|
||||
height:340rpx;
|
||||
swiper-item{
|
||||
width:100%;
|
||||
height: 100%;
|
||||
padding: 0 30rpx;
|
||||
.like{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius:10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice{
|
||||
//使整体居中的方式
|
||||
// 这个宽度使提前算好的,因为你左右两边都是30rpx的间距
|
||||
//整个大小是750,750 —— 60 = 690
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
|
||||
height: 80rpx;
|
||||
background: #f9f9f9;
|
||||
|
||||
//让文字显示一行
|
||||
line-height: 80rpx;
|
||||
//边框的弧度与高度一样就好看
|
||||
border-radius: 80rpx;
|
||||
//使内容位于同一行
|
||||
display: flex;
|
||||
.left{
|
||||
//140rpx宽度的居中样式好看,100rpx的居中样式不行
|
||||
width: 140rpx;
|
||||
// 细节处理 使这部分内容居中处理
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
//细节处理 控制一下文字的样式
|
||||
.text{
|
||||
color: $text-font-color-1;
|
||||
// 控制文字大小
|
||||
font-size: 28rpx;
|
||||
//控制文字的加粗程度
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.center{
|
||||
// “flex:1” 的意思是自动填充完剩下的内容
|
||||
flex: 1;
|
||||
swiper{
|
||||
//继承父级的百分百,这样这个swiper只会在框框的高度里面跳,不会跃出高度
|
||||
height: 100%;
|
||||
swiper-item{
|
||||
//继承父级的高度
|
||||
height: 100%;
|
||||
//细节处理 控制文字的大小
|
||||
font-size: 30rpx;
|
||||
color: #666;
|
||||
//细节处理 文字太多了怎么办? --> 不能换行、还要有省略号
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
//细节处理 文字超出部分用省略号
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right{
|
||||
width: 70rpx;
|
||||
//细节处理 让内容居中
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.select{
|
||||
padding-top: 50rpx;
|
||||
.date{
|
||||
color: $brand-theme-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.content{
|
||||
//750-30==720
|
||||
width: 720rpx;
|
||||
margin-left: 30rpx;
|
||||
margin-top:30rpx;
|
||||
scroll-view{
|
||||
white-space: nowrap;
|
||||
.box{
|
||||
display: inline-block;
|
||||
//宽高比大约是1:2.2左右
|
||||
width: 200rpx;
|
||||
height: 430rpx;
|
||||
//如果你不给图片添加下面的宽度和高度,你这个margin-right是没用用的
|
||||
margin-right: 15rpx;
|
||||
image{
|
||||
//继承父级宽度和高度的100%
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.box:last-child{
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme{
|
||||
padding: 50rpx 0;
|
||||
.more{
|
||||
font-size: 32rpx;
|
||||
color: #888;
|
||||
}
|
||||
.content{
|
||||
margin-top:30rpx;
|
||||
padding: 0 30rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3,1fr);
|
||||
gap: 15rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
116
pages/notice/detail.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
<template>
|
||||
<view class="noticeLayout">
|
||||
<view class="title">
|
||||
<view class="tag">
|
||||
<!-- <uni-tag text="置顶" :inverted="true" type="error" /> -->
|
||||
<uni-tag text="置顶" :inverted="true" type="error" v-if="detail.select"></uni-tag>
|
||||
</view>
|
||||
<view class="font">{{detail.title}}</view>
|
||||
</view>
|
||||
|
||||
<view class="info">
|
||||
<view class="item">{{detail.author}}</view>
|
||||
<view class="item">
|
||||
<uni-dateformat :date="detail.publish_date" format="yyyy-MM-dd hh:mm:ss"></uni-dateformat>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 内容区域 -->
|
||||
<!-- 对于富文本(<rich-text>),我们不能直接在页面进行展示。
|
||||
需要利用组件<rich-text :node="富文本链接">进行展示 -->
|
||||
<!-- <rich-text :nodes="detail.content"></rich-text> -->
|
||||
|
||||
<!-- 或者是利用插件商城的其他插件 -->
|
||||
<mp-html :content="detail.content" />
|
||||
|
||||
</view>
|
||||
|
||||
<view class="count">
|
||||
阅读数量:{{detail.view_count}}
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { apiNoticeDetail } from "@/api/apis.js"
|
||||
import {ref} from "vue"
|
||||
import {onLoad} from "@dcloudio/uni-app"
|
||||
const detail = ref({})
|
||||
const noticeId = ref('')
|
||||
const noticeName = ref('')
|
||||
// let noticeId
|
||||
onLoad((e)=>{
|
||||
console.log(e);
|
||||
noticeId.value = e.id
|
||||
noticeName.value = e.name
|
||||
// 注意,必须先获得这个id,才能进行getNoticeDetail()操作
|
||||
uni.setNavigationBarTitle({
|
||||
title:noticeName.value
|
||||
})
|
||||
getNoticeDetail()
|
||||
})
|
||||
|
||||
const getNoticeDetail = async () =>{
|
||||
let res = await apiNoticeDetail({id:noticeId.value});
|
||||
detail.value = res.data
|
||||
console.log(res);
|
||||
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.noticeLayout{
|
||||
padding: 30rpx;
|
||||
.title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 40rpx;
|
||||
color: #111;
|
||||
line-height: 1.6em;
|
||||
padding-bottom: 30rpx;
|
||||
|
||||
.tag{
|
||||
// // width: 50rpx;
|
||||
// height: 100rpx;
|
||||
// font-size: 20rpx;
|
||||
// color: #e3a7a8;
|
||||
// padding: 10rpx;
|
||||
// border: 1px solid #e3a7a8;
|
||||
//缩小0.8倍
|
||||
transform: scale(0.8);
|
||||
//缩小的起始点
|
||||
transform-origin: left center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.font{
|
||||
// font-size: 40rpx;
|
||||
// color: #0b0b0b;
|
||||
padding-left: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.info{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
.item{
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
padding: 50rpx 0;
|
||||
}
|
||||
|
||||
.count{
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
13
pages/notice/notice.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
707
pages/preview/preview.vue
Normal file
@@ -0,0 +1,707 @@
|
||||
<template>
|
||||
<view class="preview">
|
||||
<swiper :circular="true" :current="currentIndex" @change="swiperChange">
|
||||
<swiper-item v-for="(item,index) in classList" :key="item._id">
|
||||
<!-- 下面的这个v-if是进行流量控制的。看哪个页面就加载哪个页面
|
||||
避免用户的流量消耗。提高用户体验。
|
||||
-->
|
||||
<!-- <image v-if="index===currentIndex" @click="maskChange" :src="item.picurl" mode="aspectFill"></image> -->
|
||||
|
||||
<!-- 也可以选择加载临近一至两张的图片 -->
|
||||
|
||||
<!-- 这是加载临近的左右图片 -->
|
||||
<!-- <image v-if="Math.abs(index - currentIndex) <= 1" @click="maskChange" :src="item.picurl" mode="aspectFill"></image> -->
|
||||
|
||||
<image v-if="readImgs.includes(index)" @click="maskChange" :src="item.picurl" mode="aspectFill"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<view class="mask" v-show="maskState">
|
||||
<view class="goBack" @click="goBack" :style="{top:getPreviewBarHeight() + 'px'}">
|
||||
<uni-icons type="back" color="#fff" size="20"></uni-icons>
|
||||
</view>
|
||||
<view class="count">{{currentIndex+1}} / {{classList.length}}</view>
|
||||
<view class="time">
|
||||
<uni-dateformat :date="Date.now()" format="hh:mm"></uni-dateformat>
|
||||
</view>
|
||||
<view class="date">
|
||||
<uni-dateformat :date="Date.now()" format="MM月dd日"></uni-dateformat>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<view class="box" @click="clickInfo">
|
||||
<uni-icons type="info" size="23"></uni-icons>
|
||||
<view class="text">信息</view>
|
||||
</view>
|
||||
<view class="box" @click="clickScore">
|
||||
<uni-icons type="star" size="23"></uni-icons>
|
||||
<view class="text">{{currentInfo.score}}分</view>
|
||||
</view>
|
||||
<view class="box" @click="clickDownload">
|
||||
<uni-icons type="download" size="23"></uni-icons>
|
||||
<view class="text">下载</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<uni-popup ref="infoPopup" type="bottom">
|
||||
<view class="infoPopup">
|
||||
<view class="popHeader">
|
||||
<!-- 空占位区,用于flex布局的分布 -->
|
||||
<view></view>
|
||||
<view class="title">壁纸信息</view>
|
||||
<view class="close" @click="clickInfoClose">
|
||||
<uni-icons type="closeempty" size="18" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view :scroll-y="true">
|
||||
<view class="content">
|
||||
<view class="row">
|
||||
<view class="label">壁纸ID:</view>
|
||||
<!-- 这里的内容是可选的,所以要用text的 selectable属性 -->
|
||||
<text selectable class="value">{{currentInfo._id}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 暂时没用到 -->
|
||||
<!-- <view class="row">
|
||||
<view class="label">分类:</view>
|
||||
<text class="value class">明星美女</text>
|
||||
</view> -->
|
||||
|
||||
<view class="row">
|
||||
<view class="label">发布者:</view>
|
||||
<text class="value">{{currentInfo.nickname}}</text>
|
||||
</view>
|
||||
|
||||
<view class="row">
|
||||
<text class="label">评分:</text>
|
||||
<view class="value roteBox">
|
||||
<uni-rate :readonly="true" :touchable="false" :value="currentInfo.score" size="16" />
|
||||
<!-- <uni-rate :readonly="true" :touchable="false" :value="5"/> -->
|
||||
<text class="score">{{currentInfo.score}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row">
|
||||
<text class="label">摘要:</text>
|
||||
<view class="value">
|
||||
{{currentInfo.description}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row">
|
||||
<text class="label">标签:</text>
|
||||
<view class="value tabs">
|
||||
<view class="tab" v-for="tab in currentInfo.tabs" :key="tab">
|
||||
{{tab}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="copyright">
|
||||
声明:本图片来用户投稿,非商业使用,用于免费学习交流,如侵犯了您的权益,您可以拷贝壁纸ID举报至平台,邮箱513894357@qq.com,管理将删除侵权壁纸,维护您的权益。
|
||||
</view>
|
||||
|
||||
<!-- 自己手动加一个安全距离 -->
|
||||
<view class="safe-area-inset-bottom"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
|
||||
<!-- :is-mask-click 表示与不允许你点击旁边的蒙版进行关闭弹窗 -->
|
||||
<uni-popup ref="scorePopup" :is-mask-click="false">
|
||||
<view class="scorePopup">
|
||||
<!-- 头部 -->
|
||||
<view class="popHeader">
|
||||
<!-- 空占位区,用于flex布局的分布 -->
|
||||
<view></view>
|
||||
<view class="title">{{isScore?'已经评分过了~':'壁纸评分'}}</view>
|
||||
<view class="close" @click="clickScoreClose">
|
||||
<uni-icons type="closeempty" size="18" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 中部内容-评分区 -->
|
||||
<view class="content">
|
||||
<!-- allowHalf 允许评分一半 -->
|
||||
<uni-rate v-model="userScore" @change="onChange" :disabled="isScore" disabled-color="#FFCA3E"
|
||||
allowHalf />
|
||||
<text class="text">{{userScore}}分</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部内容-确认按钮 -->
|
||||
<view class="footer">
|
||||
<button @click="submitScore" :disabled="!userScore || isScore" type="default" size="mini"
|
||||
plain>确认评分</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- <view class="">{{readImgs}}</view> -->
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from "vue"
|
||||
import {
|
||||
getPreviewBarHeight
|
||||
} from "@/utils/system.js"
|
||||
import {
|
||||
onLoad
|
||||
} from "@dcloudio/uni-app"
|
||||
import {
|
||||
apiGetSetScore,
|
||||
apiWriteDownload
|
||||
} from "@/api/apis.js"
|
||||
// import { fail } from "assert";
|
||||
import {apiDetailWall} from "@/api/apis.js"
|
||||
import {onShareAppMessage,onShareTimeline} from "@dcloudio/uni-app"
|
||||
|
||||
const maskState = ref(true);
|
||||
//信息弹窗
|
||||
const infoPopup = ref(null)
|
||||
//当前图片的具体信息内容
|
||||
const currentInfo = ref({})
|
||||
//评分弹窗
|
||||
const scorePopup = ref(null)
|
||||
//用户评分,v-model双向绑定
|
||||
const userScore = ref(0)
|
||||
//用户是否评完分了
|
||||
const isScore = ref(false)
|
||||
//对应分类的图片列表
|
||||
const classList = ref([])
|
||||
//当前图片的id
|
||||
const currentId = ref(null)
|
||||
//通过当前图片id获得的当前图片的index
|
||||
const currentIndex = ref(0)
|
||||
//已经看过的图片的索引数组
|
||||
const readImgs = ref([])
|
||||
|
||||
|
||||
//读取缓存里面的内容
|
||||
//后面加一个空数组的原因是为了防止缓存里面没数据时用map会报错.
|
||||
const storgClassList = uni.getStorageSync("storgClassList") || [];
|
||||
classList.value = storgClassList.map(item => {
|
||||
// 如果直接return item 的话,item里面所有的属性都会不见
|
||||
// ...item的意思是就是将item里面的所有东西原模原样的全部拷贝到我们新return出来的数据
|
||||
return {
|
||||
...item,
|
||||
//注意 _small.webp是小图,要看大图的话,需要将后缀改变成.jpg
|
||||
picurl: item.smallPicurl.replace("_small.webp", ".jpg")
|
||||
}
|
||||
console.log(classList.value);
|
||||
})
|
||||
|
||||
//onLoad方法获得页面传入的参数
|
||||
onLoad(async (e) => {
|
||||
// console.log(e);
|
||||
//当前图片的id
|
||||
currentId.value = e.id
|
||||
|
||||
// 判断用户是不是通过分享页面进来的
|
||||
if(e.type == 'share'){
|
||||
// apiDetailWall()这个函数需要一个接收图片的id
|
||||
let res = await apiDetailWall({id:currentId.value})
|
||||
//将返回对象的内容全部复制给classList.value,并修改picurl
|
||||
classList.value = res.data.map(item =>{
|
||||
return {
|
||||
...item,
|
||||
picurl:item.smallPicurl.replace("_small.webp", ".jpg")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 注意:使用 _id 而不是 id,并确保类型匹配
|
||||
//根据id找在数组中的索引
|
||||
currentIndex.value = classList.value.findIndex(item => item._id == currentId.value)
|
||||
// 预先加载和去重
|
||||
readImgsFun()
|
||||
currentInfo.value = classList.value[currentIndex.value]
|
||||
})
|
||||
|
||||
|
||||
//swiper的页面滑动时会触发swiper的change事件,有对象传入
|
||||
const swiperChange = (e) => {
|
||||
currentIndex.value = e.detail.current
|
||||
// console.log(e);
|
||||
readImgsFun()
|
||||
currentInfo.value = classList.value[currentIndex.value]
|
||||
}
|
||||
|
||||
//普通状态就是加载临近左右的两张图片,包自己共三张
|
||||
//必须考虑加载页面时 第一页要加载最后一页 和 最后一页 要加载第一页的情况。
|
||||
const readImgsFun = () => {
|
||||
readImgs.value.push(
|
||||
currentIndex.value <= 0 ? classList.value.length - 1 : currentIndex.value - 1,
|
||||
currentIndex.value,
|
||||
currentIndex.value >= classList.value.length - 1 ? 0 : currentIndex.value + 1
|
||||
)
|
||||
|
||||
//new Set() 可以保持数组的唯一性。但是new Set 后的结果是一个 new Set对象
|
||||
//因此我们需要将其转换为数组对象。因此对其使用 [...]
|
||||
// ... 是展开运算符。将对象所有可枚举的属性逐一展开并复制到新对象中
|
||||
// [] 是将其转换为数组对象
|
||||
readImgs.value = [...new Set(readImgs.value)]
|
||||
|
||||
}
|
||||
|
||||
//点击info弹窗
|
||||
const clickInfo = () => {
|
||||
infoPopup.value.open();
|
||||
}
|
||||
//点击关闭info弹窗
|
||||
const clickInfoClose = () => {
|
||||
infoPopup.value.close();
|
||||
}
|
||||
|
||||
//评分弹窗
|
||||
const clickScore = () => {
|
||||
// 判断本地是否存在这个userScore,来表明用户是否评过分了
|
||||
if (currentInfo.value.userScore) {
|
||||
isScore.value = true
|
||||
//如果已经评完分了,将评过的分数赋值给展示的分数
|
||||
userScore.value = currentInfo.value.userScore
|
||||
}
|
||||
scorePopup.value.open();
|
||||
}
|
||||
//点击关闭评分弹窗
|
||||
const clickScoreClose = () => {
|
||||
scorePopup.value.close();
|
||||
userScore.value = 0
|
||||
//复原思想,将这个flag变回原来的信息,展示的时候再变回来,可以免去许多的bug
|
||||
isScore.value = false
|
||||
}
|
||||
|
||||
//确认评分
|
||||
const submitScore = async () => {
|
||||
// console.log("评分了");
|
||||
uni.showLoading({
|
||||
title: "加载中...",
|
||||
})
|
||||
//冒号的作用是将后面的名字作为当前名字的别名。两字名字都代表同个东西
|
||||
let {
|
||||
classid,
|
||||
_id: wallId
|
||||
} = currentInfo.value
|
||||
// 用户的评分作为参数传入,userScore是一个v-model
|
||||
let res = await apiGetSetScore({
|
||||
classid,
|
||||
wallId,
|
||||
userScore: userScore.value
|
||||
})
|
||||
uni.hideLoading();
|
||||
// console.log(res);
|
||||
if (res.errCode === 0) {
|
||||
uni.showToast({
|
||||
title: "评分成功",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
//classList.value[currentIndex.value] 表示找到这个数组里的这个对象
|
||||
// .userScore 表示给这个对象加一个 userScore 属性
|
||||
classList.value[currentIndex.value].userScore = userScore.value;
|
||||
//然后将这个新的 classList 保存到本地
|
||||
uni.setStorageSync("storgClassList", classList.value)
|
||||
clickScoreClose()
|
||||
}
|
||||
|
||||
//遮罩层状态
|
||||
const maskChange = () => {
|
||||
maskState.value = !maskState.value
|
||||
}
|
||||
|
||||
//返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
|
||||
},
|
||||
fail:(err) => {
|
||||
uni.reLaunch({
|
||||
url:"/pages/index/index"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 文件下载
|
||||
const clickDownload = async () => {
|
||||
// #ifdef H5
|
||||
uni.showModal({
|
||||
content: "请长按保存壁纸",
|
||||
showCancel: false
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
try {
|
||||
|
||||
uni.showLoading({
|
||||
title: "下载中...",
|
||||
// 显示过程中不允许点击其他的东西
|
||||
mask: true
|
||||
})
|
||||
|
||||
let {
|
||||
classid,
|
||||
_id: wallId
|
||||
} = currentInfo.value
|
||||
let res = await apiWriteDownload({
|
||||
classid,
|
||||
wallId
|
||||
})
|
||||
|
||||
/* != 表示5s内重复下载了
|
||||
(人家接口设计的,5s内重复下载就提示这个东西,5s内只能下载一次 */
|
||||
if (res.errCode != 0) {
|
||||
throw res
|
||||
}
|
||||
|
||||
uni.getImageInfo({
|
||||
// 这个getImageInfo是为了根据网络地址获得一个临时下载地址,以便能够下载到相册里面
|
||||
//单纯的使用 saveImageToPhotosAlbum 是不能够保存图片的
|
||||
src: currentInfo.value.picurl,
|
||||
success: (res) => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.path,
|
||||
success: (res) => {
|
||||
// console.log(res);
|
||||
uni.showToast({
|
||||
title:"保存成功,请到相册查看",
|
||||
icon:"none"
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
/* 下面这个情况是针对用户点击“下载”之后,但是没有保存时出现的
|
||||
情况,,取消保存错误信息是fail cancel ,没有授权是fail auth deny */
|
||||
if (err.errMsg == 'saveImagePhotoAlbum:fail cancel') {
|
||||
uni.showToast({
|
||||
title: "保存失败,请重新点击下载",
|
||||
icon: "none"
|
||||
})
|
||||
//此时return 是为了结束步骤。不能继续进行到下面的代码当中
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: "授权提示",
|
||||
content: "需要授权保存相册",
|
||||
//success表示系统回复了的情况
|
||||
success: res => {
|
||||
//这里表示点击了“确认"的情况
|
||||
if (res.confirm) {
|
||||
uni.openSetting({
|
||||
success: setting => {
|
||||
console.log(
|
||||
setting);
|
||||
/* setting.authSetting['scope.writePhotosAlbum']
|
||||
表示的是你 "是否授权的值(true / false" */
|
||||
if (setting
|
||||
.authSetting[
|
||||
'scope.writePhotosAlbum'
|
||||
]) {
|
||||
uni.showToast({
|
||||
title: "获取授权成功",
|
||||
icon: "none"
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "获取权限失败",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
//complete表示无论成功还是失败都会做的事件
|
||||
complete: () => {
|
||||
uni.hideLoading();
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
} catch (err) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
//分享给好友
|
||||
onShareAppMessage((e)=>{
|
||||
//分享这里是需要有一个 “return” 的
|
||||
|
||||
//在上面的onLoad中,已经将列表的id赋给了queryParams的id属性
|
||||
return{
|
||||
title:"hzb壁纸-",
|
||||
// 必须传递id进去,否则进不去内部页面
|
||||
path:"/pages/preview/preview?id="+currentId.value+"&type=share"
|
||||
}
|
||||
})
|
||||
|
||||
//分享到朋友圈
|
||||
onShareTimeline(()=>{
|
||||
return{
|
||||
// 标题
|
||||
title:"hzb壁纸~~~",
|
||||
// 分享时候的图片地址。可以本地也可以网络图
|
||||
// imageUrl:"/static/images/logo2.jpg"
|
||||
//要想看朋友圈这个,需要带的query参数
|
||||
// type表示是分享传入的
|
||||
query:"id="+currentId.value+"&type=share"
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../uni.scss';
|
||||
// @include fix-position就是下面的这堆东西
|
||||
// position: absolute;
|
||||
// left: 0;
|
||||
// right: 0;
|
||||
// //单纯的给margin:auto的话,你的宽度会被拉长,需要给一个固定宽度
|
||||
// margin: auto;
|
||||
// //宽度你给多少都不能准确到达中间位置,给一个fit-content自动适应
|
||||
// width:fit-content;
|
||||
// color: #fff;
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
|
||||
swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mask {
|
||||
.goBack {
|
||||
@include fix-position;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
left: 30rpx;
|
||||
top: 0;
|
||||
margin-left: 0;
|
||||
border-radius: 100px;
|
||||
backdrop-filter: blur(10rpx);
|
||||
border: 1px solid rbga(255, 255, 255, 0.3);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.count {
|
||||
position: absolute;
|
||||
top: 10vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
//单纯的给margin:auto的话,你的宽度会被拉长,需要给一个固定宽度
|
||||
margin: auto;
|
||||
//宽度你给多少都不能准确到达中间位置,给一个fit-content自动适应
|
||||
width: fit-content;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
border-radius: 40rpx;
|
||||
padding: 8rpx 28rpx;
|
||||
backdrop-filter: blur(20rpx);
|
||||
}
|
||||
|
||||
.time {
|
||||
@include fix-position;
|
||||
//看设计图上面的设计
|
||||
top: calc(10vh + 80rpx);
|
||||
font-size: 140rpx;
|
||||
font-weight: 100rpx;
|
||||
//去除行高
|
||||
line-height: 1em;
|
||||
//加上文字阴影,避免图片是白色是时候你看不到文字
|
||||
text-shadow: 0 4rpx rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.date {
|
||||
@include fix-position;
|
||||
top: calc(10vh + 230rpx);
|
||||
font-size: 34rpx;
|
||||
//加上文字阴影,避免图片是白色是时候你看不到文字
|
||||
text-shadow: 0 2rpx rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.footer {
|
||||
@include fix-position;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
bottom: 10vh;
|
||||
width: 65vw;
|
||||
height: 120rpx;
|
||||
border-radius: 120rpx;
|
||||
color: #000;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
box-shadow: 0 2rpx rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(20rpx);
|
||||
|
||||
//使文字和样式在同一列上
|
||||
.box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
//给box加padding,增大接触距离
|
||||
padding: 2rpx 12rpx;
|
||||
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
color: $text-font-color-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
color: $text-font-color-2;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.close {
|
||||
// 细节处理,增大图标接触面积,提高用户体验
|
||||
padding: 6rpx
|
||||
}
|
||||
}
|
||||
|
||||
.infoPopup {
|
||||
background: #fff;
|
||||
padding: 30rpx;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
overflow: hidden;
|
||||
|
||||
scroll-view {
|
||||
max-height: 60vh;
|
||||
|
||||
.content {
|
||||
.row {
|
||||
display: flex;
|
||||
padding: 16rpx 0;
|
||||
font-size: 32rpx;
|
||||
// 行高控制
|
||||
line-height: 1.7em;
|
||||
|
||||
.label {
|
||||
color: $text-font-color-3;
|
||||
width: 140rpx;
|
||||
//文字靠右,就是word里面的右对齐
|
||||
text-align: right;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
//上面父级已经给了宽度了,你子级就可以给一个flex:1来让其自动分配
|
||||
flex: 1;
|
||||
//因为可能 value的值可能很多,会把label挤压,所以加一个兼容性写法,宽度为0
|
||||
width: 0;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.roteBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.score {
|
||||
font-size: 26rpx;
|
||||
color: $text-font-color-2 ;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
white-space: wrap;
|
||||
|
||||
.tab {
|
||||
border: 1px solid $brand-theme-color;
|
||||
color: $brand-theme-color;
|
||||
font-size: 22rpx;
|
||||
padding: 10rpx 30rpx;
|
||||
;
|
||||
border-radius: 40rpx;
|
||||
line-height: 1em;
|
||||
margin: 0 10rpx 10rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
.class {
|
||||
color: $brand-theme-color;
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx;
|
||||
background: #F6F6F6;
|
||||
color: #666;
|
||||
border-radius: 10rpx;
|
||||
margin: 20rpx 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scorePopup {
|
||||
background: #fff;
|
||||
padding: 30rpx;
|
||||
width: 70vw;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.content {
|
||||
padding: 30rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
color: #FFCA3E;
|
||||
padding-left: 10rpx;
|
||||
width: 80rpx;
|
||||
line-height: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
273
pages/search/search.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<view class="searchLayout">
|
||||
<!-- cancel是"取消",clear是那个"×" -->
|
||||
<view class="search">
|
||||
<uni-search-bar
|
||||
@confirm="onSearch"
|
||||
@cancel="onClear"
|
||||
@clear="onClear"
|
||||
:focus="true"
|
||||
placeholder="搜索"
|
||||
v-model="queryParams.keyword"
|
||||
>
|
||||
</uni-search-bar>
|
||||
</view>
|
||||
|
||||
<!-- 当有图片的时候,就不展示这些东西标签啥的。 -->
|
||||
<!-- 点击标签,但是没有数据时,noSearch会变成true,也可以显示这些标签 -->
|
||||
<view v-if="!classList.length || noSearch">
|
||||
<!-- 这个最近搜索的展示是根据有没有历史记录来展示的
|
||||
如果没有历史记录,就不展示这一框
|
||||
如果有历史记录,就展示这一框
|
||||
-->
|
||||
<view class="history" v-if="historySearch.length">
|
||||
<view class="topTitle" >
|
||||
<view class="text">最近搜索</view>
|
||||
<view class="icon" @click="removeHistory" >
|
||||
<uni-icons type="trash" size="25"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tabs">
|
||||
<view class="tab" v-for="tab in historySearch" :key="tab"
|
||||
@click="clickTab(tab)">{{tab}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="recommend">
|
||||
<view class="topTitle">
|
||||
<view class="text">热门搜索</view>
|
||||
</view>
|
||||
|
||||
<!-- 这里我本来的:key="index" ,但是人家却是:key="tab"-->
|
||||
<view class="tabs">
|
||||
<view class="tab" v-for="tab in recommendList" :key="tab"
|
||||
@click="clickTab(tab)">{{tab}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 没有搜索结果的情况,这是一个插件 -->
|
||||
<view class="noSearch" v-if="noSearch">
|
||||
<uv-empty mode="search" ></uv-empty>
|
||||
</view>
|
||||
|
||||
<!-- 有搜索结果的展示区域 -->
|
||||
<view v-else>
|
||||
<view class="list">
|
||||
<!-- 这里你单独的进行传id也是不能够看到预览页面的 -->
|
||||
<!-- 因为预览页面呢个够被看到是取决你有没有缓存这个预览页面的数据的 -->
|
||||
<!-- 而缓存预览页面的数据我们可以在请求网络的数据的时候就进行存储 -->
|
||||
<!--
|
||||
:url是:url="`/pages/preview/preview?id=${item._id}`"
|
||||
不是:url="`pages/preview/preview?id=${item._id}`"
|
||||
前面还要有一个 “/”
|
||||
-->
|
||||
|
||||
<!-- <navigator :url="`pages/preview/preview?id=${item._id}`" class="item"
|
||||
v-for="item in classList" :key="item._id"> -->
|
||||
|
||||
<navigator :url="`/pages/preview/preview?id=${item._id}`" class="item"
|
||||
v-for="item in classList" :key="item._id">
|
||||
|
||||
<image :src="item.smallPicurl" mode="aspectFill"></image>
|
||||
</navigator>
|
||||
</view>
|
||||
<view v-if="noData || classList.length" class="loadingLayout">
|
||||
<uni-load-more :status="noData?'noMore':'loading'"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {onReachBottom,onUnload,onLoad} from "@dcloudio/uni-app"
|
||||
import {apiSearchData} from "@/api/apis.js"
|
||||
|
||||
//传递的参数
|
||||
const queryParams = ref({
|
||||
pageNum:1,
|
||||
pageSize:12,
|
||||
keyword:""
|
||||
})
|
||||
|
||||
//搜索历史词
|
||||
//获取历史搜索词,我们需要使其从缓存里面读取,保证刷新不会重新被赋值
|
||||
// 当用户没有缓存时,给一个空数组,避免出现获取不到null的情况,进而影响后续操作
|
||||
const historySearch = ref(uni.getStorageSync("historySearch") || []);
|
||||
|
||||
//热门推荐词
|
||||
const recommendList = ref(["美女","帅哥","宠物","卡通"])
|
||||
|
||||
//进到标签页面时可能发生的情况
|
||||
//没有数据了
|
||||
const noData = ref(false)
|
||||
//没有搜索结果
|
||||
const noSearch = ref(false)
|
||||
|
||||
//搜索结果列表 搜索的结果最终是要在preview页面进行查看的
|
||||
// classList初始化为空,只有在调用了searchData()函数之后才会被赋值
|
||||
const classList = ref([])
|
||||
|
||||
|
||||
//点击清除按钮
|
||||
const onClear = ()=>{
|
||||
initParams()
|
||||
}
|
||||
|
||||
//点击标签进行搜索.需要一个参数接收传入的标签名
|
||||
// 问题:1.搜索框的值怎么表示? --》 v-model 绑定,监视:value和@input事件
|
||||
// 2.怎么得到值后就自动”comfirm“
|
||||
const clickTab = (value) =>{
|
||||
/* 因为你在点击了标签的内容之后,还可以在搜索框继续进行搜索,那此时你新搜索的内容会跟之前一样,
|
||||
被添加到原来的内容下面。因此你需要对其进行初始化,并将keyword换成最新的关键词 */
|
||||
initParams(value)
|
||||
// 点击标签之后不是触发searchData(),因为这样不会这个点击的标签不会被添加到历史记录里面
|
||||
// 点击标签之后要触发的函数是onSearch()
|
||||
// searchData()
|
||||
onSearch()
|
||||
}
|
||||
|
||||
//清空最近搜索历史记录
|
||||
const removeHistory = ()=>{
|
||||
uni.showModal({
|
||||
title:"是否清空历史搜索",
|
||||
success:(res) =>{
|
||||
if(res.confirm){
|
||||
// console.log("确认删除");
|
||||
uni.removeStorageSync("historySearch")
|
||||
historySearch.value = []
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//1.点击搜索,点击了之后,搜索记录里面要多加一个记录
|
||||
const onSearch = ()=>{
|
||||
//加一个加载页,提高用户体验。那时候时候取消呢?在searchData()获取数据那时候进行操作
|
||||
uni.showLoading()
|
||||
// console.log(queryParams.value.keyword);
|
||||
// 第一种添加的方式就是直接加到前面,老的历史词就直接展开
|
||||
// 第二种就是直接用数组的添加方法
|
||||
|
||||
//slice进行切片操作,确保只有10个历史记录
|
||||
historySearch.value = [...new Set([queryParams.value.keyword,...historySearch.value])].slice(0,10)
|
||||
uni.setStorageSync("historySearch",historySearch.value)
|
||||
/* 因为你在点击了标签的内容之后,还可以在搜索框继续进行搜索,那此时你新搜索的内容会跟之前一样,
|
||||
被添加到原来的内容下面。因此你需要对其进行初始化,并将keyword换成最新的关键词 */
|
||||
initParams(queryParams.value.keyword)
|
||||
// 只有点击“搜索”之后才要触发这个函数
|
||||
searchData()
|
||||
|
||||
}
|
||||
|
||||
|
||||
//搜索之后所有的要做的功能的合集
|
||||
const searchData = async () =>{
|
||||
// 加一个try、catch进行操作,捕捉“拿不到数据”的情况。
|
||||
try{
|
||||
//使res等于请求过来的数据
|
||||
let res = await apiSearchData(queryParams.value)
|
||||
classList.value = [...classList.value,...res.data]
|
||||
|
||||
//将数据保存到缓存里面,方便上面点击标签后要预览页面(preview)
|
||||
uni.setStorageSync("storgClassList",classList.value)
|
||||
|
||||
//如果后面没有数据了,就需要把noData变成true
|
||||
if(queryParams.value.pageSize > res.data.length) noData.value = true
|
||||
|
||||
//下面这个是判断有没有搜索结果的
|
||||
//如果先点击了有图片的标签,那么当你再点击没图片的标签时,就还是展示原来那个有图片的标签
|
||||
//如果原本classList就是空的,并且你点击的标签也没有图片时,才会展示“没有搜索结果”
|
||||
if(res.data.length == 0 && classList.value.length == 0) noSearch.value = true
|
||||
// console.log(res);
|
||||
}finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//初始化搜索框,清空原本的内容
|
||||
//什么时候用呢?
|
||||
// 1.当我们点击“取消”和"×"的时候进行调用
|
||||
// 2.当我们点击新的标签时就要先初始化
|
||||
const initParams = (value='')=>{
|
||||
//清空原先已经展示的数据
|
||||
classList.value = []
|
||||
noData.value = false
|
||||
noSearch.value = false
|
||||
queryParams.value = {
|
||||
pageNum:1,
|
||||
pageSize:12,
|
||||
// 如果有传入值,就把这个值赋给keyword,没有值的话就默认变成""
|
||||
keyword:value || ""
|
||||
}
|
||||
}
|
||||
|
||||
//触底加载更多
|
||||
onReachBottom(()=>{
|
||||
//这个if表示如果后面没有数据了,就直接return结束,不要再进行请求数据了
|
||||
if(noData.value) return
|
||||
queryParams.value.pageNum++
|
||||
searchData()
|
||||
})
|
||||
|
||||
//关闭页面时将数据清除,能够提高性能
|
||||
onUnload(()=>{
|
||||
uni.removeStorageSync("storgClassList",classList.value)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.searchLayout{
|
||||
.search{
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
.topTitle{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.history{
|
||||
padding: 30rpx;
|
||||
}
|
||||
.recommend{
|
||||
padding: 30rpx;
|
||||
}
|
||||
.tabs{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 20rpx;
|
||||
.tab{
|
||||
background: #F4F4F4;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
padding: 10rpx 28rpx;
|
||||
border-radius: 50rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
.list{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3,1fr);
|
||||
gap: 5rpx;
|
||||
padding: 20rpx 5rpx;
|
||||
.item{
|
||||
height: 440rpx;
|
||||
image{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
239
pages/user/user.vue
Normal file
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
|
||||
|
||||
<!-- 注意,如果userinfo被加载出来才会显示这个内容,避免报错。否则就显示loding -->
|
||||
<view class="userLayout pageBg" v-if="userinfo">
|
||||
<!-- 添加一个状态栏的高度,避免被刘海屏挡住了 -->
|
||||
<view :style="{height:getNavBarHeight() + 'px'}"></view>
|
||||
|
||||
<view class="userinfo">
|
||||
<view class="avatar">
|
||||
<image src="/static/images/xxmLogo.png" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="ip">{{userinfo.IP}}</view>
|
||||
<view class="address">来自于:
|
||||
<!-- 避免开代理获取不到城市和省份的情况,外面考虑以下爱的内容,最不其给你在中国 -->
|
||||
<!-- 1. 安全访问操作符 (?.) 确保拥有该属性,没回的返回undefined,不会报错/如果都没有,就默认是“中国” -->
|
||||
{{userinfo?.address?.city || userinfo?.address?.province || userinfo?.address?.country || '中国' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- 菜单 -->
|
||||
<view class="section">
|
||||
<view class="list">
|
||||
<!-- 区分页面,表明这是通过user页面然后点击“我的下载”进入的 -->
|
||||
<navigator url="/pages/classlist/classlist?name=我的下载&type=download">
|
||||
<view class="row">
|
||||
<!-- 这里分为左右两部分,(图标、文字)以及 (右箭头) -->
|
||||
<view class="left">
|
||||
<uni-icons type="download-filled" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text" >我的下载</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="text">{{userinfo.downloadSize}}</view>
|
||||
<uni-icons type="forward" size="15" color="#aaa"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
|
||||
<!-- 区分页面,表明这是通过user页面然后点击“我的评分”进入的 -->
|
||||
<navigator url="/pages/classlist/classlist?name=我的评分&type=score">
|
||||
<view class="row">
|
||||
<!-- 这里分为左右两部分,(图标、文字)以及 (右箭头) -->
|
||||
<view class="left">
|
||||
<uni-icons type="star-filled" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text" >我的评分</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="text">{{userinfo.scoreSize}}</view>
|
||||
<uni-icons type="forward" size="15" color="#aaa"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
|
||||
<view class="row">
|
||||
<!-- 这里分为左右两部分,(图标、文字)以及 (右箭头) -->
|
||||
<view class="left">
|
||||
<uni-icons type="chatboxes-filled" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text" >联系客服</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="text"></view>
|
||||
<uni-icons type="forward" size="15" color="#aaa"></uni-icons>
|
||||
</view>
|
||||
|
||||
<!-- #ifdef MP -->
|
||||
<button open-type="contact" class="contact">联系客服</button>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef WEB -->
|
||||
<button @click="clickContact">拨打电话</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="section">
|
||||
<view class="list">
|
||||
<!-- 订阅更新和常见问题的页面都是在公告列表里面的,但是id变一下就可以了 -->
|
||||
<navigator url="/pages/notice/detail?id=653507c6466d417a3718e94b&name=订阅更新">
|
||||
<view class="row">
|
||||
<!-- 这里分为左右两部分,(图标、文字)以及 (右箭头) -->
|
||||
<view class="left">
|
||||
<uni-icons type="notification-filled" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text" >订阅更新</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons type="forward" size="15" color="#aaa"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
|
||||
<!-- 订阅更新和常见问题的页面都是在公告列表里面的,但是id变一下就可以了 -->
|
||||
<navigator url="/pages/notice/detail?id=6536358ce0ec19c8d67fbe82&name=常见问题">
|
||||
<view class="row">
|
||||
<!-- 这里分为左右两部分,(图标、文字)以及 (右箭头) -->
|
||||
<view class="left">
|
||||
<uni-icons type="flag-filled" size="20" color="#28b389"></uni-icons>
|
||||
<view class="text" >常见问题</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons type="forward" size="15" color="#aaa"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</navigator>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- userinfo没有被加载出来就显示loading -->
|
||||
<view class="loadingLayout" v-else>
|
||||
<view :style="{height:getNavBarHeight()+'px'}"></view>
|
||||
<uni-load-more status="loading"></uni-load-more>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getNavBarHeight} from "@/utils/system.js"
|
||||
import {apiUserInfo} from "@/api/apis.js"
|
||||
import { ref } from "vue";
|
||||
|
||||
const userinfo = ref(null)
|
||||
|
||||
const clickContact = ()=>{
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: '114' //仅为示例
|
||||
});
|
||||
}
|
||||
|
||||
const getUserInfo = async ()=>{
|
||||
let res = await apiUserInfo()
|
||||
// console.log(res);
|
||||
userinfo.value = res.data
|
||||
}
|
||||
|
||||
getUserInfo()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.userLayout{
|
||||
.userinfo{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 50rpx 0;
|
||||
.avatar{
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
// 对父组件设置border-radius和overflow:hidden
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
// 同时还需要image设置width和height 100%
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.ip{
|
||||
font-size: 44rpx;
|
||||
color: #333;
|
||||
padding: 20rpx 0 5rpx;
|
||||
}
|
||||
.address{
|
||||
font-size: 28rpx;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.section{
|
||||
width: 690rpx;
|
||||
// 父元素使其居中处理
|
||||
margin: 50rpx auto;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 10rpx;
|
||||
box-shadow: 0 0 30rpx rgba(0,0,0,0.05);
|
||||
|
||||
.list{
|
||||
.row{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
//细节处理,不要贴边
|
||||
padding:0 30rpx;
|
||||
height: 100rpx;
|
||||
border-bottom: 1px solid #eee;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
|
||||
//最后一个元素会有两个边框,所以我们需要去掉一个
|
||||
//&:&号表示同名,
|
||||
//这里即指(.row) 还要一个伪类选择器宣导最后一个元素
|
||||
&:last-child{
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.left{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.text{
|
||||
padding-left: 20rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.right{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.text{
|
||||
font-size: 28rpx;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
button{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
25
project.config.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"setting": {
|
||||
"es6": true,
|
||||
"postcss": true,
|
||||
"minified": true,
|
||||
"uglifyFileName": false,
|
||||
"enhance": true,
|
||||
"packNpmRelationList": [],
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
},
|
||||
"useCompilerPlugins": false,
|
||||
"minifyWXML": true
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
},
|
||||
"appid": "wxd0cd1606ac6a1936",
|
||||
"editorSetting": {}
|
||||
}
|
||||
14
project.private.config.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"libVersion": "3.9.0",
|
||||
"projectname": "wallpaper-kt",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"coverView": true,
|
||||
"lazyloadPlaceholderEnable": false,
|
||||
"skylineRenderEnable": false,
|
||||
"preloadBackgroundData": false,
|
||||
"autoAudits": false,
|
||||
"showShadowRootInWxmlPanel": true,
|
||||
"compileHotReLoad": true
|
||||
}
|
||||
}
|
||||
BIN
static/images/tabBar/classify-h.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/images/tabBar/classify.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/images/tabBar/home-h.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
static/images/tabBar/home.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/tabBar/user-h.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/tabBar/user.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/xxmLogo.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
13
uni.promisify.adaptor.js
Normal file
@@ -0,0 +1,13 @@
|
||||
uni.addInterceptor({
|
||||
returnValue (res) {
|
||||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||
return res;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
res.then((res) => {
|
||||
if (!res) return resolve(res)
|
||||
return res[0] ? reject(res[0]) : resolve(res[1])
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
88
uni.scss
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
@import "@/common/style/base-style.scss";
|
||||
// 定义一个 mixin
|
||||
@mixin fix-position{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
//单纯的给margin:auto的话,你的宽度会被拉长,需要给一个固定宽度
|
||||
margin: auto;
|
||||
//宽度你给多少都不能准确到达中间位置,给一个fit-content自动适应
|
||||
width:fit-content;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color:#333;//基本色
|
||||
$uni-text-color-inverse:#fff;//反色
|
||||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable:#c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-bg-color-grey:#f8f8f8;
|
||||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color:#c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm:12px;
|
||||
$uni-font-size-base:14px;
|
||||
$uni-font-size-lg:16px;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm:20px;
|
||||
$uni-img-size-base:26px;
|
||||
$uni-img-size-lg:40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2C405A; // 文章标题颜色
|
||||
$uni-font-size-title:20px;
|
||||
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||
$uni-font-size-subtitle:26px;
|
||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$uni-font-size-paragraph:15px;
|
||||
192
uni_modules/mp-html/README.md
Normal file
@@ -0,0 +1,192 @@
|
||||
## 为减小组件包的大小,默认组件包中不包含编辑、latex 公式等扩展功能,需要使用扩展功能的请参考下方的 插件扩展 栏的说明
|
||||
|
||||
## 功能介绍
|
||||
- 全端支持(含 `v3、NVUE`)
|
||||
- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
|
||||
- 支持丰富的事件效果(自动预览图片、链接处理等)
|
||||
- 支持设置占位图(加载中、出错时、预览时)
|
||||
- 支持锚点跳转、长按复制等丰富功能
|
||||
- 支持大部分 *html* 实体
|
||||
- 丰富的插件(关键词搜索、内容编辑、`latex` 公式等)
|
||||
- 效率高、容错性强且轻量化
|
||||
|
||||
查看 [功能介绍](https://jin-yufeng.github.io/mp-html/#/overview/feature) 了解更多
|
||||
|
||||
## 使用方法
|
||||
- `uni_modules` 方式
|
||||
1. 点击右上角的 `使用 HBuilder X 导入插件` 按钮直接导入项目或点击 `下载插件 ZIP` 按钮下载插件包并解压到项目的 `uni_modules/mp-html` 目录下
|
||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
||||
```html
|
||||
<!-- 不需要引入,可直接使用 -->
|
||||
<mp-html :content="html" />
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
html: '<div>Hello World!</div>'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可
|
||||
|
||||
- 源码方式
|
||||
1. 从 [github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 或 [gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 下载源码
|
||||
插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取
|
||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
||||
```html
|
||||
<mp-html :content="html" />
|
||||
```
|
||||
```javascript
|
||||
import mpHtml from '@/components/mp-html/mp-html'
|
||||
export default {
|
||||
// HBuilderX 2.5.5+ 可以通过 easycom 自动引入
|
||||
components: {
|
||||
mpHtml
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
html: '<div>Hello World!</div>'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- npm 方式
|
||||
1. 在项目根目录下执行
|
||||
```bash
|
||||
npm install mp-html
|
||||
```
|
||||
2. 在需要使用页面的 `(n)vue` 文件中添加
|
||||
```html
|
||||
<mp-html :content="html" />
|
||||
```
|
||||
```javascript
|
||||
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
|
||||
export default {
|
||||
// 不可省略
|
||||
components: {
|
||||
mpHtml
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
html: '<div>Hello World!</div>'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
3. 需要更新版本时执行以下命令即可
|
||||
```bash
|
||||
npm update mp-html
|
||||
```
|
||||
|
||||
使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
|
||||
如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
|
||||
|
||||
查看 [快速开始](https://jin-yufeng.github.io/mp-html/#/overview/quickstart) 了解更多
|
||||
|
||||
## 组件属性
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|:---:|:---:|:---:|---|
|
||||
| container-style | String | | 容器的样式([2.1.0+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v210)) |
|
||||
| content | String | | 用于渲染的 html 字符串 |
|
||||
| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
|
||||
| domain | String | | 主域名(用于链接拼接) |
|
||||
| error-img | String | | 图片出错时的占位图链接 |
|
||||
| lazy-load | Boolean | false | 是否开启图片懒加载 |
|
||||
| loading-img | String | | 图片加载过程中的占位图链接 |
|
||||
| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
|
||||
| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
|
||||
| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
|
||||
| selectable | Boolean | false | 是否开启文本长按复制 |
|
||||
| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
|
||||
| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
|
||||
| tag-style | Object | | 设置标签的默认样式 |
|
||||
| use-anchor | Boolean | false | 是否使用锚点链接 |
|
||||
|
||||
查看 [属性](https://jin-yufeng.github.io/mp-html/#/basic/prop) 了解更多
|
||||
|
||||
## 组件事件
|
||||
|
||||
| 名称 | 触发时机 |
|
||||
|:---:|---|
|
||||
| load | dom 树加载完毕时 |
|
||||
| ready | 图片加载完毕时 |
|
||||
| error | 发生渲染错误时 |
|
||||
| imgtap | 图片被点击时 |
|
||||
| linktap | 链接被点击时 |
|
||||
| play | 音视频播放时 |
|
||||
|
||||
查看 [事件](https://jin-yufeng.github.io/mp-html/#/basic/event) 了解更多
|
||||
|
||||
## api
|
||||
组件实例上提供了一些 `api` 方法可供调用
|
||||
|
||||
| 名称 | 作用 |
|
||||
|:---:|---|
|
||||
| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
|
||||
| navigateTo | 锚点跳转 |
|
||||
| getText | 获取文本内容 |
|
||||
| getRect | 获取富文本内容的位置和大小 |
|
||||
| setContent | 设置富文本内容 |
|
||||
| imgList | 获取所有图片的数组 |
|
||||
| pauseMedia | 暂停播放音视频([2.2.2+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v222)) |
|
||||
| setPlaybackRate | 设置音视频播放速率([2.4.0+](https://jin-yufeng.github.io/mp-html/#/changelog/changelog#v240)) |
|
||||
|
||||
查看 [api](https://jin-yufeng.github.io/mp-html/#/advanced/api) 了解更多
|
||||
|
||||
## 插件扩展
|
||||
除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
|
||||
|
||||
| 名称 | 作用 |
|
||||
|:---:|---|
|
||||
| audio | 音乐播放器 |
|
||||
| editable | 富文本 **编辑**([示例项目](https://mp-html.oss-cn-hangzhou.aliyuncs.com/editable.zip)) |
|
||||
| emoji | 解析 emoji |
|
||||
| highlight | 代码块高亮显示 |
|
||||
| markdown | 渲染 markdown |
|
||||
| search | 关键词搜索 |
|
||||
| style | 匹配 style 标签中的样式 |
|
||||
| txv-video | 使用腾讯视频 |
|
||||
| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
|
||||
| latex | 渲染 latex 公式 by [@Zeng-J](https://github.com/Zeng-J) |
|
||||
|
||||
从插件市场导入的包中 **不含有** 扩展插件,使用插件需通过微信小程序 `富文本插件` 获取或参考以下方法进行打包:
|
||||
1. 获取完整组件包
|
||||
```bash
|
||||
npm install mp-html
|
||||
```
|
||||
2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件
|
||||
3. 生成新的组件包
|
||||
在 `node_modules/mp-html` 目录下执行
|
||||
```bash
|
||||
npm install
|
||||
npm run build:uni-app
|
||||
```
|
||||
4. 拷贝 `dist/uni-app` 中的内容到项目根目录
|
||||
|
||||
查看 [插件](https://jin-yufeng.github.io/mp-html/#/advanced/plugin) 了解更多
|
||||
|
||||
## 关于 nvue
|
||||
`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面
|
||||
由于渲染方式与其他端不同,有以下限制:
|
||||
1. 不支持 `lazy-load` 属性
|
||||
2. 视频不支持全屏播放
|
||||
3. 如果在 `flex-direction: row` 的容器中使用,需要给组件设置宽度或设置 `flex: 1` 占满剩余宽度
|
||||
|
||||
纯 `nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)
|
||||
|
||||
|
||||
## 问题反馈
|
||||
遇到问题时,请先查阅 [常见问题](https://jin-yufeng.github.io/mp-html/#/question/faq) 和 [issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题
|
||||
可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)
|
||||
提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复
|
||||
|
||||
欢迎加入 `QQ` 交流群:
|
||||
群1(已满):`699734691`
|
||||
群2(已满):`778239129`
|
||||
群3:`960265313`
|
||||
|
||||
查看 [问题反馈](https://jin-yufeng.github.io/mp-html/#/question/feedback) 了解更多
|
||||
156
uni_modules/mp-html/changelog.md
Normal file
@@ -0,0 +1,156 @@
|
||||
## v2.5.1(2025-04-20)
|
||||
1. `U` 适配鸿蒙 `APP` [详细](https://github.com/jin-yufeng/mp-html/issues/615)
|
||||
2. `U` 微信小程序替换废弃 `api` `getSystemInfoSync` [详细](https://github.com/jin-yufeng/mp-html/issues/613)
|
||||
3. `F` 修复了 `app` 端播放视频可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/617)
|
||||
4. `F` 修复了 `latex` 插件可能出现 `xxx can be used only in display mode` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/632)
|
||||
5. `F` 修复了 `uni-app` 包 `latex` 公式可能不显示的问题 [#599](https://github.com/jin-yufeng/mp-html/issues/599)、[#627](https://github.com/jin-yufeng/mp-html/issues/627)
|
||||
## v2.5.0(2024-04-22)
|
||||
1. `U` `play` 事件增加返回 `src` 等信息 [详细](https://github.com/jin-yufeng/mp-html/issues/526)
|
||||
2. `U` `preview-img` 属性支持设置为 `all` 开启 `base64` 图片预览 [详细](https://github.com/jin-yufeng/mp-html/issues/536)
|
||||
3. `U` `editable` 插件增加简易模式(点击文字直接编辑)
|
||||
4. `U` `latex` 插件支持块级公式 [详细](https://github.com/jin-yufeng/mp-html/issues/582)
|
||||
5. `F` 修复了表格部分情况下背景丢失的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/587)
|
||||
6. `F` 修复了部分 `svg` 无法显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/591)
|
||||
7. `F` 修复了 `h5` 和 `app` 端部分情况下样式无法识别的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/518)
|
||||
8. `F` 修复了 `latex` 插件部分情况下显示不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/580)
|
||||
9. `F` 修复了 `editable` 插件表格无法删除的问题
|
||||
10. `F` 修复了 `editable` 插件 `vue3` `h5` 端点击图片报错的问题
|
||||
11. `F` 修复了 `editable` 插件点击表格没有菜单栏的问题
|
||||
## v2.4.3(2024-01-21)
|
||||
1. `A` 增加 [card](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#card) 插件 [详细](https://github.com/jin-yufeng/mp-html/pull/533) by [@whoooami](https://github.com/whoooami)
|
||||
2. `F` 修复了 `svg` 中包含 `foreignobject` 可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/523)
|
||||
3. `F` 修复了合并单元格的表格部分情况下显示不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/561)
|
||||
4. `F` 修复了 `img` 标签设置 `object-fit` 无效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/567)
|
||||
5. `F` 修复了 `latex` 插件公式会换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/540)
|
||||
6. `F` 修复了 `editable` 和 `audio` 插件共用时点击 `audio` 无法编辑的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/529) by [@whoooami](https://github.com/whoooami)
|
||||
7. `F` 修复了微信小程序部分情况下图片会报错 `replace of undefined` 的问题
|
||||
8. `F` 修复了快手小程序图片不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/571)
|
||||
## v2.4.2(2023-05-14)
|
||||
1. `A` `editable` 插件支持修改文字颜色 [详细](https://github.com/jin-yufeng/mp-html/issues/254)
|
||||
2. `F` 修复了 `svg` 中有 `style` 不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/505)
|
||||
3. `F` 修复了使用旧版编译器可能报错 `Bad attr nodes` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/472)
|
||||
4. `F` 修复了 `app` 端可能出现无法读取 `lazyLoad` 的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/513)
|
||||
5. `F` 修复了 `editable` 插件在点击换图时未拼接 `domain` 的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/497) by [@TwoKe945](https://github.com/TwoKe945)
|
||||
6. `F` 修复了 `latex` 插件部分情况下不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/515)
|
||||
7. `F` 修复了 `editable` 插件点击音视频时其他标签框不消失的问题
|
||||
## v2.4.1(2022-12-25)
|
||||
1. `F` 修复了没有图片时 `ready` 事件可能不触发的问题
|
||||
2. `F` 修复了加载过程中可能出现 `Root label not found` 错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/470)
|
||||
3. `F` 修复了 `audio` 插件退出页面可能会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/457)
|
||||
4. `F` 修复了 `vue3` 运行到 `app` 在 `HBuilder X 3.6.10` 以上报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/480)
|
||||
5. `F` 修复了 `nvue` 端链接中包含 `%22` 时可能无法显示的问题
|
||||
6. `F` 修复了 `vue3` 使用 `highlight` 插件可能报错的问题
|
||||
## v2.4.0(2022-08-27)
|
||||
1. `A` 增加了 [setPlaybackRate](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#setPlaybackRate) 的 `api`,可以设置音视频的播放速率 [详细](https://github.com/jin-yufeng/mp-html/issues/452)
|
||||
2. `A` 示例小程序代码开源 [详细](https://github.com/jin-yufeng/mp-html-demo)
|
||||
3. `U` 优化 `ready` 事件触发时机,未设置懒加载的情况下基本可以准确触发 [详细](https://github.com/jin-yufeng/mp-html/issues/195)
|
||||
4. `U` `highlight` 插件在编辑状态下不进行高亮处理,便于编辑
|
||||
5. `F` 修复了 `flex` 布局下图片大小可能不正确的问题
|
||||
6. `F` 修复了 `selectable` 属性没有设置 `force` 也可能出现渲染异常的问题
|
||||
7. `F` 修复了表格中的图片大小可能不正确的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/448)
|
||||
8. `F` 修复了含有合并单元格的表格可能无法设置竖直对齐的问题
|
||||
9. `F` 修复了 `editable` 插件在 `scroll-view` 中使用时工具条位置可能不正确的问题
|
||||
10. `F` 修复了 `vue3` 使用 [search](advanced/plugin#search) 插件可能导致错误换行的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/449)
|
||||
## v2.3.2(2022-08-13)
|
||||
1. `A` 增加 [latex](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#latex) 插件,可以渲染数学公式 [详细](https://github.com/jin-yufeng/mp-html/pull/447) by [@Zeng-J](https://github.com/Zeng-J)
|
||||
2. `U` 优化根节点下有很多标签的长内容渲染速度
|
||||
3. `U` `highlight` 插件适配 `lang-xxx` 格式
|
||||
4. `F` 修复了 `table` 标签设置 `border` 属性后可能无法修改边框样式的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/439) by [@zouxingjie](https://github.com/zouxingjie)
|
||||
5. `F` 修复了 `editable` 插件输入连续空格无效的问题
|
||||
6. `F` 修复了 `vue3` 图片设置 `inline` 会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/438)
|
||||
7. `F` 修复了 `vue3` 使用 `table` 可能报错的问题
|
||||
## v2.3.1(2022-05-20)
|
||||
1. `U` `app` 端支持使用本地图片
|
||||
2. `U` 优化了微信小程序 `selectable` 属性在 `ios` 端的处理 [详细](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable)
|
||||
3. `F` 修复了 `editable` 插件不在顶部时 `tooltip` 位置可能错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/430)
|
||||
4. `F` 修复了 `vue3` 运行到微信小程序可能报错丢失内容的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/414)
|
||||
5. `F` 修复了 `vue3` 部分标签可能被错误换行的问题
|
||||
6. `F` 修复了 `editable` 插件 `app` 端插入视频无法预览的问题
|
||||
## v2.3.0(2022-04-01)
|
||||
1. `A` 增加了 `play` 事件,音视频播放时触发,可用于与页面其他音视频进行互斥播放 [详细](basic/event#play)
|
||||
2. `U` `show-img-menu` 属性支持控制预览时是否长按弹出菜单
|
||||
3. `U` 优化 `wxs` 处理,提高渲染性能 [详细](https://developers.weixin.qq.com/community/develop/article/doc/0006cc2b204740f601bd43fa25a413)
|
||||
4. `U` `video` 标签支持 `object-fit` 属性
|
||||
5. `U` 增加支持一些常用实体编码 [详细](https://github.com/jin-yufeng/mp-html/issues/418)
|
||||
6. `F` 修复了图片仅设置高度可能不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/410)
|
||||
7. `F` 修复了 `video` 标签高度设置为 `auto` 不显示的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/411)
|
||||
8. `F` 修复了使用 `grid` 布局时可能样式错误的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/413)
|
||||
9. `F` 修复了含有合并单元格的表格部分情况下显示异常的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/417)
|
||||
10. `F` 修复了 `editable` 插件连续插入内容时顺序不正确的问题
|
||||
11. `F` 修复了 `uni-app` 包 `vue3` 使用 `audio` 插件报错的问题
|
||||
12. `F` 修复了 `uni-app` 包 `highlight` 插件使用自定义的 `prism.min.js` 报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/416)
|
||||
## v2.2.2(2022-02-26)
|
||||
1. `A` 增加了 [pauseMedia](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
|
||||
2. `U` 优化了长内容的加载速度
|
||||
3. `U` 适配 `vue3` [#389](https://github.com/jin-yufeng/mp-html/issues/389)、[#398](https://github.com/jin-yufeng/mp-html/pull/398) by [@zhouhuafei](https://github.com/zhouhuafei)、[#400](https://github.com/jin-yufeng/mp-html/issues/400)
|
||||
4. `F` 修复了小程序端图片高度设置为百分比时可能不显示的问题
|
||||
5. `F` 修复了 `highlight` 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
|
||||
## v2.2.1(2021-12-24)
|
||||
1. `A` `editable` 插件增加上下移动标签功能
|
||||
2. `U` `editable` 插件支持在文本中间光标处插入内容
|
||||
3. `F` 修复了 `nvue` 端设置 `margin` 后可能导致高度不正确的问题
|
||||
4. `F` 修复了 `highlight` 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
|
||||
5. `F` 修复了编辑状态下使用 `emoji` 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
|
||||
6. `F` 修复了使用 `editable` 插件后将 `selectable` 属性设置为 `force` 不生效的问题
|
||||
## v2.2.0(2021-10-12)
|
||||
1. `A` 增加 `customElements` 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
|
||||
2. `A` `editable` 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
|
||||
3. `A` `editable` 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
|
||||
4. `U` `editable` 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
|
||||
5. `U` `editable` 插入图片和音视频时支持拼接 `domian` 主域名
|
||||
6. `F` 修复了内部链接参数中包含 `://` 时被认为是外部链接的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/356)
|
||||
7. `F` 修复了部分 `svg` 标签名或属性名大小写不正确时不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/351)
|
||||
8. `F` 修复了 `nvue` 页面运行到非 `app` 平台时可能样式错误的问题
|
||||
## v2.1.5(2021-08-13)
|
||||
1. `A` 增加支持标签的 `dir` 属性
|
||||
2. `F` 修复了 `ruby` 标签文字与拼音没有居中对齐的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/325)
|
||||
3. `F` 修复了音视频标签内有 `a` 标签时可能无法播放的问题
|
||||
4. `F` 修复了 `externStyle` 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
|
||||
5. `F` 修复了 `h5` 端引入 `externStyle` 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
|
||||
## v2.1.4(2021-07-14)
|
||||
1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
|
||||
2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
|
||||
3. `F` 修复了 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
|
||||
4. `F` 修复了 `editable` 插件只能添加图片链接不能修改的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/312) by [@leeseett](https://github.com/leeseett)
|
||||
## v2.1.3(2021-06-12)
|
||||
1. `A` `editable` 插件增加 `insertTable` 方法
|
||||
2. `U` `editable` 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
|
||||
3. `F` 修复了 `externStyle` 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
|
||||
4. `F` 修复了多个组件同时使用时 `tag-style` 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
|
||||
5. `F` 修复了包含 `linearGradient` 的 `svg` 可能无法显示的问题
|
||||
6. `F` 修复了编译到头条小程序时可能报错的问题
|
||||
7. `F` 修复了 `nvue` 端不触发 `click` 事件的问题
|
||||
8. `F` 修复了 `editable` 插件尾部插入时无法撤销的问题
|
||||
9. `F` 修复了 `editable` 插件的 `insertHtml` 方法只能在末尾插入的问题
|
||||
10. `F` 修复了 `editable` 插件插入音频不显示的问题
|
||||
## v2.1.2(2021-04-24)
|
||||
1. `A` 增加了 [img-cache](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#img-cache) 插件,可以在 `app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
|
||||
2. `U` 支持通过 `container-style` 属性设置 `white-space` 来保留连续空格和换行符 [详细](https://jin-yufeng.gitee.io/mp-html/#/question/faq#space)
|
||||
3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
|
||||
4. `U` `editable` 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
|
||||
5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
|
||||
6. `F` 修复了编译到支付宝和头条小程序时部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
|
||||
## v2.1.1(2021-04-09)
|
||||
1. 修复了对 `p` 标签设置 `tag-style` 可能不生效的问题
|
||||
2. 修复了 `svg` 标签中的文本无法显示的问题
|
||||
3. 修复了使用 `editable` 插件编辑表格时可能报错的问题
|
||||
4. 修复了使用 `highlight` 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
|
||||
5. 修复了使用 `editable` 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
|
||||
6. 修复了 `style` 插件连续子选择器失效的问题
|
||||
7. 修复了 `editable` 插件无法修改图片和字体大小的问题
|
||||
## v2.1.0.2(2021-03-21)
|
||||
修复了 `nvue` 端使用可能报错的问题
|
||||
## v2.1.0(2021-03-20)
|
||||
1. `A` 增加了 [container-style](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
|
||||
2. `A` 增加支持 `strike` 标签
|
||||
3. `A` `editable` 插件增加 `placeholder` 属性 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
|
||||
4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
|
||||
5. `U` 外部样式支持标签名选择器 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart#setting)
|
||||
6. `F` 修复了 `nvue` 端部分情况下可能不显示的问题
|
||||
## v2.0.5(2021-03-12)
|
||||
1. `U` [linktap](https://jin-yufeng.gitee.io/mp-html/#/basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
|
||||
2. `U` [selectable](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable) 属性设置为 `force` 时能够在微信 `iOS` 端生效(文本块会变成 `inline-block`) [详细](https://github.com/jin-yufeng/mp-html/issues/267)
|
||||
3. `F` 修复了部分情况下竖向无法滚动的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/182)
|
||||
4. `F` 修复了多次修改富文本数据时部分内容可能不显示的问题
|
||||
5. `F` 修复了 [腾讯视频](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
|
||||
6. `F` 修复了 [highlight](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)
|
||||
498
uni_modules/mp-html/components/mp-html/mp-html.vue
Normal file
@@ -0,0 +1,498 @@
|
||||
<template>
|
||||
<view id="_root" :class="(selectable?'_select ':'')+'_root'" :style="containerStyle">
|
||||
<slot v-if="!nodes[0]" />
|
||||
<!-- #ifndef APP-PLUS-NVUE -->
|
||||
<node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]" name="span" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS-NVUE -->
|
||||
<web-view ref="web" src="/uni_modules/mp-html/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* mp-html v2.5.1
|
||||
* @description 富文本组件
|
||||
* @tutorial https://github.com/jin-yufeng/mp-html
|
||||
* @property {String} container-style 容器的样式
|
||||
* @property {String} content 用于渲染的 html 字符串
|
||||
* @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
|
||||
* @property {String} domain 主域名,用于拼接链接
|
||||
* @property {String} error-img 图片出错时的占位图链接
|
||||
* @property {Boolean} lazy-load 是否开启图片懒加载
|
||||
* @property {string} loading-img 图片加载过程中的占位图链接
|
||||
* @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
|
||||
* @property {Boolean} preview-img 是否允许图片被点击时自动预览
|
||||
* @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
|
||||
* @property {Boolean | String} selectable 是否开启长按复制
|
||||
* @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
|
||||
* @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
|
||||
* @property {Object} tag-style 标签的默认样式
|
||||
* @property {Boolean | Number} use-anchor 是否使用锚点链接
|
||||
* @event {Function} load dom 结构加载完毕时触发
|
||||
* @event {Function} ready 所有图片加载完毕时触发
|
||||
* @event {Function} imgtap 图片被点击时触发
|
||||
* @event {Function} linktap 链接被点击时触发
|
||||
* @event {Function} play 音视频播放时触发
|
||||
* @event {Function} error 媒体加载出错时触发
|
||||
*/
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
import node from './node/node'
|
||||
// #endif
|
||||
import Parser from './parser'
|
||||
const plugins=[]
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
export default {
|
||||
name: 'mp-html',
|
||||
data () {
|
||||
return {
|
||||
nodes: [],
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
height: 3
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
containerStyle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
copyLink: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
domain: String,
|
||||
errorImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
lazyLoad: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
loadingImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
pauseVideo: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
previewImg: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
scrollTable: [Boolean, String],
|
||||
selectable: [Boolean, String],
|
||||
setTitle: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
showImgMenu: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
tagStyle: Object,
|
||||
useAnchor: [Boolean, Number]
|
||||
},
|
||||
// #ifdef VUE3
|
||||
emits: ['load', 'ready', 'imgtap', 'linktap', 'play', 'error'],
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
components: {
|
||||
node
|
||||
},
|
||||
// #endif
|
||||
watch: {
|
||||
content (content) {
|
||||
this.setContent(content)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.plugins = []
|
||||
for (let i = plugins.length; i--;) {
|
||||
this.plugins.push(new plugins[i](this))
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.content && !this.nodes.length) {
|
||||
this.setContent(this.content)
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this._hook('onDetached')
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @description 将锚点跳转的范围限定在一个 scroll-view 内
|
||||
* @param {Object} page scroll-view 所在页面的示例
|
||||
* @param {String} selector scroll-view 的选择器
|
||||
* @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
|
||||
*/
|
||||
in (page, selector, scrollTop) {
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
if (page && selector && scrollTop) {
|
||||
this._in = {
|
||||
page,
|
||||
selector,
|
||||
scrollTop
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 锚点跳转
|
||||
* @param {String} id 要跳转的锚点 id
|
||||
* @param {Number} offset 跳转位置的偏移量
|
||||
* @returns {Promise}
|
||||
*/
|
||||
navigateTo (id, offset) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.useAnchor) {
|
||||
reject(Error('Anchor is disabled'))
|
||||
return
|
||||
}
|
||||
offset = offset || parseInt(this.useAnchor) || 0
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (!id) {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset
|
||||
})
|
||||
resolve()
|
||||
} else {
|
||||
this._navigateTo = {
|
||||
resolve,
|
||||
reject,
|
||||
offset
|
||||
}
|
||||
this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let deep = ' '
|
||||
// #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
|
||||
deep = '>>>'
|
||||
// #endif
|
||||
const selector = uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this._in ? this._in.page : this)
|
||||
// #endif
|
||||
.select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
|
||||
if (this._in) {
|
||||
selector.select(this._in.selector).scrollOffset()
|
||||
.select(this._in.selector).boundingClientRect()
|
||||
} else {
|
||||
// 获取 scroll-view 的位置和滚动距离
|
||||
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
|
||||
}
|
||||
selector.exec(res => {
|
||||
if (!res[0]) {
|
||||
reject(Error('Label not found'))
|
||||
return
|
||||
}
|
||||
const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
|
||||
if (this._in) {
|
||||
// scroll-view 跳转
|
||||
this._in.page[this._in.scrollTop] = scrollTop
|
||||
} else {
|
||||
// 页面跳转
|
||||
uni.pageScrollTo({
|
||||
scrollTop,
|
||||
duration: 300
|
||||
})
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取文本内容
|
||||
* @return {String}
|
||||
*/
|
||||
getText (nodes) {
|
||||
let text = '';
|
||||
(function traversal (nodes) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
if (node.type === 'text') {
|
||||
text += node.text.replace(/&/g, '&')
|
||||
} else if (node.name === 'br') {
|
||||
text += '\n'
|
||||
} else {
|
||||
// 块级标签前后加换行
|
||||
const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
|
||||
if (isBlock && text && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
}
|
||||
// 递归获取子节点的文本
|
||||
if (node.children) {
|
||||
traversal(node.children)
|
||||
}
|
||||
if (isBlock && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
} else if (node.name === 'td' || node.name === 'th') {
|
||||
text += '\t'
|
||||
}
|
||||
}
|
||||
}
|
||||
})(nodes || this.nodes)
|
||||
return text
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取内容大小和位置
|
||||
* @return {Promise}
|
||||
*/
|
||||
getRect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 暂停播放媒体
|
||||
*/
|
||||
pauseMedia () {
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].pause()
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let page = this.$parent
|
||||
while (!page.$scope) page = page.$parent
|
||||
page.$scope.$getAppWebview().evalJS(command)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$refs.web.evalJs(command)
|
||||
// #endif
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置媒体播放速率
|
||||
* @param {Number} rate 播放速率
|
||||
*/
|
||||
setPlaybackRate (rate) {
|
||||
this.playbackRate = rate
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].playbackRate(rate)
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].playbackRate=' + rate
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let page = this.$parent
|
||||
while (!page.$scope) page = page.$parent
|
||||
page.$scope.$getAppWebview().evalJS(command)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$refs.web.evalJs(command)
|
||||
// #endif
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置内容
|
||||
* @param {String} content html 内容
|
||||
* @param {Boolean} append 是否在尾部追加
|
||||
*/
|
||||
setContent (content, append) {
|
||||
if (!append || !this.imgList) {
|
||||
this.imgList = []
|
||||
}
|
||||
const nodes = new Parser(this).parse(content)
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (this._ready) {
|
||||
this._set(nodes, append)
|
||||
}
|
||||
// #endif
|
||||
this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
|
||||
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
this._videos = []
|
||||
this.$nextTick(() => {
|
||||
this._hook('onLoad')
|
||||
this.$emit('load')
|
||||
})
|
||||
|
||||
if (this.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
|
||||
// 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
|
||||
let height = 0
|
||||
const callback = rect => {
|
||||
if (!rect || !rect.height) rect = {}
|
||||
// 350ms 总高度无变化就触发 ready 事件
|
||||
if (rect.height === height) {
|
||||
this.$emit('ready', rect)
|
||||
} else {
|
||||
height = rect.height
|
||||
setTimeout(() => {
|
||||
this.getRect().then(callback).catch(callback)
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
this.getRect().then(callback).catch(callback)
|
||||
} else {
|
||||
// 未设置懒加载,等待所有图片加载完毕
|
||||
if (!this.imgList._unloadimgs) {
|
||||
this.getRect().then(rect => {
|
||||
this.$emit('ready', rect)
|
||||
}).catch(() => {
|
||||
this.$emit('ready', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 调用插件钩子函数
|
||||
*/
|
||||
_hook (name) {
|
||||
for (let i = plugins.length; i--;) {
|
||||
if (this.plugins[i][name]) {
|
||||
this.plugins[i][name]()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
/**
|
||||
* @description 设置内容
|
||||
*/
|
||||
_set (nodes, append) {
|
||||
this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes).replace(/%22/g, '') + ',' + JSON.stringify([this.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 接收到 web-view 消息
|
||||
*/
|
||||
_onMessage (e) {
|
||||
const message = e.detail.data[0]
|
||||
switch (message.action) {
|
||||
// web-view 初始化完毕
|
||||
case 'onJSBridgeReady':
|
||||
this._ready = true
|
||||
if (this.nodes) {
|
||||
this._set(this.nodes)
|
||||
}
|
||||
break
|
||||
// 内容 dom 加载完毕
|
||||
case 'onLoad':
|
||||
this.height = message.height
|
||||
this._hook('onLoad')
|
||||
this.$emit('load')
|
||||
break
|
||||
// 所有图片加载完毕
|
||||
case 'onReady':
|
||||
this.getRect().then(res => {
|
||||
this.$emit('ready', res)
|
||||
}).catch(() => {
|
||||
this.$emit('ready', {})
|
||||
})
|
||||
break
|
||||
// 总高度发生变化
|
||||
case 'onHeightChange':
|
||||
this.height = message.height
|
||||
break
|
||||
// 图片点击
|
||||
case 'onImgTap':
|
||||
this.$emit('imgtap', message.attrs)
|
||||
if (this.previewImg) {
|
||||
uni.previewImage({
|
||||
current: parseInt(message.attrs.i),
|
||||
urls: this.imgList
|
||||
})
|
||||
}
|
||||
break
|
||||
// 链接点击
|
||||
case 'onLinkTap': {
|
||||
const href = message.attrs.href
|
||||
this.$emit('linktap', message.attrs)
|
||||
if (href) {
|
||||
// 锚点跳转
|
||||
if (href[0] === '#') {
|
||||
if (this.useAnchor) {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset: message.offset
|
||||
})
|
||||
}
|
||||
} else if (href.includes('://')) {
|
||||
// 打开外链
|
||||
if (this.copyLink) {
|
||||
plus.runtime.openWeb(href)
|
||||
}
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: href,
|
||||
fail () {
|
||||
uni.switchTab({
|
||||
url: href
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'onPlay':
|
||||
this.$emit('play')
|
||||
break
|
||||
// 获取到锚点的偏移量
|
||||
case 'getOffset':
|
||||
if (typeof message.offset === 'number') {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset: message.offset + this._navigateTo.offset
|
||||
})
|
||||
this._navigateTo.resolve()
|
||||
} else {
|
||||
this._navigateTo.reject(Error('Label not found'))
|
||||
}
|
||||
break
|
||||
// 点击
|
||||
case 'onClick':
|
||||
this.$emit('tap')
|
||||
this.$emit('click')
|
||||
break
|
||||
// 出错
|
||||
case 'onError':
|
||||
this.$emit('error', {
|
||||
source: message.source,
|
||||
attrs: message.attrs
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
/* 根节点样式 */
|
||||
._root {
|
||||
padding: 1px 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* 长按复制 */
|
||||
._select {
|
||||
user-select: text;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
597
uni_modules/mp-html/components/mp-html/node/node.vue
Normal file
@@ -0,0 +1,597 @@
|
||||
<template>
|
||||
<view :id="attrs.id" :class="'_block _'+name+' '+attrs.class" :style="attrs.style">
|
||||
<block v-for="(n, i) in childs" v-bind:key="i">
|
||||
<!-- 图片 -->
|
||||
<!-- 占位图 -->
|
||||
<image v-if="n.name==='img'&&!n.t&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
|
||||
<!-- 显示图片 -->
|
||||
<!-- #ifdef H5 || (APP-PLUS && VUE2) -->
|
||||
<img v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || (APP-PLUS && VUE2) -->
|
||||
<!-- 表格中的图片,使用 rich-text 防止大小不正确 -->
|
||||
<rich-text v-if="n.name==='img'&&n.t" :style="'display:'+n.t" :nodes="[{attrs:{style:n.attrs.style||'',src:n.attrs.src},name:'img'}]" :data-i="i" @tap.stop="imgTap" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+ctrl[i]+'px;'+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :mode="!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || APP-PLUS || MP-KUAISHOU -->
|
||||
<image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style" :src="n.attrs.src" :mode="!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-KUAISHOU -->
|
||||
<image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src" :lazy-load="opts[0]" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap"></image>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS && VUE3 -->
|
||||
<image v-else-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;'+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :mode="!n.h?'widthFix':(!n.w?'heightFix':(n.m||''))" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
|
||||
<!-- #endif -->
|
||||
<!-- 文本 -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<text v-else-if="n.text" :user-select="opts[4]=='force'&&isiOS" decode>{{n.text}}</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN || MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
|
||||
<text v-else-if="n.text" decode>{{n.text}}</text>
|
||||
<!-- #endif -->
|
||||
<text v-else-if="n.name==='br'">\n</text>
|
||||
<!-- 链接 -->
|
||||
<view v-else-if="n.name==='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class" hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @tap.stop="linkTap">
|
||||
<node name="span" :childs="n.children" :opts="opts" style="display:inherit" />
|
||||
</view>
|
||||
<!-- 视频 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view v-else-if="n.html" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style" v-html="n.html" :data-i="i" @vplay.stop="play" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<video v-else-if="n.name==='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :object-fit="n.attrs['object-fit']" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 || APP-PLUS -->
|
||||
<iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
|
||||
<embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
|
||||
<!-- 音频 -->
|
||||
<audio v-else-if="n.name==='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
|
||||
<!-- #endif -->
|
||||
<view v-else-if="(n.name==='table'&&n.c)||n.name==='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
|
||||
<node v-if="n.name==='li'" :childs="n.children" :opts="opts" />
|
||||
<view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
|
||||
<node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="opts" />
|
||||
<block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
|
||||
<view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
|
||||
<node :childs="tr.children" :opts="opts" />
|
||||
</view>
|
||||
<view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
|
||||
<view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
|
||||
<node :childs="td.children" :opts="opts" />
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 富文本 -->
|
||||
<!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
|
||||
<rich-text v-else-if="!n.c&&!handler.isInline(n.name, n.attrs.style)" :id="n.attrs.id" :style="n.f" :user-select="opts[4]" :nodes="[n]" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
|
||||
<rich-text v-else-if="!n.c" :id="n.attrs.id" :style="'display:inline;'+n.f" :preview="false" :selectable="opts[4]" :user-select="opts[4]" :nodes="[n]" />
|
||||
<!-- #endif -->
|
||||
<!-- 继续递归 -->
|
||||
<view v-else-if="n.c===2" :id="n.attrs.id" :class="'_block _'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
|
||||
<node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs" :childs="n2.children" :opts="opts" />
|
||||
</view>
|
||||
<node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" />
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<script module="handler" lang="wxs">
|
||||
// 行内标签列表
|
||||
var inlineTags = {
|
||||
abbr: true,
|
||||
b: true,
|
||||
big: true,
|
||||
code: true,
|
||||
del: true,
|
||||
em: true,
|
||||
i: true,
|
||||
ins: true,
|
||||
label: true,
|
||||
q: true,
|
||||
small: true,
|
||||
span: true,
|
||||
strong: true,
|
||||
sub: true,
|
||||
sup: true
|
||||
}
|
||||
/**
|
||||
* @description 判断是否为行内标签
|
||||
*/
|
||||
module.exports = {
|
||||
isInline: function (tagName, style) {
|
||||
return inlineTags[tagName] || (style || '').indexOf('display:inline') !== -1
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
|
||||
import node from './node'
|
||||
export default {
|
||||
name: 'node',
|
||||
options: {
|
||||
// #ifdef MP-WEIXIN
|
||||
virtualHost: true,
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
addGlobalClass: false
|
||||
// #endif
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
ctrl: {},
|
||||
// #ifdef MP-WEIXIN
|
||||
isiOS: uni.getSystemInfoSync().system.includes('iOS')
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: String,
|
||||
attrs: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
childs: Array,
|
||||
opts: Array
|
||||
},
|
||||
components: {
|
||||
|
||||
// #ifndef ((H5 || APP-PLUS) && VUE3) || APP-HARMONY
|
||||
node
|
||||
// #endif
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick(() => {
|
||||
for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root.$parent);
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (this.opts[0]) {
|
||||
let i
|
||||
for (i = this.childs.length; i--;) {
|
||||
if (this.childs[i].name === 'img') break
|
||||
}
|
||||
if (i !== -1) {
|
||||
this.observer = uni.createIntersectionObserver(this).relativeToViewport({
|
||||
top: 500,
|
||||
bottom: 500
|
||||
})
|
||||
this.observer.observe('._img', res => {
|
||||
if (res.intersectionRatio) {
|
||||
this.$set(this.ctrl, 'load', 1)
|
||||
this.observer.disconnect()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
beforeDestroy () {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (this.observer) {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods:{
|
||||
// #ifdef MP-WEIXIN
|
||||
toJSON () { return this },
|
||||
// #endif
|
||||
/**
|
||||
* @description 播放视频事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
play (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
const node = this.childs[i]
|
||||
this.root.$emit('play', {
|
||||
source: node.name,
|
||||
attrs: {
|
||||
...node.attrs,
|
||||
src: node.src[this.ctrl[i] || 0]
|
||||
}
|
||||
})
|
||||
// #ifndef APP-PLUS
|
||||
if (this.root.pauseVideo) {
|
||||
let flag = false
|
||||
const id = e.target.id
|
||||
for (let i = this.root._videos.length; i--;) {
|
||||
if (this.root._videos[i].id === id) {
|
||||
flag = true
|
||||
} else {
|
||||
this.root._videos[i].pause() // 自动暂停其他视频
|
||||
}
|
||||
}
|
||||
// 将自己加入列表
|
||||
if (!flag) {
|
||||
const ctx = uni.createVideoContext(id
|
||||
// #ifndef MP-BAIDU
|
||||
, this
|
||||
// #endif
|
||||
)
|
||||
ctx.id = id
|
||||
if (this.root.playbackRate) {
|
||||
ctx.playbackRate(this.root.playbackRate)
|
||||
}
|
||||
this.root._videos.push(ctx)
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgTap (e) {
|
||||
const node = this.childs[e.currentTarget.dataset.i]
|
||||
if (node.a) {
|
||||
this.linkTap(node.a)
|
||||
return
|
||||
}
|
||||
if (node.attrs.ignore) return
|
||||
// #ifdef H5 || APP-PLUS
|
||||
node.attrs.src = node.attrs.src || node.attrs['data-src']
|
||||
// #endif
|
||||
// #ifndef APP-HARMONY
|
||||
this.root.$emit('imgtap', node.attrs)
|
||||
// #endif
|
||||
// #ifdef APP-HARMONY
|
||||
this.root.$emit('imgtap', {
|
||||
...node.attrs
|
||||
})
|
||||
// #endif
|
||||
// 自动预览图片
|
||||
if (this.root.previewImg) {
|
||||
uni.previewImage({
|
||||
// #ifdef MP-WEIXIN
|
||||
showmenu: this.root.showImgMenu,
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
enablesavephoto: this.root.showImgMenu,
|
||||
enableShowPhotoDownload: this.root.showImgMenu,
|
||||
// #endif
|
||||
current: parseInt(node.attrs.i),
|
||||
urls: this.root.imgList
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片长按
|
||||
*/
|
||||
imgLongTap (e) {
|
||||
// #ifdef APP-PLUS
|
||||
const attrs = this.childs[e.currentTarget.dataset.i].attrs
|
||||
if (this.opts[3] && !attrs.ignore) {
|
||||
uni.showActionSheet({
|
||||
itemList: ['保存图片'],
|
||||
success: () => {
|
||||
const save = path => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: path,
|
||||
success () {
|
||||
uni.showToast({
|
||||
title: '保存成功'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.root.imgList[attrs.i].startsWith('http')) {
|
||||
uni.downloadFile({
|
||||
url: this.root.imgList[attrs.i],
|
||||
success: res => save(res.tempFilePath)
|
||||
})
|
||||
} else {
|
||||
save(this.root.imgList[attrs.i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片加载完成事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgLoad (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
/* #ifndef H5 || (APP-PLUS && VUE2) */
|
||||
if (!this.childs[i].w) {
|
||||
// 设置原宽度
|
||||
this.$set(this.ctrl, i, e.detail.width)
|
||||
} else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
|
||||
// 加载完毕,取消加载中占位图
|
||||
this.$set(this.ctrl, i, 1)
|
||||
}
|
||||
this.checkReady()
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 检查是否所有图片加载完毕
|
||||
*/
|
||||
checkReady () {
|
||||
if (this.root && !this.root.lazyLoad) {
|
||||
this.root._unloadimgs -= 1
|
||||
if (!this.root._unloadimgs) {
|
||||
setTimeout(() => {
|
||||
this.root.getRect().then(rect => {
|
||||
this.root.$emit('ready', rect)
|
||||
}).catch(() => {
|
||||
this.root.$emit('ready', {})
|
||||
})
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 链接点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
linkTap (e) {
|
||||
const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
|
||||
const attrs = node.attrs || e
|
||||
const href = attrs.href
|
||||
this.root.$emit('linktap', Object.assign({
|
||||
innerText: this.root.getText(node.children || []) // 链接内的文本内容
|
||||
}, attrs))
|
||||
if (href) {
|
||||
if (href[0] === '#') {
|
||||
// 跳转锚点
|
||||
this.root.navigateTo(href.substring(1)).catch(() => { })
|
||||
} else if (href.split('?')[0].includes('://')) {
|
||||
// 复制外部链接
|
||||
if (this.root.copyLink) {
|
||||
// #ifdef H5
|
||||
window.open(href)
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
uni.setClipboardData({
|
||||
data: href,
|
||||
success: () =>
|
||||
uni.showToast({
|
||||
title: '链接已复制'
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
plus.runtime.openWeb(href)
|
||||
// #endif
|
||||
}
|
||||
} else {
|
||||
// 跳转页面
|
||||
uni.navigateTo({
|
||||
url: href,
|
||||
fail () {
|
||||
uni.switchTab({
|
||||
url: href,
|
||||
fail () { }
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 错误事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
mediaError (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
const node = this.childs[i]
|
||||
// 加载其他源
|
||||
if (node.name === 'video' || node.name === 'audio') {
|
||||
let index = (this.ctrl[i] || 0) + 1
|
||||
if (index > node.src.length) {
|
||||
index = 0
|
||||
}
|
||||
if (index < node.src.length) {
|
||||
this.$set(this.ctrl, i, index)
|
||||
return
|
||||
}
|
||||
} else if (node.name === 'img') {
|
||||
// #ifdef H5 && VUE3
|
||||
if (this.opts[0] && !this.ctrl.load) return
|
||||
// #endif
|
||||
// 显示错误占位图
|
||||
if (this.opts[2]) {
|
||||
this.$set(this.ctrl, i, -1)
|
||||
}
|
||||
this.checkReady()
|
||||
}
|
||||
if (this.root) {
|
||||
this.root.$emit('error', {
|
||||
source: node.name,
|
||||
attrs: node.attrs,
|
||||
// #ifndef H5 && VUE3
|
||||
errMsg: e.detail.errMsg
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* a 标签默认效果 */
|
||||
._a {
|
||||
padding: 1.5px 0 1.5px 0;
|
||||
color: #366092;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* a 标签点击态效果 */
|
||||
._hover {
|
||||
text-decoration: underline;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 图片默认效果 */
|
||||
._img {
|
||||
max-width: 100%;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
/* 内部样式 */
|
||||
|
||||
._block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
._b,
|
||||
._strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
._del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
._em,
|
||||
._i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
._h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
._h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
._h3 {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
._h5 {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
|
||||
._h6 {
|
||||
font-size: 0.67em;
|
||||
}
|
||||
|
||||
._h1,
|
||||
._h2,
|
||||
._h3,
|
||||
._h4,
|
||||
._h5,
|
||||
._h6 {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._image {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
._ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._li {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
._ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
._ol,
|
||||
._ul {
|
||||
display: block;
|
||||
padding-left: 40px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
._q::before {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._q::after {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._sub {
|
||||
font-size: smaller;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
._sup {
|
||||
font-size: smaller;
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
._thead,
|
||||
._tbody,
|
||||
._tfoot {
|
||||
display: table-row-group;
|
||||
}
|
||||
|
||||
._tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
._td,
|
||||
._th {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
._th {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
._ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
._ul ._ul {
|
||||
margin: 0;
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
._ul ._ul ._ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
._abbr,
|
||||
._b,
|
||||
._code,
|
||||
._del,
|
||||
._em,
|
||||
._i,
|
||||
._ins,
|
||||
._label,
|
||||
._q,
|
||||
._span,
|
||||
._strong,
|
||||
._sub,
|
||||
._sup {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* #ifdef APP-PLUS */
|
||||
._video {
|
||||
width: 300px;
|
||||
height: 225px;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
1400
uni_modules/mp-html/components/mp-html/parser.js
Normal file
79
uni_modules/mp-html/package.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"id": "mp-html",
|
||||
"displayName": "mp-html 富文本组件【全端支持,支持编辑、latex等扩展】",
|
||||
"version": "v2.5.1",
|
||||
"description": "一个强大的富文本组件,高效轻量,功能丰富",
|
||||
"keywords": [
|
||||
"富文本",
|
||||
"编辑器",
|
||||
"html",
|
||||
"rich-text",
|
||||
"editor"
|
||||
],
|
||||
"repository": "https://github.com/jin-yufeng/mp-html",
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/mp-html",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y",
|
||||
"app-harmony": "u",
|
||||
"app-uvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d<r.length;d++)!function(d){var u=r[d],l=void 0;if(u.type&&"node"!==u.type)l=document.createTextNode(u.text.replace(/&/g,"&"));else{var g=u.name;"svg"===g&&(c="http://www.w3.org/2000/svg"),"html"!==g&&"body"!==g||(g="div"),l=c?document.createElementNS(c,g):document.createElement(g);for(var p in u.attrs)l.setAttribute(p,u.attrs[p]);if(u.children&&o(u.children,l,c),"img"===g){if(window.unloadimgs+=1,l.onload=n,l.onerror=n,!l.src&&l.getAttribute("data-src")&&(l.src=l.getAttribute("data-src")),u.attrs.ignore||(l.onclick=function(e){e.stopPropagation(),uni.postMessage({data:{action:"onImgTap",attrs:t(this)}})}),a[2]){var h=new Image;h.src=l.src,l.src=a[2],h.onload=function(){l.src=this.src},h.onerror=function(){l.onerror()}}l.onerror=e}else if("a"===g)l.addEventListener("click",function(e){e.stopPropagation(),e.preventDefault();var n,o=this.getAttribute("href");o&&"#"===o[0]&&(n=(document.getElementById(o.substr(1))||{}).offsetTop),uni.postMessage({data:{action:"onLinkTap",attrs:t(this),offset:n}})},!0);else if("video"===g||"audio"===g)i.push(l),u.attrs.autoplay||u.attrs.controls||l.setAttribute("controls","true"),l.onplay=function(){if(uni.postMessage({data:{action:"onPlay"}}),a[3])for(var t=0;t<i.length;t++)i[t]!==this&&i[t].pause()},l.onerror=function(){uni.postMessage({data:{action:"onError",source:g,attrs:t(this)}})};else if("table"===g&&a[4]&&!l.style.cssText.includes("inline")){var f=document.createElement("div");f.style.overflow="auto",f.appendChild(l),l=f}else"svg"===g&&(c=void 0)}s.appendChild(l)}(d)}document.addEventListener("UniAppJSBridgeReady",function(){document.body.onclick=function(){return uni.postMessage({data:{action:"onClick"}})},uni.postMessage({data:{action:"onJSBridgeReady"}})});var a,i=[];window.setContent=function(t,e,n){var r=document.getElementById("content");e[0]&&(document.body.style.cssText=e[0]),e[5]||(r.style.userSelect="none"),n||(r.innerHTML="",i=[]),a=e,window.unloadimgs=0;var s=document.createDocumentFragment();o(t,s),r.appendChild(s);var c=r.scrollHeight;uni.postMessage({data:{action:"onLoad",height:c}}),window.unloadimgs||uni.postMessage({data:{action:"onReady",height:c}}),clearInterval(window.timer),window.timer=setInterval(function(){r.scrollHeight!==c&&(c=r.scrollHeight,uni.postMessage({data:{action:"onHeightChange",height:c}}))},350)},window.onunload=function(){clearInterval(window.timer)};
|
||||
1
uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));
|
||||
1
uni_modules/mp-html/static/app-plus/mp-html/local.html
Normal file
@@ -0,0 +1 @@
|
||||
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>
|
||||
10
uni_modules/uni-dateformat/changelog.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 1.0.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
|
||||
## 0.0.5(2021-07-08)
|
||||
- 调整 默认时间不再是当前时间,而是显示'-'字符
|
||||
## 0.0.4(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 0.0.3(2021-02-04)
|
||||
- 调整为uni_modules目录规范
|
||||
- 修复 iOS 平台日期格式化出错的问题
|
||||
@@ -0,0 +1,200 @@
|
||||
// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
|
||||
function pad(str, length = 2) {
|
||||
str += ''
|
||||
while (str.length < length) {
|
||||
str = '0' + str
|
||||
}
|
||||
return str.slice(-length)
|
||||
}
|
||||
|
||||
const parser = {
|
||||
yyyy: (dateObj) => {
|
||||
return pad(dateObj.year, 4)
|
||||
},
|
||||
yy: (dateObj) => {
|
||||
return pad(dateObj.year)
|
||||
},
|
||||
MM: (dateObj) => {
|
||||
return pad(dateObj.month)
|
||||
},
|
||||
M: (dateObj) => {
|
||||
return dateObj.month
|
||||
},
|
||||
dd: (dateObj) => {
|
||||
return pad(dateObj.day)
|
||||
},
|
||||
d: (dateObj) => {
|
||||
return dateObj.day
|
||||
},
|
||||
hh: (dateObj) => {
|
||||
return pad(dateObj.hour)
|
||||
},
|
||||
h: (dateObj) => {
|
||||
return dateObj.hour
|
||||
},
|
||||
mm: (dateObj) => {
|
||||
return pad(dateObj.minute)
|
||||
},
|
||||
m: (dateObj) => {
|
||||
return dateObj.minute
|
||||
},
|
||||
ss: (dateObj) => {
|
||||
return pad(dateObj.second)
|
||||
},
|
||||
s: (dateObj) => {
|
||||
return dateObj.second
|
||||
},
|
||||
SSS: (dateObj) => {
|
||||
return pad(dateObj.millisecond, 3)
|
||||
},
|
||||
S: (dateObj) => {
|
||||
return dateObj.millisecond
|
||||
},
|
||||
}
|
||||
|
||||
// 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12
|
||||
function getDate(time) {
|
||||
if (time instanceof Date) {
|
||||
return time
|
||||
}
|
||||
switch (typeof time) {
|
||||
case 'string':
|
||||
{
|
||||
// 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
|
||||
if (time.indexOf('T') > -1) {
|
||||
return new Date(time)
|
||||
}
|
||||
return new Date(time.replace(/-/g, '/'))
|
||||
}
|
||||
default:
|
||||
return new Date(time)
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') {
|
||||
if (!date && date !== 0) {
|
||||
return ''
|
||||
}
|
||||
date = getDate(date)
|
||||
const dateObj = {
|
||||
year: date.getFullYear(),
|
||||
month: date.getMonth() + 1,
|
||||
day: date.getDate(),
|
||||
hour: date.getHours(),
|
||||
minute: date.getMinutes(),
|
||||
second: date.getSeconds(),
|
||||
millisecond: date.getMilliseconds()
|
||||
}
|
||||
const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
|
||||
let flag = true
|
||||
let result = format
|
||||
while (flag) {
|
||||
flag = false
|
||||
result = result.replace(tokenRegExp, function(matched) {
|
||||
flag = true
|
||||
return parser[matched](dateObj)
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function friendlyDate(time, {
|
||||
locale = 'zh',
|
||||
threshold = [60000, 3600000],
|
||||
format = 'yyyy/MM/dd hh:mm:ss'
|
||||
}) {
|
||||
if (time === '-') {
|
||||
return time
|
||||
}
|
||||
if (!time && time !== 0) {
|
||||
return ''
|
||||
}
|
||||
const localeText = {
|
||||
zh: {
|
||||
year: '年',
|
||||
month: '月',
|
||||
day: '天',
|
||||
hour: '小时',
|
||||
minute: '分钟',
|
||||
second: '秒',
|
||||
ago: '前',
|
||||
later: '后',
|
||||
justNow: '刚刚',
|
||||
soon: '马上',
|
||||
template: '{num}{unit}{suffix}'
|
||||
},
|
||||
en: {
|
||||
year: 'year',
|
||||
month: 'month',
|
||||
day: 'day',
|
||||
hour: 'hour',
|
||||
minute: 'minute',
|
||||
second: 'second',
|
||||
ago: 'ago',
|
||||
later: 'later',
|
||||
justNow: 'just now',
|
||||
soon: 'soon',
|
||||
template: '{num} {unit} {suffix}'
|
||||
}
|
||||
}
|
||||
const text = localeText[locale] || localeText.zh
|
||||
let date = getDate(time)
|
||||
let ms = date.getTime() - Date.now()
|
||||
let absMs = Math.abs(ms)
|
||||
if (absMs < threshold[0]) {
|
||||
return ms < 0 ? text.justNow : text.soon
|
||||
}
|
||||
if (absMs >= threshold[1]) {
|
||||
return formatDate(date, format)
|
||||
}
|
||||
let num
|
||||
let unit
|
||||
let suffix = text.later
|
||||
if (ms < 0) {
|
||||
suffix = text.ago
|
||||
ms = -ms
|
||||
}
|
||||
const seconds = Math.floor((ms) / 1000)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
const days = Math.floor(hours / 24)
|
||||
const months = Math.floor(days / 30)
|
||||
const years = Math.floor(months / 12)
|
||||
switch (true) {
|
||||
case years > 0:
|
||||
num = years
|
||||
unit = text.year
|
||||
break
|
||||
case months > 0:
|
||||
num = months
|
||||
unit = text.month
|
||||
break
|
||||
case days > 0:
|
||||
num = days
|
||||
unit = text.day
|
||||
break
|
||||
case hours > 0:
|
||||
num = hours
|
||||
unit = text.hour
|
||||
break
|
||||
case minutes > 0:
|
||||
num = minutes
|
||||
unit = text.minute
|
||||
break
|
||||
default:
|
||||
num = seconds
|
||||
unit = text.second
|
||||
break
|
||||
}
|
||||
|
||||
if (locale === 'en') {
|
||||
if (num === 1) {
|
||||
num = 'a'
|
||||
} else {
|
||||
unit += 's'
|
||||
}
|
||||
}
|
||||
|
||||
return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
|
||||
suffix)
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<text>{{dateShow}}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {friendlyDate} from './date-format.js'
|
||||
/**
|
||||
* Dateformat 日期格式化
|
||||
* @description 日期格式化组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3279
|
||||
* @property {Object|String|Number} date 日期对象/日期字符串/时间戳
|
||||
* @property {String} locale 格式化使用的语言
|
||||
* @value zh 中文
|
||||
* @value en 英文
|
||||
* @property {Array} threshold 应用不同类型格式化的阈值
|
||||
* @property {String} format 输出日期字符串时的格式
|
||||
*/
|
||||
export default {
|
||||
name: 'uniDateformat',
|
||||
props: {
|
||||
date: {
|
||||
type: [Object, String, Number],
|
||||
default () {
|
||||
return '-'
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
type: String,
|
||||
default: 'zh',
|
||||
},
|
||||
threshold: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [0, 0]
|
||||
}
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
default: 'yyyy/MM/dd hh:mm:ss'
|
||||
},
|
||||
// refreshRate使用不当可能导致性能问题,谨慎使用
|
||||
refreshRate: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
refreshMark: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dateShow() {
|
||||
this.refreshMark
|
||||
return friendlyDate(this.date, {
|
||||
locale: this.locale,
|
||||
threshold: this.threshold,
|
||||
format: this.format
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
refreshRate: {
|
||||
handler() {
|
||||
this.setAutoRefresh()
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refresh() {
|
||||
this.refreshMark++
|
||||
},
|
||||
setAutoRefresh() {
|
||||
clearInterval(this.refreshInterval)
|
||||
if (this.refreshRate) {
|
||||
this.refreshInterval = setInterval(() => {
|
||||
this.refresh()
|
||||
}, parseInt(this.refreshRate))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
88
uni_modules/uni-dateformat/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uni-dateformat",
|
||||
"displayName": "uni-dateformat 日期格式化",
|
||||
"version": "1.0.0",
|
||||
"description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"日期格式化",
|
||||
"时间格式化",
|
||||
"格式化时间",
|
||||
""
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
uni_modules/uni-dateformat/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
### DateFormat 日期格式化
|
||||
> **组件名:uni-dateformat**
|
||||
> 代码块: `uDateformat`
|
||||
|
||||
|
||||
日期格式化组件。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
42
uni_modules/uni-icons/changelog.md
Normal file
@@ -0,0 +1,42 @@
|
||||
## 2.0.10(2024-06-07)
|
||||
- 优化 uni-app x 中,size 属性的类型
|
||||
## 2.0.9(2024-01-12)
|
||||
fix: 修复图标大小默认值错误的问题
|
||||
## 2.0.8(2023-12-14)
|
||||
- 修复 项目未使用 ts 情况下,打包报错的bug
|
||||
## 2.0.7(2023-12-14)
|
||||
- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug
|
||||
## 2.0.6(2023-12-11)
|
||||
- 优化 兼容老版本icon类型,如 top ,bottom 等
|
||||
## 2.0.5(2023-12-11)
|
||||
- 优化 兼容老版本icon类型,如 top ,bottom 等
|
||||
## 2.0.4(2023-12-06)
|
||||
- 优化 uni-app x 下示例项目图标排序
|
||||
## 2.0.3(2023-12-06)
|
||||
- 修复 nvue下引入组件报错的bug
|
||||
## 2.0.2(2023-12-05)
|
||||
-优化 size 属性支持单位
|
||||
## 2.0.1(2023-12-05)
|
||||
- 新增 uni-app x 支持定义图标
|
||||
## 1.3.5(2022-01-24)
|
||||
- 优化 size 属性可以传入不带单位的字符串数值
|
||||
## 1.3.4(2022-01-24)
|
||||
- 优化 size 支持其他单位
|
||||
## 1.3.3(2022-01-17)
|
||||
- 修复 nvue 有些图标不显示的bug,兼容老版本图标
|
||||
## 1.3.2(2021-12-01)
|
||||
- 优化 示例可复制图标名称
|
||||
## 1.3.1(2021-11-23)
|
||||
- 优化 兼容旧组件 type 值
|
||||
## 1.3.0(2021-11-19)
|
||||
- 新增 更多图标
|
||||
- 优化 自定义图标使用方式
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
|
||||
## 1.1.7(2021-11-08)
|
||||
## 1.2.0(2021-07-30)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.1.5(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.1.4(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
91
uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<text class="uni-icons" :style="styleObj">
|
||||
<slot>{{unicode}}</slot>
|
||||
</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fontData, IconsDataItem } from './uniicons_file'
|
||||
|
||||
/**
|
||||
* Icons 图标
|
||||
* @description 用于展示 icon 图标
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
|
||||
* @property {Number,String} size 图标大小
|
||||
* @property {String} type 图标图案,参考示例
|
||||
* @property {String} color 图标颜色
|
||||
* @property {String} customPrefix 自定义图标
|
||||
* @event {Function} click 点击 Icon 触发事件
|
||||
*/
|
||||
export default {
|
||||
name: "uni-icons",
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333333'
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 16
|
||||
},
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
unicode() : string {
|
||||
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
|
||||
if (codes !== null) {
|
||||
return codes.unicode
|
||||
}
|
||||
return ''
|
||||
},
|
||||
iconSize() : string {
|
||||
const size = this.size
|
||||
if (typeof size == 'string') {
|
||||
const reg = /^[0-9]*$/g
|
||||
return reg.test(size as string) ? '' + size + 'px' : '' + size;
|
||||
// return '' + this.size
|
||||
}
|
||||
return this.getFontSize(size as number)
|
||||
},
|
||||
styleObj() : UTSJSONObject {
|
||||
if (this.fontFamily !== '') {
|
||||
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
|
||||
}
|
||||
return { color: this.color, fontSize: this.iconSize }
|
||||
}
|
||||
},
|
||||
created() { },
|
||||
methods: {
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
getFontSize(size : number) : string {
|
||||
return size + 'px';
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@font-face {
|
||||
font-family: UniIconsFontFamily;
|
||||
src: url('./uniicons.ttf');
|
||||
}
|
||||
|
||||
.uni-icons {
|
||||
font-family: UniIconsFontFamily;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
110
uni_modules/uni-icons/components/uni-icons/uni-icons.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
|
||||
<slot></slot>
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fontData } from './uniicons_file_vue.js';
|
||||
|
||||
const getVal = (val) => {
|
||||
const reg = /^[0-9]*$/g
|
||||
return (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;
|
||||
}
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
var domModule = weex.requireModule('dom');
|
||||
import iconUrl from './uniicons.ttf'
|
||||
domModule.addRule('fontFace', {
|
||||
'fontFamily': "uniicons",
|
||||
'src': "url('" + iconUrl + "')"
|
||||
});
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* Icons 图标
|
||||
* @description 用于展示 icons 图标
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
|
||||
* @property {Number} size 图标大小
|
||||
* @property {String} type 图标图案,参考示例
|
||||
* @property {String} color 图标颜色
|
||||
* @property {String} customPrefix 自定义图标
|
||||
* @event {Function} click 点击 Icon 触发事件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniIcons',
|
||||
emits: ['click'],
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333333'
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 16
|
||||
},
|
||||
customPrefix: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
icons: fontData
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
unicode() {
|
||||
let code = this.icons.find(v => v.font_class === this.type)
|
||||
if (code) {
|
||||
return code.unicode
|
||||
}
|
||||
return ''
|
||||
},
|
||||
iconSize() {
|
||||
return getVal(this.size)
|
||||
},
|
||||
styleObj() {
|
||||
if (this.fontFamily !== '') {
|
||||
return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
|
||||
}
|
||||
return `color: ${this.color}; font-size: ${this.iconSize};`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* #ifndef APP-NVUE */
|
||||
@import './uniicons.css';
|
||||
|
||||
@font-face {
|
||||
font-family: uniicons;
|
||||
src: url('./uniicons.ttf');
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.uni-icons {
|
||||
font-family: uniicons;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
664
uni_modules/uni-icons/components/uni-icons/uniicons.css
Normal file
@@ -0,0 +1,664 @@
|
||||
|
||||
.uniui-cart-filled:before {
|
||||
content: "\e6d0";
|
||||
}
|
||||
|
||||
.uniui-gift-filled:before {
|
||||
content: "\e6c4";
|
||||
}
|
||||
|
||||
.uniui-color:before {
|
||||
content: "\e6cf";
|
||||
}
|
||||
|
||||
.uniui-wallet:before {
|
||||
content: "\e6b1";
|
||||
}
|
||||
|
||||
.uniui-settings-filled:before {
|
||||
content: "\e6ce";
|
||||
}
|
||||
|
||||
.uniui-auth-filled:before {
|
||||
content: "\e6cc";
|
||||
}
|
||||
|
||||
.uniui-shop-filled:before {
|
||||
content: "\e6cd";
|
||||
}
|
||||
|
||||
.uniui-staff-filled:before {
|
||||
content: "\e6cb";
|
||||
}
|
||||
|
||||
.uniui-vip-filled:before {
|
||||
content: "\e6c6";
|
||||
}
|
||||
|
||||
.uniui-plus-filled:before {
|
||||
content: "\e6c7";
|
||||
}
|
||||
|
||||
.uniui-folder-add-filled:before {
|
||||
content: "\e6c8";
|
||||
}
|
||||
|
||||
.uniui-color-filled:before {
|
||||
content: "\e6c9";
|
||||
}
|
||||
|
||||
.uniui-tune-filled:before {
|
||||
content: "\e6ca";
|
||||
}
|
||||
|
||||
.uniui-calendar-filled:before {
|
||||
content: "\e6c0";
|
||||
}
|
||||
|
||||
.uniui-notification-filled:before {
|
||||
content: "\e6c1";
|
||||
}
|
||||
|
||||
.uniui-wallet-filled:before {
|
||||
content: "\e6c2";
|
||||
}
|
||||
|
||||
.uniui-medal-filled:before {
|
||||
content: "\e6c3";
|
||||
}
|
||||
|
||||
.uniui-fire-filled:before {
|
||||
content: "\e6c5";
|
||||
}
|
||||
|
||||
.uniui-refreshempty:before {
|
||||
content: "\e6bf";
|
||||
}
|
||||
|
||||
.uniui-location-filled:before {
|
||||
content: "\e6af";
|
||||
}
|
||||
|
||||
.uniui-person-filled:before {
|
||||
content: "\e69d";
|
||||
}
|
||||
|
||||
.uniui-personadd-filled:before {
|
||||
content: "\e698";
|
||||
}
|
||||
|
||||
.uniui-arrowthinleft:before {
|
||||
content: "\e6d2";
|
||||
}
|
||||
|
||||
.uniui-arrowthinup:before {
|
||||
content: "\e6d3";
|
||||
}
|
||||
|
||||
.uniui-arrowthindown:before {
|
||||
content: "\e6d4";
|
||||
}
|
||||
|
||||
.uniui-back:before {
|
||||
content: "\e6b9";
|
||||
}
|
||||
|
||||
.uniui-forward:before {
|
||||
content: "\e6ba";
|
||||
}
|
||||
|
||||
.uniui-arrow-right:before {
|
||||
content: "\e6bb";
|
||||
}
|
||||
|
||||
.uniui-arrow-left:before {
|
||||
content: "\e6bc";
|
||||
}
|
||||
|
||||
.uniui-arrow-up:before {
|
||||
content: "\e6bd";
|
||||
}
|
||||
|
||||
.uniui-arrow-down:before {
|
||||
content: "\e6be";
|
||||
}
|
||||
|
||||
.uniui-arrowthinright:before {
|
||||
content: "\e6d1";
|
||||
}
|
||||
|
||||
.uniui-down:before {
|
||||
content: "\e6b8";
|
||||
}
|
||||
|
||||
.uniui-bottom:before {
|
||||
content: "\e6b8";
|
||||
}
|
||||
|
||||
.uniui-arrowright:before {
|
||||
content: "\e6d5";
|
||||
}
|
||||
|
||||
.uniui-right:before {
|
||||
content: "\e6b5";
|
||||
}
|
||||
|
||||
.uniui-up:before {
|
||||
content: "\e6b6";
|
||||
}
|
||||
|
||||
.uniui-top:before {
|
||||
content: "\e6b6";
|
||||
}
|
||||
|
||||
.uniui-left:before {
|
||||
content: "\e6b7";
|
||||
}
|
||||
|
||||
.uniui-arrowup:before {
|
||||
content: "\e6d6";
|
||||
}
|
||||
|
||||
.uniui-eye:before {
|
||||
content: "\e651";
|
||||
}
|
||||
|
||||
.uniui-eye-filled:before {
|
||||
content: "\e66a";
|
||||
}
|
||||
|
||||
.uniui-eye-slash:before {
|
||||
content: "\e6b3";
|
||||
}
|
||||
|
||||
.uniui-eye-slash-filled:before {
|
||||
content: "\e6b4";
|
||||
}
|
||||
|
||||
.uniui-info-filled:before {
|
||||
content: "\e649";
|
||||
}
|
||||
|
||||
.uniui-reload:before {
|
||||
content: "\e6b2";
|
||||
}
|
||||
|
||||
.uniui-micoff-filled:before {
|
||||
content: "\e6b0";
|
||||
}
|
||||
|
||||
.uniui-map-pin-ellipse:before {
|
||||
content: "\e6ac";
|
||||
}
|
||||
|
||||
.uniui-map-pin:before {
|
||||
content: "\e6ad";
|
||||
}
|
||||
|
||||
.uniui-location:before {
|
||||
content: "\e6ae";
|
||||
}
|
||||
|
||||
.uniui-starhalf:before {
|
||||
content: "\e683";
|
||||
}
|
||||
|
||||
.uniui-star:before {
|
||||
content: "\e688";
|
||||
}
|
||||
|
||||
.uniui-star-filled:before {
|
||||
content: "\e68f";
|
||||
}
|
||||
|
||||
.uniui-calendar:before {
|
||||
content: "\e6a0";
|
||||
}
|
||||
|
||||
.uniui-fire:before {
|
||||
content: "\e6a1";
|
||||
}
|
||||
|
||||
.uniui-medal:before {
|
||||
content: "\e6a2";
|
||||
}
|
||||
|
||||
.uniui-font:before {
|
||||
content: "\e6a3";
|
||||
}
|
||||
|
||||
.uniui-gift:before {
|
||||
content: "\e6a4";
|
||||
}
|
||||
|
||||
.uniui-link:before {
|
||||
content: "\e6a5";
|
||||
}
|
||||
|
||||
.uniui-notification:before {
|
||||
content: "\e6a6";
|
||||
}
|
||||
|
||||
.uniui-staff:before {
|
||||
content: "\e6a7";
|
||||
}
|
||||
|
||||
.uniui-vip:before {
|
||||
content: "\e6a8";
|
||||
}
|
||||
|
||||
.uniui-folder-add:before {
|
||||
content: "\e6a9";
|
||||
}
|
||||
|
||||
.uniui-tune:before {
|
||||
content: "\e6aa";
|
||||
}
|
||||
|
||||
.uniui-auth:before {
|
||||
content: "\e6ab";
|
||||
}
|
||||
|
||||
.uniui-person:before {
|
||||
content: "\e699";
|
||||
}
|
||||
|
||||
.uniui-email-filled:before {
|
||||
content: "\e69a";
|
||||
}
|
||||
|
||||
.uniui-phone-filled:before {
|
||||
content: "\e69b";
|
||||
}
|
||||
|
||||
.uniui-phone:before {
|
||||
content: "\e69c";
|
||||
}
|
||||
|
||||
.uniui-email:before {
|
||||
content: "\e69e";
|
||||
}
|
||||
|
||||
.uniui-personadd:before {
|
||||
content: "\e69f";
|
||||
}
|
||||
|
||||
.uniui-chatboxes-filled:before {
|
||||
content: "\e692";
|
||||
}
|
||||
|
||||
.uniui-contact:before {
|
||||
content: "\e693";
|
||||
}
|
||||
|
||||
.uniui-chatbubble-filled:before {
|
||||
content: "\e694";
|
||||
}
|
||||
|
||||
.uniui-contact-filled:before {
|
||||
content: "\e695";
|
||||
}
|
||||
|
||||
.uniui-chatboxes:before {
|
||||
content: "\e696";
|
||||
}
|
||||
|
||||
.uniui-chatbubble:before {
|
||||
content: "\e697";
|
||||
}
|
||||
|
||||
.uniui-upload-filled:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.uniui-upload:before {
|
||||
content: "\e690";
|
||||
}
|
||||
|
||||
.uniui-weixin:before {
|
||||
content: "\e691";
|
||||
}
|
||||
|
||||
.uniui-compose:before {
|
||||
content: "\e67f";
|
||||
}
|
||||
|
||||
.uniui-qq:before {
|
||||
content: "\e680";
|
||||
}
|
||||
|
||||
.uniui-download-filled:before {
|
||||
content: "\e681";
|
||||
}
|
||||
|
||||
.uniui-pyq:before {
|
||||
content: "\e682";
|
||||
}
|
||||
|
||||
.uniui-sound:before {
|
||||
content: "\e684";
|
||||
}
|
||||
|
||||
.uniui-trash-filled:before {
|
||||
content: "\e685";
|
||||
}
|
||||
|
||||
.uniui-sound-filled:before {
|
||||
content: "\e686";
|
||||
}
|
||||
|
||||
.uniui-trash:before {
|
||||
content: "\e687";
|
||||
}
|
||||
|
||||
.uniui-videocam-filled:before {
|
||||
content: "\e689";
|
||||
}
|
||||
|
||||
.uniui-spinner-cycle:before {
|
||||
content: "\e68a";
|
||||
}
|
||||
|
||||
.uniui-weibo:before {
|
||||
content: "\e68b";
|
||||
}
|
||||
|
||||
.uniui-videocam:before {
|
||||
content: "\e68c";
|
||||
}
|
||||
|
||||
.uniui-download:before {
|
||||
content: "\e68d";
|
||||
}
|
||||
|
||||
.uniui-help:before {
|
||||
content: "\e679";
|
||||
}
|
||||
|
||||
.uniui-navigate-filled:before {
|
||||
content: "\e67a";
|
||||
}
|
||||
|
||||
.uniui-plusempty:before {
|
||||
content: "\e67b";
|
||||
}
|
||||
|
||||
.uniui-smallcircle:before {
|
||||
content: "\e67c";
|
||||
}
|
||||
|
||||
.uniui-minus-filled:before {
|
||||
content: "\e67d";
|
||||
}
|
||||
|
||||
.uniui-micoff:before {
|
||||
content: "\e67e";
|
||||
}
|
||||
|
||||
.uniui-closeempty:before {
|
||||
content: "\e66c";
|
||||
}
|
||||
|
||||
.uniui-clear:before {
|
||||
content: "\e66d";
|
||||
}
|
||||
|
||||
.uniui-navigate:before {
|
||||
content: "\e66e";
|
||||
}
|
||||
|
||||
.uniui-minus:before {
|
||||
content: "\e66f";
|
||||
}
|
||||
|
||||
.uniui-image:before {
|
||||
content: "\e670";
|
||||
}
|
||||
|
||||
.uniui-mic:before {
|
||||
content: "\e671";
|
||||
}
|
||||
|
||||
.uniui-paperplane:before {
|
||||
content: "\e672";
|
||||
}
|
||||
|
||||
.uniui-close:before {
|
||||
content: "\e673";
|
||||
}
|
||||
|
||||
.uniui-help-filled:before {
|
||||
content: "\e674";
|
||||
}
|
||||
|
||||
.uniui-paperplane-filled:before {
|
||||
content: "\e675";
|
||||
}
|
||||
|
||||
.uniui-plus:before {
|
||||
content: "\e676";
|
||||
}
|
||||
|
||||
.uniui-mic-filled:before {
|
||||
content: "\e677";
|
||||
}
|
||||
|
||||
.uniui-image-filled:before {
|
||||
content: "\e678";
|
||||
}
|
||||
|
||||
.uniui-locked-filled:before {
|
||||
content: "\e668";
|
||||
}
|
||||
|
||||
.uniui-info:before {
|
||||
content: "\e669";
|
||||
}
|
||||
|
||||
.uniui-locked:before {
|
||||
content: "\e66b";
|
||||
}
|
||||
|
||||
.uniui-camera-filled:before {
|
||||
content: "\e658";
|
||||
}
|
||||
|
||||
.uniui-chat-filled:before {
|
||||
content: "\e659";
|
||||
}
|
||||
|
||||
.uniui-camera:before {
|
||||
content: "\e65a";
|
||||
}
|
||||
|
||||
.uniui-circle:before {
|
||||
content: "\e65b";
|
||||
}
|
||||
|
||||
.uniui-checkmarkempty:before {
|
||||
content: "\e65c";
|
||||
}
|
||||
|
||||
.uniui-chat:before {
|
||||
content: "\e65d";
|
||||
}
|
||||
|
||||
.uniui-circle-filled:before {
|
||||
content: "\e65e";
|
||||
}
|
||||
|
||||
.uniui-flag:before {
|
||||
content: "\e65f";
|
||||
}
|
||||
|
||||
.uniui-flag-filled:before {
|
||||
content: "\e660";
|
||||
}
|
||||
|
||||
.uniui-gear-filled:before {
|
||||
content: "\e661";
|
||||
}
|
||||
|
||||
.uniui-home:before {
|
||||
content: "\e662";
|
||||
}
|
||||
|
||||
.uniui-home-filled:before {
|
||||
content: "\e663";
|
||||
}
|
||||
|
||||
.uniui-gear:before {
|
||||
content: "\e664";
|
||||
}
|
||||
|
||||
.uniui-smallcircle-filled:before {
|
||||
content: "\e665";
|
||||
}
|
||||
|
||||
.uniui-map-filled:before {
|
||||
content: "\e666";
|
||||
}
|
||||
|
||||
.uniui-map:before {
|
||||
content: "\e667";
|
||||
}
|
||||
|
||||
.uniui-refresh-filled:before {
|
||||
content: "\e656";
|
||||
}
|
||||
|
||||
.uniui-refresh:before {
|
||||
content: "\e657";
|
||||
}
|
||||
|
||||
.uniui-cloud-upload:before {
|
||||
content: "\e645";
|
||||
}
|
||||
|
||||
.uniui-cloud-download-filled:before {
|
||||
content: "\e646";
|
||||
}
|
||||
|
||||
.uniui-cloud-download:before {
|
||||
content: "\e647";
|
||||
}
|
||||
|
||||
.uniui-cloud-upload-filled:before {
|
||||
content: "\e648";
|
||||
}
|
||||
|
||||
.uniui-redo:before {
|
||||
content: "\e64a";
|
||||
}
|
||||
|
||||
.uniui-images-filled:before {
|
||||
content: "\e64b";
|
||||
}
|
||||
|
||||
.uniui-undo-filled:before {
|
||||
content: "\e64c";
|
||||
}
|
||||
|
||||
.uniui-more:before {
|
||||
content: "\e64d";
|
||||
}
|
||||
|
||||
.uniui-more-filled:before {
|
||||
content: "\e64e";
|
||||
}
|
||||
|
||||
.uniui-undo:before {
|
||||
content: "\e64f";
|
||||
}
|
||||
|
||||
.uniui-images:before {
|
||||
content: "\e650";
|
||||
}
|
||||
|
||||
.uniui-paperclip:before {
|
||||
content: "\e652";
|
||||
}
|
||||
|
||||
.uniui-settings:before {
|
||||
content: "\e653";
|
||||
}
|
||||
|
||||
.uniui-search:before {
|
||||
content: "\e654";
|
||||
}
|
||||
|
||||
.uniui-redo-filled:before {
|
||||
content: "\e655";
|
||||
}
|
||||
|
||||
.uniui-list:before {
|
||||
content: "\e644";
|
||||
}
|
||||
|
||||
.uniui-mail-open-filled:before {
|
||||
content: "\e63a";
|
||||
}
|
||||
|
||||
.uniui-hand-down-filled:before {
|
||||
content: "\e63c";
|
||||
}
|
||||
|
||||
.uniui-hand-down:before {
|
||||
content: "\e63d";
|
||||
}
|
||||
|
||||
.uniui-hand-up-filled:before {
|
||||
content: "\e63e";
|
||||
}
|
||||
|
||||
.uniui-hand-up:before {
|
||||
content: "\e63f";
|
||||
}
|
||||
|
||||
.uniui-heart-filled:before {
|
||||
content: "\e641";
|
||||
}
|
||||
|
||||
.uniui-mail-open:before {
|
||||
content: "\e643";
|
||||
}
|
||||
|
||||
.uniui-heart:before {
|
||||
content: "\e639";
|
||||
}
|
||||
|
||||
.uniui-loop:before {
|
||||
content: "\e633";
|
||||
}
|
||||
|
||||
.uniui-pulldown:before {
|
||||
content: "\e632";
|
||||
}
|
||||
|
||||
.uniui-scan:before {
|
||||
content: "\e62a";
|
||||
}
|
||||
|
||||
.uniui-bars:before {
|
||||
content: "\e627";
|
||||
}
|
||||
|
||||
.uniui-checkbox:before {
|
||||
content: "\e62b";
|
||||
}
|
||||
|
||||
.uniui-checkbox-filled:before {
|
||||
content: "\e62c";
|
||||
}
|
||||
|
||||
.uniui-shop:before {
|
||||
content: "\e62f";
|
||||
}
|
||||
|
||||
.uniui-headphones:before {
|
||||
content: "\e630";
|
||||
}
|
||||
|
||||
.uniui-cart:before {
|
||||
content: "\e631";
|
||||
}
|
||||
BIN
uni_modules/uni-icons/components/uni-icons/uniicons.ttf
Normal file
664
uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
Normal file
@@ -0,0 +1,664 @@
|
||||
|
||||
export type IconsData = {
|
||||
id : string
|
||||
name : string
|
||||
font_family : string
|
||||
css_prefix_text : string
|
||||
description : string
|
||||
glyphs : Array<IconsDataItem>
|
||||
}
|
||||
|
||||
export type IconsDataItem = {
|
||||
font_class : string
|
||||
unicode : string
|
||||
}
|
||||
|
||||
|
||||
export const fontData = [
|
||||
{
|
||||
"font_class": "arrow-down",
|
||||
"unicode": "\ue6be"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-left",
|
||||
"unicode": "\ue6bc"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-right",
|
||||
"unicode": "\ue6bb"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-up",
|
||||
"unicode": "\ue6bd"
|
||||
},
|
||||
{
|
||||
"font_class": "auth",
|
||||
"unicode": "\ue6ab"
|
||||
},
|
||||
{
|
||||
"font_class": "auth-filled",
|
||||
"unicode": "\ue6cc"
|
||||
},
|
||||
{
|
||||
"font_class": "back",
|
||||
"unicode": "\ue6b9"
|
||||
},
|
||||
{
|
||||
"font_class": "bars",
|
||||
"unicode": "\ue627"
|
||||
},
|
||||
{
|
||||
"font_class": "calendar",
|
||||
"unicode": "\ue6a0"
|
||||
},
|
||||
{
|
||||
"font_class": "calendar-filled",
|
||||
"unicode": "\ue6c0"
|
||||
},
|
||||
{
|
||||
"font_class": "camera",
|
||||
"unicode": "\ue65a"
|
||||
},
|
||||
{
|
||||
"font_class": "camera-filled",
|
||||
"unicode": "\ue658"
|
||||
},
|
||||
{
|
||||
"font_class": "cart",
|
||||
"unicode": "\ue631"
|
||||
},
|
||||
{
|
||||
"font_class": "cart-filled",
|
||||
"unicode": "\ue6d0"
|
||||
},
|
||||
{
|
||||
"font_class": "chat",
|
||||
"unicode": "\ue65d"
|
||||
},
|
||||
{
|
||||
"font_class": "chat-filled",
|
||||
"unicode": "\ue659"
|
||||
},
|
||||
{
|
||||
"font_class": "chatboxes",
|
||||
"unicode": "\ue696"
|
||||
},
|
||||
{
|
||||
"font_class": "chatboxes-filled",
|
||||
"unicode": "\ue692"
|
||||
},
|
||||
{
|
||||
"font_class": "chatbubble",
|
||||
"unicode": "\ue697"
|
||||
},
|
||||
{
|
||||
"font_class": "chatbubble-filled",
|
||||
"unicode": "\ue694"
|
||||
},
|
||||
{
|
||||
"font_class": "checkbox",
|
||||
"unicode": "\ue62b"
|
||||
},
|
||||
{
|
||||
"font_class": "checkbox-filled",
|
||||
"unicode": "\ue62c"
|
||||
},
|
||||
{
|
||||
"font_class": "checkmarkempty",
|
||||
"unicode": "\ue65c"
|
||||
},
|
||||
{
|
||||
"font_class": "circle",
|
||||
"unicode": "\ue65b"
|
||||
},
|
||||
{
|
||||
"font_class": "circle-filled",
|
||||
"unicode": "\ue65e"
|
||||
},
|
||||
{
|
||||
"font_class": "clear",
|
||||
"unicode": "\ue66d"
|
||||
},
|
||||
{
|
||||
"font_class": "close",
|
||||
"unicode": "\ue673"
|
||||
},
|
||||
{
|
||||
"font_class": "closeempty",
|
||||
"unicode": "\ue66c"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-download",
|
||||
"unicode": "\ue647"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-download-filled",
|
||||
"unicode": "\ue646"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-upload",
|
||||
"unicode": "\ue645"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-upload-filled",
|
||||
"unicode": "\ue648"
|
||||
},
|
||||
{
|
||||
"font_class": "color",
|
||||
"unicode": "\ue6cf"
|
||||
},
|
||||
{
|
||||
"font_class": "color-filled",
|
||||
"unicode": "\ue6c9"
|
||||
},
|
||||
{
|
||||
"font_class": "compose",
|
||||
"unicode": "\ue67f"
|
||||
},
|
||||
{
|
||||
"font_class": "contact",
|
||||
"unicode": "\ue693"
|
||||
},
|
||||
{
|
||||
"font_class": "contact-filled",
|
||||
"unicode": "\ue695"
|
||||
},
|
||||
{
|
||||
"font_class": "down",
|
||||
"unicode": "\ue6b8"
|
||||
},
|
||||
{
|
||||
"font_class": "bottom",
|
||||
"unicode": "\ue6b8"
|
||||
},
|
||||
{
|
||||
"font_class": "download",
|
||||
"unicode": "\ue68d"
|
||||
},
|
||||
{
|
||||
"font_class": "download-filled",
|
||||
"unicode": "\ue681"
|
||||
},
|
||||
{
|
||||
"font_class": "email",
|
||||
"unicode": "\ue69e"
|
||||
},
|
||||
{
|
||||
"font_class": "email-filled",
|
||||
"unicode": "\ue69a"
|
||||
},
|
||||
{
|
||||
"font_class": "eye",
|
||||
"unicode": "\ue651"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-filled",
|
||||
"unicode": "\ue66a"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-slash",
|
||||
"unicode": "\ue6b3"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-slash-filled",
|
||||
"unicode": "\ue6b4"
|
||||
},
|
||||
{
|
||||
"font_class": "fire",
|
||||
"unicode": "\ue6a1"
|
||||
},
|
||||
{
|
||||
"font_class": "fire-filled",
|
||||
"unicode": "\ue6c5"
|
||||
},
|
||||
{
|
||||
"font_class": "flag",
|
||||
"unicode": "\ue65f"
|
||||
},
|
||||
{
|
||||
"font_class": "flag-filled",
|
||||
"unicode": "\ue660"
|
||||
},
|
||||
{
|
||||
"font_class": "folder-add",
|
||||
"unicode": "\ue6a9"
|
||||
},
|
||||
{
|
||||
"font_class": "folder-add-filled",
|
||||
"unicode": "\ue6c8"
|
||||
},
|
||||
{
|
||||
"font_class": "font",
|
||||
"unicode": "\ue6a3"
|
||||
},
|
||||
{
|
||||
"font_class": "forward",
|
||||
"unicode": "\ue6ba"
|
||||
},
|
||||
{
|
||||
"font_class": "gear",
|
||||
"unicode": "\ue664"
|
||||
},
|
||||
{
|
||||
"font_class": "gear-filled",
|
||||
"unicode": "\ue661"
|
||||
},
|
||||
{
|
||||
"font_class": "gift",
|
||||
"unicode": "\ue6a4"
|
||||
},
|
||||
{
|
||||
"font_class": "gift-filled",
|
||||
"unicode": "\ue6c4"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-down",
|
||||
"unicode": "\ue63d"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-down-filled",
|
||||
"unicode": "\ue63c"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-up",
|
||||
"unicode": "\ue63f"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-up-filled",
|
||||
"unicode": "\ue63e"
|
||||
},
|
||||
{
|
||||
"font_class": "headphones",
|
||||
"unicode": "\ue630"
|
||||
},
|
||||
{
|
||||
"font_class": "heart",
|
||||
"unicode": "\ue639"
|
||||
},
|
||||
{
|
||||
"font_class": "heart-filled",
|
||||
"unicode": "\ue641"
|
||||
},
|
||||
{
|
||||
"font_class": "help",
|
||||
"unicode": "\ue679"
|
||||
},
|
||||
{
|
||||
"font_class": "help-filled",
|
||||
"unicode": "\ue674"
|
||||
},
|
||||
{
|
||||
"font_class": "home",
|
||||
"unicode": "\ue662"
|
||||
},
|
||||
{
|
||||
"font_class": "home-filled",
|
||||
"unicode": "\ue663"
|
||||
},
|
||||
{
|
||||
"font_class": "image",
|
||||
"unicode": "\ue670"
|
||||
},
|
||||
{
|
||||
"font_class": "image-filled",
|
||||
"unicode": "\ue678"
|
||||
},
|
||||
{
|
||||
"font_class": "images",
|
||||
"unicode": "\ue650"
|
||||
},
|
||||
{
|
||||
"font_class": "images-filled",
|
||||
"unicode": "\ue64b"
|
||||
},
|
||||
{
|
||||
"font_class": "info",
|
||||
"unicode": "\ue669"
|
||||
},
|
||||
{
|
||||
"font_class": "info-filled",
|
||||
"unicode": "\ue649"
|
||||
},
|
||||
{
|
||||
"font_class": "left",
|
||||
"unicode": "\ue6b7"
|
||||
},
|
||||
{
|
||||
"font_class": "link",
|
||||
"unicode": "\ue6a5"
|
||||
},
|
||||
{
|
||||
"font_class": "list",
|
||||
"unicode": "\ue644"
|
||||
},
|
||||
{
|
||||
"font_class": "location",
|
||||
"unicode": "\ue6ae"
|
||||
},
|
||||
{
|
||||
"font_class": "location-filled",
|
||||
"unicode": "\ue6af"
|
||||
},
|
||||
{
|
||||
"font_class": "locked",
|
||||
"unicode": "\ue66b"
|
||||
},
|
||||
{
|
||||
"font_class": "locked-filled",
|
||||
"unicode": "\ue668"
|
||||
},
|
||||
{
|
||||
"font_class": "loop",
|
||||
"unicode": "\ue633"
|
||||
},
|
||||
{
|
||||
"font_class": "mail-open",
|
||||
"unicode": "\ue643"
|
||||
},
|
||||
{
|
||||
"font_class": "mail-open-filled",
|
||||
"unicode": "\ue63a"
|
||||
},
|
||||
{
|
||||
"font_class": "map",
|
||||
"unicode": "\ue667"
|
||||
},
|
||||
{
|
||||
"font_class": "map-filled",
|
||||
"unicode": "\ue666"
|
||||
},
|
||||
{
|
||||
"font_class": "map-pin",
|
||||
"unicode": "\ue6ad"
|
||||
},
|
||||
{
|
||||
"font_class": "map-pin-ellipse",
|
||||
"unicode": "\ue6ac"
|
||||
},
|
||||
{
|
||||
"font_class": "medal",
|
||||
"unicode": "\ue6a2"
|
||||
},
|
||||
{
|
||||
"font_class": "medal-filled",
|
||||
"unicode": "\ue6c3"
|
||||
},
|
||||
{
|
||||
"font_class": "mic",
|
||||
"unicode": "\ue671"
|
||||
},
|
||||
{
|
||||
"font_class": "mic-filled",
|
||||
"unicode": "\ue677"
|
||||
},
|
||||
{
|
||||
"font_class": "micoff",
|
||||
"unicode": "\ue67e"
|
||||
},
|
||||
{
|
||||
"font_class": "micoff-filled",
|
||||
"unicode": "\ue6b0"
|
||||
},
|
||||
{
|
||||
"font_class": "minus",
|
||||
"unicode": "\ue66f"
|
||||
},
|
||||
{
|
||||
"font_class": "minus-filled",
|
||||
"unicode": "\ue67d"
|
||||
},
|
||||
{
|
||||
"font_class": "more",
|
||||
"unicode": "\ue64d"
|
||||
},
|
||||
{
|
||||
"font_class": "more-filled",
|
||||
"unicode": "\ue64e"
|
||||
},
|
||||
{
|
||||
"font_class": "navigate",
|
||||
"unicode": "\ue66e"
|
||||
},
|
||||
{
|
||||
"font_class": "navigate-filled",
|
||||
"unicode": "\ue67a"
|
||||
},
|
||||
{
|
||||
"font_class": "notification",
|
||||
"unicode": "\ue6a6"
|
||||
},
|
||||
{
|
||||
"font_class": "notification-filled",
|
||||
"unicode": "\ue6c1"
|
||||
},
|
||||
{
|
||||
"font_class": "paperclip",
|
||||
"unicode": "\ue652"
|
||||
},
|
||||
{
|
||||
"font_class": "paperplane",
|
||||
"unicode": "\ue672"
|
||||
},
|
||||
{
|
||||
"font_class": "paperplane-filled",
|
||||
"unicode": "\ue675"
|
||||
},
|
||||
{
|
||||
"font_class": "person",
|
||||
"unicode": "\ue699"
|
||||
},
|
||||
{
|
||||
"font_class": "person-filled",
|
||||
"unicode": "\ue69d"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd",
|
||||
"unicode": "\ue69f"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd-filled",
|
||||
"unicode": "\ue698"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd-filled-copy",
|
||||
"unicode": "\ue6d1"
|
||||
},
|
||||
{
|
||||
"font_class": "phone",
|
||||
"unicode": "\ue69c"
|
||||
},
|
||||
{
|
||||
"font_class": "phone-filled",
|
||||
"unicode": "\ue69b"
|
||||
},
|
||||
{
|
||||
"font_class": "plus",
|
||||
"unicode": "\ue676"
|
||||
},
|
||||
{
|
||||
"font_class": "plus-filled",
|
||||
"unicode": "\ue6c7"
|
||||
},
|
||||
{
|
||||
"font_class": "plusempty",
|
||||
"unicode": "\ue67b"
|
||||
},
|
||||
{
|
||||
"font_class": "pulldown",
|
||||
"unicode": "\ue632"
|
||||
},
|
||||
{
|
||||
"font_class": "pyq",
|
||||
"unicode": "\ue682"
|
||||
},
|
||||
{
|
||||
"font_class": "qq",
|
||||
"unicode": "\ue680"
|
||||
},
|
||||
{
|
||||
"font_class": "redo",
|
||||
"unicode": "\ue64a"
|
||||
},
|
||||
{
|
||||
"font_class": "redo-filled",
|
||||
"unicode": "\ue655"
|
||||
},
|
||||
{
|
||||
"font_class": "refresh",
|
||||
"unicode": "\ue657"
|
||||
},
|
||||
{
|
||||
"font_class": "refresh-filled",
|
||||
"unicode": "\ue656"
|
||||
},
|
||||
{
|
||||
"font_class": "refreshempty",
|
||||
"unicode": "\ue6bf"
|
||||
},
|
||||
{
|
||||
"font_class": "reload",
|
||||
"unicode": "\ue6b2"
|
||||
},
|
||||
{
|
||||
"font_class": "right",
|
||||
"unicode": "\ue6b5"
|
||||
},
|
||||
{
|
||||
"font_class": "scan",
|
||||
"unicode": "\ue62a"
|
||||
},
|
||||
{
|
||||
"font_class": "search",
|
||||
"unicode": "\ue654"
|
||||
},
|
||||
{
|
||||
"font_class": "settings",
|
||||
"unicode": "\ue653"
|
||||
},
|
||||
{
|
||||
"font_class": "settings-filled",
|
||||
"unicode": "\ue6ce"
|
||||
},
|
||||
{
|
||||
"font_class": "shop",
|
||||
"unicode": "\ue62f"
|
||||
},
|
||||
{
|
||||
"font_class": "shop-filled",
|
||||
"unicode": "\ue6cd"
|
||||
},
|
||||
{
|
||||
"font_class": "smallcircle",
|
||||
"unicode": "\ue67c"
|
||||
},
|
||||
{
|
||||
"font_class": "smallcircle-filled",
|
||||
"unicode": "\ue665"
|
||||
},
|
||||
{
|
||||
"font_class": "sound",
|
||||
"unicode": "\ue684"
|
||||
},
|
||||
{
|
||||
"font_class": "sound-filled",
|
||||
"unicode": "\ue686"
|
||||
},
|
||||
{
|
||||
"font_class": "spinner-cycle",
|
||||
"unicode": "\ue68a"
|
||||
},
|
||||
{
|
||||
"font_class": "staff",
|
||||
"unicode": "\ue6a7"
|
||||
},
|
||||
{
|
||||
"font_class": "staff-filled",
|
||||
"unicode": "\ue6cb"
|
||||
},
|
||||
{
|
||||
"font_class": "star",
|
||||
"unicode": "\ue688"
|
||||
},
|
||||
{
|
||||
"font_class": "star-filled",
|
||||
"unicode": "\ue68f"
|
||||
},
|
||||
{
|
||||
"font_class": "starhalf",
|
||||
"unicode": "\ue683"
|
||||
},
|
||||
{
|
||||
"font_class": "trash",
|
||||
"unicode": "\ue687"
|
||||
},
|
||||
{
|
||||
"font_class": "trash-filled",
|
||||
"unicode": "\ue685"
|
||||
},
|
||||
{
|
||||
"font_class": "tune",
|
||||
"unicode": "\ue6aa"
|
||||
},
|
||||
{
|
||||
"font_class": "tune-filled",
|
||||
"unicode": "\ue6ca"
|
||||
},
|
||||
{
|
||||
"font_class": "undo",
|
||||
"unicode": "\ue64f"
|
||||
},
|
||||
{
|
||||
"font_class": "undo-filled",
|
||||
"unicode": "\ue64c"
|
||||
},
|
||||
{
|
||||
"font_class": "up",
|
||||
"unicode": "\ue6b6"
|
||||
},
|
||||
{
|
||||
"font_class": "top",
|
||||
"unicode": "\ue6b6"
|
||||
},
|
||||
{
|
||||
"font_class": "upload",
|
||||
"unicode": "\ue690"
|
||||
},
|
||||
{
|
||||
"font_class": "upload-filled",
|
||||
"unicode": "\ue68e"
|
||||
},
|
||||
{
|
||||
"font_class": "videocam",
|
||||
"unicode": "\ue68c"
|
||||
},
|
||||
{
|
||||
"font_class": "videocam-filled",
|
||||
"unicode": "\ue689"
|
||||
},
|
||||
{
|
||||
"font_class": "vip",
|
||||
"unicode": "\ue6a8"
|
||||
},
|
||||
{
|
||||
"font_class": "vip-filled",
|
||||
"unicode": "\ue6c6"
|
||||
},
|
||||
{
|
||||
"font_class": "wallet",
|
||||
"unicode": "\ue6b1"
|
||||
},
|
||||
{
|
||||
"font_class": "wallet-filled",
|
||||
"unicode": "\ue6c2"
|
||||
},
|
||||
{
|
||||
"font_class": "weibo",
|
||||
"unicode": "\ue68b"
|
||||
},
|
||||
{
|
||||
"font_class": "weixin",
|
||||
"unicode": "\ue691"
|
||||
}
|
||||
] as IconsDataItem[]
|
||||
|
||||
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
|
||||
649
uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
Normal file
@@ -0,0 +1,649 @@
|
||||
|
||||
export const fontData = [
|
||||
{
|
||||
"font_class": "arrow-down",
|
||||
"unicode": "\ue6be"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-left",
|
||||
"unicode": "\ue6bc"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-right",
|
||||
"unicode": "\ue6bb"
|
||||
},
|
||||
{
|
||||
"font_class": "arrow-up",
|
||||
"unicode": "\ue6bd"
|
||||
},
|
||||
{
|
||||
"font_class": "auth",
|
||||
"unicode": "\ue6ab"
|
||||
},
|
||||
{
|
||||
"font_class": "auth-filled",
|
||||
"unicode": "\ue6cc"
|
||||
},
|
||||
{
|
||||
"font_class": "back",
|
||||
"unicode": "\ue6b9"
|
||||
},
|
||||
{
|
||||
"font_class": "bars",
|
||||
"unicode": "\ue627"
|
||||
},
|
||||
{
|
||||
"font_class": "calendar",
|
||||
"unicode": "\ue6a0"
|
||||
},
|
||||
{
|
||||
"font_class": "calendar-filled",
|
||||
"unicode": "\ue6c0"
|
||||
},
|
||||
{
|
||||
"font_class": "camera",
|
||||
"unicode": "\ue65a"
|
||||
},
|
||||
{
|
||||
"font_class": "camera-filled",
|
||||
"unicode": "\ue658"
|
||||
},
|
||||
{
|
||||
"font_class": "cart",
|
||||
"unicode": "\ue631"
|
||||
},
|
||||
{
|
||||
"font_class": "cart-filled",
|
||||
"unicode": "\ue6d0"
|
||||
},
|
||||
{
|
||||
"font_class": "chat",
|
||||
"unicode": "\ue65d"
|
||||
},
|
||||
{
|
||||
"font_class": "chat-filled",
|
||||
"unicode": "\ue659"
|
||||
},
|
||||
{
|
||||
"font_class": "chatboxes",
|
||||
"unicode": "\ue696"
|
||||
},
|
||||
{
|
||||
"font_class": "chatboxes-filled",
|
||||
"unicode": "\ue692"
|
||||
},
|
||||
{
|
||||
"font_class": "chatbubble",
|
||||
"unicode": "\ue697"
|
||||
},
|
||||
{
|
||||
"font_class": "chatbubble-filled",
|
||||
"unicode": "\ue694"
|
||||
},
|
||||
{
|
||||
"font_class": "checkbox",
|
||||
"unicode": "\ue62b"
|
||||
},
|
||||
{
|
||||
"font_class": "checkbox-filled",
|
||||
"unicode": "\ue62c"
|
||||
},
|
||||
{
|
||||
"font_class": "checkmarkempty",
|
||||
"unicode": "\ue65c"
|
||||
},
|
||||
{
|
||||
"font_class": "circle",
|
||||
"unicode": "\ue65b"
|
||||
},
|
||||
{
|
||||
"font_class": "circle-filled",
|
||||
"unicode": "\ue65e"
|
||||
},
|
||||
{
|
||||
"font_class": "clear",
|
||||
"unicode": "\ue66d"
|
||||
},
|
||||
{
|
||||
"font_class": "close",
|
||||
"unicode": "\ue673"
|
||||
},
|
||||
{
|
||||
"font_class": "closeempty",
|
||||
"unicode": "\ue66c"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-download",
|
||||
"unicode": "\ue647"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-download-filled",
|
||||
"unicode": "\ue646"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-upload",
|
||||
"unicode": "\ue645"
|
||||
},
|
||||
{
|
||||
"font_class": "cloud-upload-filled",
|
||||
"unicode": "\ue648"
|
||||
},
|
||||
{
|
||||
"font_class": "color",
|
||||
"unicode": "\ue6cf"
|
||||
},
|
||||
{
|
||||
"font_class": "color-filled",
|
||||
"unicode": "\ue6c9"
|
||||
},
|
||||
{
|
||||
"font_class": "compose",
|
||||
"unicode": "\ue67f"
|
||||
},
|
||||
{
|
||||
"font_class": "contact",
|
||||
"unicode": "\ue693"
|
||||
},
|
||||
{
|
||||
"font_class": "contact-filled",
|
||||
"unicode": "\ue695"
|
||||
},
|
||||
{
|
||||
"font_class": "down",
|
||||
"unicode": "\ue6b8"
|
||||
},
|
||||
{
|
||||
"font_class": "bottom",
|
||||
"unicode": "\ue6b8"
|
||||
},
|
||||
{
|
||||
"font_class": "download",
|
||||
"unicode": "\ue68d"
|
||||
},
|
||||
{
|
||||
"font_class": "download-filled",
|
||||
"unicode": "\ue681"
|
||||
},
|
||||
{
|
||||
"font_class": "email",
|
||||
"unicode": "\ue69e"
|
||||
},
|
||||
{
|
||||
"font_class": "email-filled",
|
||||
"unicode": "\ue69a"
|
||||
},
|
||||
{
|
||||
"font_class": "eye",
|
||||
"unicode": "\ue651"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-filled",
|
||||
"unicode": "\ue66a"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-slash",
|
||||
"unicode": "\ue6b3"
|
||||
},
|
||||
{
|
||||
"font_class": "eye-slash-filled",
|
||||
"unicode": "\ue6b4"
|
||||
},
|
||||
{
|
||||
"font_class": "fire",
|
||||
"unicode": "\ue6a1"
|
||||
},
|
||||
{
|
||||
"font_class": "fire-filled",
|
||||
"unicode": "\ue6c5"
|
||||
},
|
||||
{
|
||||
"font_class": "flag",
|
||||
"unicode": "\ue65f"
|
||||
},
|
||||
{
|
||||
"font_class": "flag-filled",
|
||||
"unicode": "\ue660"
|
||||
},
|
||||
{
|
||||
"font_class": "folder-add",
|
||||
"unicode": "\ue6a9"
|
||||
},
|
||||
{
|
||||
"font_class": "folder-add-filled",
|
||||
"unicode": "\ue6c8"
|
||||
},
|
||||
{
|
||||
"font_class": "font",
|
||||
"unicode": "\ue6a3"
|
||||
},
|
||||
{
|
||||
"font_class": "forward",
|
||||
"unicode": "\ue6ba"
|
||||
},
|
||||
{
|
||||
"font_class": "gear",
|
||||
"unicode": "\ue664"
|
||||
},
|
||||
{
|
||||
"font_class": "gear-filled",
|
||||
"unicode": "\ue661"
|
||||
},
|
||||
{
|
||||
"font_class": "gift",
|
||||
"unicode": "\ue6a4"
|
||||
},
|
||||
{
|
||||
"font_class": "gift-filled",
|
||||
"unicode": "\ue6c4"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-down",
|
||||
"unicode": "\ue63d"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-down-filled",
|
||||
"unicode": "\ue63c"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-up",
|
||||
"unicode": "\ue63f"
|
||||
},
|
||||
{
|
||||
"font_class": "hand-up-filled",
|
||||
"unicode": "\ue63e"
|
||||
},
|
||||
{
|
||||
"font_class": "headphones",
|
||||
"unicode": "\ue630"
|
||||
},
|
||||
{
|
||||
"font_class": "heart",
|
||||
"unicode": "\ue639"
|
||||
},
|
||||
{
|
||||
"font_class": "heart-filled",
|
||||
"unicode": "\ue641"
|
||||
},
|
||||
{
|
||||
"font_class": "help",
|
||||
"unicode": "\ue679"
|
||||
},
|
||||
{
|
||||
"font_class": "help-filled",
|
||||
"unicode": "\ue674"
|
||||
},
|
||||
{
|
||||
"font_class": "home",
|
||||
"unicode": "\ue662"
|
||||
},
|
||||
{
|
||||
"font_class": "home-filled",
|
||||
"unicode": "\ue663"
|
||||
},
|
||||
{
|
||||
"font_class": "image",
|
||||
"unicode": "\ue670"
|
||||
},
|
||||
{
|
||||
"font_class": "image-filled",
|
||||
"unicode": "\ue678"
|
||||
},
|
||||
{
|
||||
"font_class": "images",
|
||||
"unicode": "\ue650"
|
||||
},
|
||||
{
|
||||
"font_class": "images-filled",
|
||||
"unicode": "\ue64b"
|
||||
},
|
||||
{
|
||||
"font_class": "info",
|
||||
"unicode": "\ue669"
|
||||
},
|
||||
{
|
||||
"font_class": "info-filled",
|
||||
"unicode": "\ue649"
|
||||
},
|
||||
{
|
||||
"font_class": "left",
|
||||
"unicode": "\ue6b7"
|
||||
},
|
||||
{
|
||||
"font_class": "link",
|
||||
"unicode": "\ue6a5"
|
||||
},
|
||||
{
|
||||
"font_class": "list",
|
||||
"unicode": "\ue644"
|
||||
},
|
||||
{
|
||||
"font_class": "location",
|
||||
"unicode": "\ue6ae"
|
||||
},
|
||||
{
|
||||
"font_class": "location-filled",
|
||||
"unicode": "\ue6af"
|
||||
},
|
||||
{
|
||||
"font_class": "locked",
|
||||
"unicode": "\ue66b"
|
||||
},
|
||||
{
|
||||
"font_class": "locked-filled",
|
||||
"unicode": "\ue668"
|
||||
},
|
||||
{
|
||||
"font_class": "loop",
|
||||
"unicode": "\ue633"
|
||||
},
|
||||
{
|
||||
"font_class": "mail-open",
|
||||
"unicode": "\ue643"
|
||||
},
|
||||
{
|
||||
"font_class": "mail-open-filled",
|
||||
"unicode": "\ue63a"
|
||||
},
|
||||
{
|
||||
"font_class": "map",
|
||||
"unicode": "\ue667"
|
||||
},
|
||||
{
|
||||
"font_class": "map-filled",
|
||||
"unicode": "\ue666"
|
||||
},
|
||||
{
|
||||
"font_class": "map-pin",
|
||||
"unicode": "\ue6ad"
|
||||
},
|
||||
{
|
||||
"font_class": "map-pin-ellipse",
|
||||
"unicode": "\ue6ac"
|
||||
},
|
||||
{
|
||||
"font_class": "medal",
|
||||
"unicode": "\ue6a2"
|
||||
},
|
||||
{
|
||||
"font_class": "medal-filled",
|
||||
"unicode": "\ue6c3"
|
||||
},
|
||||
{
|
||||
"font_class": "mic",
|
||||
"unicode": "\ue671"
|
||||
},
|
||||
{
|
||||
"font_class": "mic-filled",
|
||||
"unicode": "\ue677"
|
||||
},
|
||||
{
|
||||
"font_class": "micoff",
|
||||
"unicode": "\ue67e"
|
||||
},
|
||||
{
|
||||
"font_class": "micoff-filled",
|
||||
"unicode": "\ue6b0"
|
||||
},
|
||||
{
|
||||
"font_class": "minus",
|
||||
"unicode": "\ue66f"
|
||||
},
|
||||
{
|
||||
"font_class": "minus-filled",
|
||||
"unicode": "\ue67d"
|
||||
},
|
||||
{
|
||||
"font_class": "more",
|
||||
"unicode": "\ue64d"
|
||||
},
|
||||
{
|
||||
"font_class": "more-filled",
|
||||
"unicode": "\ue64e"
|
||||
},
|
||||
{
|
||||
"font_class": "navigate",
|
||||
"unicode": "\ue66e"
|
||||
},
|
||||
{
|
||||
"font_class": "navigate-filled",
|
||||
"unicode": "\ue67a"
|
||||
},
|
||||
{
|
||||
"font_class": "notification",
|
||||
"unicode": "\ue6a6"
|
||||
},
|
||||
{
|
||||
"font_class": "notification-filled",
|
||||
"unicode": "\ue6c1"
|
||||
},
|
||||
{
|
||||
"font_class": "paperclip",
|
||||
"unicode": "\ue652"
|
||||
},
|
||||
{
|
||||
"font_class": "paperplane",
|
||||
"unicode": "\ue672"
|
||||
},
|
||||
{
|
||||
"font_class": "paperplane-filled",
|
||||
"unicode": "\ue675"
|
||||
},
|
||||
{
|
||||
"font_class": "person",
|
||||
"unicode": "\ue699"
|
||||
},
|
||||
{
|
||||
"font_class": "person-filled",
|
||||
"unicode": "\ue69d"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd",
|
||||
"unicode": "\ue69f"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd-filled",
|
||||
"unicode": "\ue698"
|
||||
},
|
||||
{
|
||||
"font_class": "personadd-filled-copy",
|
||||
"unicode": "\ue6d1"
|
||||
},
|
||||
{
|
||||
"font_class": "phone",
|
||||
"unicode": "\ue69c"
|
||||
},
|
||||
{
|
||||
"font_class": "phone-filled",
|
||||
"unicode": "\ue69b"
|
||||
},
|
||||
{
|
||||
"font_class": "plus",
|
||||
"unicode": "\ue676"
|
||||
},
|
||||
{
|
||||
"font_class": "plus-filled",
|
||||
"unicode": "\ue6c7"
|
||||
},
|
||||
{
|
||||
"font_class": "plusempty",
|
||||
"unicode": "\ue67b"
|
||||
},
|
||||
{
|
||||
"font_class": "pulldown",
|
||||
"unicode": "\ue632"
|
||||
},
|
||||
{
|
||||
"font_class": "pyq",
|
||||
"unicode": "\ue682"
|
||||
},
|
||||
{
|
||||
"font_class": "qq",
|
||||
"unicode": "\ue680"
|
||||
},
|
||||
{
|
||||
"font_class": "redo",
|
||||
"unicode": "\ue64a"
|
||||
},
|
||||
{
|
||||
"font_class": "redo-filled",
|
||||
"unicode": "\ue655"
|
||||
},
|
||||
{
|
||||
"font_class": "refresh",
|
||||
"unicode": "\ue657"
|
||||
},
|
||||
{
|
||||
"font_class": "refresh-filled",
|
||||
"unicode": "\ue656"
|
||||
},
|
||||
{
|
||||
"font_class": "refreshempty",
|
||||
"unicode": "\ue6bf"
|
||||
},
|
||||
{
|
||||
"font_class": "reload",
|
||||
"unicode": "\ue6b2"
|
||||
},
|
||||
{
|
||||
"font_class": "right",
|
||||
"unicode": "\ue6b5"
|
||||
},
|
||||
{
|
||||
"font_class": "scan",
|
||||
"unicode": "\ue62a"
|
||||
},
|
||||
{
|
||||
"font_class": "search",
|
||||
"unicode": "\ue654"
|
||||
},
|
||||
{
|
||||
"font_class": "settings",
|
||||
"unicode": "\ue653"
|
||||
},
|
||||
{
|
||||
"font_class": "settings-filled",
|
||||
"unicode": "\ue6ce"
|
||||
},
|
||||
{
|
||||
"font_class": "shop",
|
||||
"unicode": "\ue62f"
|
||||
},
|
||||
{
|
||||
"font_class": "shop-filled",
|
||||
"unicode": "\ue6cd"
|
||||
},
|
||||
{
|
||||
"font_class": "smallcircle",
|
||||
"unicode": "\ue67c"
|
||||
},
|
||||
{
|
||||
"font_class": "smallcircle-filled",
|
||||
"unicode": "\ue665"
|
||||
},
|
||||
{
|
||||
"font_class": "sound",
|
||||
"unicode": "\ue684"
|
||||
},
|
||||
{
|
||||
"font_class": "sound-filled",
|
||||
"unicode": "\ue686"
|
||||
},
|
||||
{
|
||||
"font_class": "spinner-cycle",
|
||||
"unicode": "\ue68a"
|
||||
},
|
||||
{
|
||||
"font_class": "staff",
|
||||
"unicode": "\ue6a7"
|
||||
},
|
||||
{
|
||||
"font_class": "staff-filled",
|
||||
"unicode": "\ue6cb"
|
||||
},
|
||||
{
|
||||
"font_class": "star",
|
||||
"unicode": "\ue688"
|
||||
},
|
||||
{
|
||||
"font_class": "star-filled",
|
||||
"unicode": "\ue68f"
|
||||
},
|
||||
{
|
||||
"font_class": "starhalf",
|
||||
"unicode": "\ue683"
|
||||
},
|
||||
{
|
||||
"font_class": "trash",
|
||||
"unicode": "\ue687"
|
||||
},
|
||||
{
|
||||
"font_class": "trash-filled",
|
||||
"unicode": "\ue685"
|
||||
},
|
||||
{
|
||||
"font_class": "tune",
|
||||
"unicode": "\ue6aa"
|
||||
},
|
||||
{
|
||||
"font_class": "tune-filled",
|
||||
"unicode": "\ue6ca"
|
||||
},
|
||||
{
|
||||
"font_class": "undo",
|
||||
"unicode": "\ue64f"
|
||||
},
|
||||
{
|
||||
"font_class": "undo-filled",
|
||||
"unicode": "\ue64c"
|
||||
},
|
||||
{
|
||||
"font_class": "up",
|
||||
"unicode": "\ue6b6"
|
||||
},
|
||||
{
|
||||
"font_class": "top",
|
||||
"unicode": "\ue6b6"
|
||||
},
|
||||
{
|
||||
"font_class": "upload",
|
||||
"unicode": "\ue690"
|
||||
},
|
||||
{
|
||||
"font_class": "upload-filled",
|
||||
"unicode": "\ue68e"
|
||||
},
|
||||
{
|
||||
"font_class": "videocam",
|
||||
"unicode": "\ue68c"
|
||||
},
|
||||
{
|
||||
"font_class": "videocam-filled",
|
||||
"unicode": "\ue689"
|
||||
},
|
||||
{
|
||||
"font_class": "vip",
|
||||
"unicode": "\ue6a8"
|
||||
},
|
||||
{
|
||||
"font_class": "vip-filled",
|
||||
"unicode": "\ue6c6"
|
||||
},
|
||||
{
|
||||
"font_class": "wallet",
|
||||
"unicode": "\ue6b1"
|
||||
},
|
||||
{
|
||||
"font_class": "wallet-filled",
|
||||
"unicode": "\ue6c2"
|
||||
},
|
||||
{
|
||||
"font_class": "weibo",
|
||||
"unicode": "\ue68b"
|
||||
},
|
||||
{
|
||||
"font_class": "weixin",
|
||||
"unicode": "\ue691"
|
||||
}
|
||||
]
|
||||
|
||||
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
|
||||
89
uni_modules/uni-icons/package.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"id": "uni-icons",
|
||||
"displayName": "uni-icons 图标",
|
||||
"version": "2.0.10",
|
||||
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"icon",
|
||||
"图标"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.2.14"
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y",
|
||||
"app-uvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "y",
|
||||
"快手": "y",
|
||||
"飞书": "y",
|
||||
"京东": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
uni_modules/uni-icons/readme.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Icons 图标
|
||||
> **组件名:uni-icons**
|
||||
> 代码块: `uIcons`
|
||||
|
||||
用于展示 icons 图标 。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
25
uni_modules/uni-load-more/changelog.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## 1.3.6(2024-10-15)
|
||||
- 修复 微信小程序中的getSystemInfo警告
|
||||
## 1.3.5(2024-10-12)
|
||||
- 修复 微信小程序中的getSystemInfo警告
|
||||
## 1.3.4(2024-10-12)
|
||||
- 修复 微信小程序中的getSystemInfo警告
|
||||
## 1.3.3(2022-01-20)
|
||||
- 新增 showText属性 ,是否显示文本
|
||||
## 1.3.2(2022-01-19)
|
||||
- 修复 nvue 平台下不显示文本的bug
|
||||
## 1.3.1(2022-01-19)
|
||||
- 修复 微信小程序平台样式选择器报警告的问题
|
||||
## 1.3.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more)
|
||||
## 1.2.1(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.2.0(2021-07-30)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.1.8(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.1.7(2021-03-30)
|
||||
- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug
|
||||
## 1.1.6(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "Pull up to show more",
|
||||
"uni-load-more.contentrefresh": "loading...",
|
||||
"uni-load-more.contentnomore": "No more data"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "上拉显示更多",
|
||||
"uni-load-more.contentrefresh": "正在加载...",
|
||||
"uni-load-more.contentnomore": "没有更多数据了"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "上拉顯示更多",
|
||||
"uni-load-more.contentrefresh": "正在加載...",
|
||||
"uni-load-more.contentnomore": "沒有更多數據了"
|
||||
}
|
||||
84
uni_modules/uni-load-more/package.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"id": "uni-load-more",
|
||||
"displayName": "uni-load-more 加载更多",
|
||||
"version": "1.3.6",
|
||||
"description": "LoadMore 组件,常用在列表里面,做滚动加载使用。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"加载更多",
|
||||
"load-more"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
uni_modules/uni-load-more/readme.md
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
### LoadMore 加载更多
|
||||
> **组件名:uni-load-more**
|
||||
> 代码块: `uLoadMore`
|
||||
|
||||
|
||||
用于列表中,做滚动加载使用,展示 loading 的各种状态。
|
||||
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
||||
|
||||
100
uni_modules/uni-popup/changelog.md
Normal file
@@ -0,0 +1,100 @@
|
||||
## 1.9.10(2025-07-18)
|
||||
- 修复 nvue 下弹窗样式错乱的问题 ,更新依赖 uni-transition 组件
|
||||
- 更新 示例取消 borderRadius 属性 ,如需内容圆角,用户应该直接在内容插槽中实现
|
||||
## 1.9.9(2025-06-11)
|
||||
- 修复 uni-popup-dialog 中 setVal 方法报错的问题
|
||||
- 修复 uni-popup-dialog 数据双向绑定问题。
|
||||
## 1.9.8(2025-04-16)
|
||||
- 修复 更新组件示例 ,解决更新数据或保存项目导致弹窗消失的问题
|
||||
## 1.9.7(2025-04-14)
|
||||
- 修复 uni-popup-dialog 弹出框在vue3中双向绑定问题
|
||||
## 1.9.6(2025-01-08)
|
||||
- 修复 示例中过期图片地址
|
||||
## 1.9.5(2024-10-15)
|
||||
- 修复 微信小程序中的getSystemInfo警告
|
||||
## 1.9.2(2024-09-21)
|
||||
- 修复 uni-popup在android上的重复点击弹出位置不正确的bug
|
||||
## 1.9.1(2024-04-02)
|
||||
- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法)
|
||||
## 1.9.0(2024-03-28)
|
||||
- 修复 uni-popup-dialog 双向绑定时初始化逻辑修正
|
||||
## 1.8.9(2024-03-20)
|
||||
- 修复 uni-popup-dialog 数据输入时修正为双向绑定
|
||||
## 1.8.8(2024-02-20)
|
||||
- 修复 uni-popup 在微信小程序下出现文字向上闪动的bug
|
||||
## 1.8.7(2024-02-02)
|
||||
- 新增 uni-popup-dialog 新增属性focus:input模式下,是否自动自动聚焦
|
||||
## 1.8.6(2024-01-30)
|
||||
- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数
|
||||
## 1.8.5(2024-01-26)
|
||||
- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示
|
||||
## 1.8.4(2023-11-15)
|
||||
- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close`
|
||||
## 1.8.3(2023-04-17)
|
||||
- 修复 uni-popup 重复打开时的 bug
|
||||
## 1.8.2(2023-02-02)
|
||||
- uni-popup-dialog 组件新增 inputType 属性
|
||||
## 1.8.1(2022-12-01)
|
||||
- 修复 nvue 下 v-show 报错
|
||||
## 1.8.0(2022-11-29)
|
||||
- 优化 主题样式
|
||||
## 1.7.9(2022-04-02)
|
||||
- 修复 弹出层内部无法滚动的bug
|
||||
## 1.7.8(2022-03-28)
|
||||
- 修复 小程序中高度错误的bug
|
||||
## 1.7.7(2022-03-17)
|
||||
- 修复 快速调用open出现问题的Bug
|
||||
## 1.7.6(2022-02-14)
|
||||
- 修复 safeArea 属性不能设置为false的bug
|
||||
## 1.7.5(2022-01-19)
|
||||
- 修复 isMaskClick 失效的bug
|
||||
## 1.7.4(2022-01-19)
|
||||
- 新增 cancelText \ confirmText 属性 ,可自定义文本
|
||||
- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
|
||||
- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
|
||||
## 1.7.3(2022-01-13)
|
||||
- 修复 设置 safeArea 属性不生效的bug
|
||||
## 1.7.2(2021-11-26)
|
||||
- 优化 组件示例
|
||||
## 1.7.1(2021-11-26)
|
||||
- 修复 vuedoc 文字错误
|
||||
## 1.7.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
|
||||
## 1.6.2(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.6.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.6.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.5.0(2021-06-23)
|
||||
- 新增 mask-click 遮罩层点击事件
|
||||
## 1.4.5(2021-06-22)
|
||||
- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.4(2021-06-18)
|
||||
- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.3(2021-06-08)
|
||||
- 修复 错误的 watch 字段
|
||||
- 修复 safeArea 属性不生效的问题
|
||||
- 修复 点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.2(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.4.1(2021-04-29)
|
||||
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
|
||||
## 1.4.0 (2021-04-29)
|
||||
- 新增 type 属性的 left\right 值,支持左右弹出
|
||||
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
|
||||
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
|
||||
- 新增 safeArea 属性,是否适配底部安全区
|
||||
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
|
||||
- 修复 App 端弹出等待的Bug
|
||||
- 优化 提升低配设备性能,优化动画卡顿问题
|
||||
- 优化 更简单的组件自定义方式
|
||||
## 1.2.9(2021-02-05)
|
||||
- 优化 组件引用关系,通过uni_modules引用组件
|
||||
## 1.2.8(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
## 1.2.7(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 新增 支持 PC 端
|
||||
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端
|
||||
@@ -0,0 +1,45 @@
|
||||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
document.removeEventListener('keyup', listener)
|
||||
})
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<view class="uni-popup-dialog">
|
||||
<view class="uni-dialog-title">
|
||||
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
|
||||
</view>
|
||||
<view v-if="mode === 'base'" class="uni-dialog-content">
|
||||
<slot>
|
||||
<text class="uni-dialog-content-text">{{content}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
<view v-else class="uni-dialog-content">
|
||||
<slot>
|
||||
<input class="uni-dialog-input" :maxlength="maxlength" v-model="val" :type="inputType"
|
||||
:placeholder="placeholderText" :focus="focus">
|
||||
</slot>
|
||||
</view>
|
||||
<view class="uni-dialog-button-group">
|
||||
<view class="uni-dialog-button" v-if="showClose" @click="closeDialog">
|
||||
<text class="uni-dialog-button-text">{{closeText}}</text>
|
||||
</view>
|
||||
<view class="uni-dialog-button" :class="showClose?'uni-border-left':''" @click="onOk">
|
||||
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(messages)
|
||||
/**
|
||||
* PopUp 弹出层-对话框样式
|
||||
* @description 弹出层-对话框样式
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} value input 模式下的默认值
|
||||
* @property {String} placeholder input 模式下输入提示
|
||||
* @property {Boolean} focus input模式下是否自动聚焦,默认为true
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} mode = [base|input] 模式、
|
||||
* @value base 基础对话框
|
||||
* @value input 可输入对话框
|
||||
* @showClose {Boolean} 是否显示关闭按钮
|
||||
* @property {String} content 对话框内容
|
||||
* @property {Boolean} beforeClose 是否拦截取消事件
|
||||
* @property {Number} maxlength 输入
|
||||
* @event {Function} confirm 点击确认按钮触发
|
||||
* @event {Function} close 点击取消按钮触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "uniPopupDialog",
|
||||
mixins: [popup],
|
||||
emits: ['confirm', 'close', 'update:modelValue', 'input'],
|
||||
props: {
|
||||
inputType: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #ifdef VUE2
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
|
||||
|
||||
placeholder: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'error'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'base'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: -1,
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogType: 'error',
|
||||
val: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
okText() {
|
||||
return this.confirmText || t("uni-popup.ok")
|
||||
},
|
||||
closeText() {
|
||||
return this.cancelText || t("uni-popup.cancel")
|
||||
},
|
||||
placeholderText() {
|
||||
return this.placeholder || t("uni-popup.placeholder")
|
||||
},
|
||||
titleText() {
|
||||
return this.title || t("uni-popup.title")
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
type(val) {
|
||||
this.dialogType = val
|
||||
},
|
||||
mode(val) {
|
||||
if (val === 'input') {
|
||||
this.dialogType = 'info'
|
||||
}
|
||||
},
|
||||
value(val) {
|
||||
this.setVal(val)
|
||||
},
|
||||
// #ifdef VUE3
|
||||
modelValue(val) {
|
||||
this.setVal(val)
|
||||
},
|
||||
// #endif
|
||||
val(val) {
|
||||
// #ifdef VUE2
|
||||
// TODO 兼容 vue2
|
||||
this.$emit('input', val);
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
// TODO 兼容 vue3
|
||||
this.$emit('update:modelValue', val);
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 对话框遮罩不可点击
|
||||
this.popup.disableMask()
|
||||
// this.popup.closeMask()
|
||||
if (this.mode === 'input') {
|
||||
this.dialogType = 'info'
|
||||
this.val = this.value;
|
||||
// #ifdef VUE3
|
||||
this.val = this.modelValue;
|
||||
// #endif
|
||||
} else {
|
||||
this.dialogType = this.type
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 给val属性赋值
|
||||
*/
|
||||
setVal(val) {
|
||||
if (this.maxlength != -1 && this.mode === 'input') {
|
||||
this.val = val.slice(0, this.maxlength);
|
||||
} else {
|
||||
this.val = val
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
onOk() {
|
||||
if (this.mode === 'input') {
|
||||
this.$emit('confirm', this.val)
|
||||
} else {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
if (this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
/**
|
||||
* 点击取消按钮
|
||||
*/
|
||||
closeDialog() {
|
||||
this.$emit('close')
|
||||
if (this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
close() {
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-popup-dialog {
|
||||
width: 300px;
|
||||
border-radius: 11px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.uni-dialog-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.uni-dialog-title-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.uni-dialog-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.uni-dialog-content-text {
|
||||
font-size: 14px;
|
||||
color: #6C6C6C;
|
||||
}
|
||||
|
||||
.uni-dialog-button-group {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
border-top-color: #f5f5f5;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.uni-border-left {
|
||||
border-left-color: #f0f0f0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button-text {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-button-color {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.uni-dialog-input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
border: 1px #eee solid;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
border-radius: 5px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
color: #4cd964;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
color: #dd524d;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view class="uni-popup-message">
|
||||
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
|
||||
<slot>
|
||||
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
/**
|
||||
* PopUp 弹出层-消息提示
|
||||
* @description 弹出层-消息提示
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} message 消息提示文字
|
||||
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniPopupMessage',
|
||||
mixins:[popup],
|
||||
props: {
|
||||
/**
|
||||
* 主题 success/warning/info/error 默认 success
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
/**
|
||||
* 消息文字
|
||||
*/
|
||||
message: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
},
|
||||
maskShow:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
this.popup.maskShow = this.maskShow
|
||||
this.popup.messageChild = this
|
||||
},
|
||||
methods: {
|
||||
timerClose(){
|
||||
if(this.duration === 0) return
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(()=>{
|
||||
this.popup.close()
|
||||
},this.duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" >
|
||||
.uni-popup-message {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-popup-message__box {
|
||||
background-color: #e1f3d8;
|
||||
padding: 10px 15px;
|
||||
border-color: #eee;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.fixforpc-width {
|
||||
margin-top: 20px;
|
||||
border-radius: 4px;
|
||||
flex: none;
|
||||
min-width: 380px;
|
||||
/* #ifndef APP-NVUE */
|
||||
max-width: 50%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
max-width: 500px;
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
|
||||
.uni-popup-message-text {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
background-color: #e1f3d8;
|
||||
}
|
||||
|
||||
.uni-popup__success-text {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
background-color: #faecd8;
|
||||
}
|
||||
|
||||
.uni-popup__warn-text {
|
||||
color: #E6A23C;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
background-color: #fde2e2;
|
||||
}
|
||||
|
||||
.uni-popup__error-text {
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
background-color: #F2F6FC;
|
||||
}
|
||||
|
||||
.uni-popup__info-text {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<view class="uni-popup-share">
|
||||
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
|
||||
<view class="uni-share-content">
|
||||
<view class="uni-share-content-box">
|
||||
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
|
||||
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
|
||||
<text class="uni-share-text">{{item.text}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-share-button-box">
|
||||
<button class="uni-share-button" @click="close">{{cancelText}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const { t } = initVueI18n(messages)
|
||||
export default {
|
||||
name: 'UniPopupShare',
|
||||
mixins:[popup],
|
||||
emits:['select'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// TODO 替换为自己的图标
|
||||
bottomData: [{
|
||||
text: '微信',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: '支付宝',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'ali'
|
||||
},
|
||||
{
|
||||
text: 'QQ',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'qq'
|
||||
},
|
||||
{
|
||||
text: '新浪',
|
||||
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
|
||||
name: 'sina'
|
||||
},
|
||||
// {
|
||||
// text: '百度',
|
||||
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
|
||||
// name: 'copy'
|
||||
// },
|
||||
// {
|
||||
// text: '其他',
|
||||
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
|
||||
// name: 'more'
|
||||
// }
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
computed: {
|
||||
cancelText() {
|
||||
return t("uni-popup.cancel")
|
||||
},
|
||||
shareTitleText() {
|
||||
return this.title || t("uni-popup.shareTitle")
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 选择内容
|
||||
*/
|
||||
select(item, index) {
|
||||
this.$emit('select', {
|
||||
item,
|
||||
index
|
||||
})
|
||||
this.close()
|
||||
|
||||
},
|
||||
/**
|
||||
* 关闭窗口
|
||||
*/
|
||||
close() {
|
||||
if(this.beforeClose) return
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" >
|
||||
.uni-popup-share {
|
||||
background-color: #fff;
|
||||
border-top-left-radius: 11px;
|
||||
border-top-right-radius: 11px;
|
||||
}
|
||||
.uni-share-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
}
|
||||
.uni-share-title-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.uni-share-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.uni-share-content-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.uni-share-content-item {
|
||||
width: 90px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-share-content-item:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.uni-share-image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.uni-share-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #3B4144;
|
||||
}
|
||||
|
||||
.uni-share-button-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.uni-share-button {
|
||||
flex: 1;
|
||||
border-radius: 50px;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uni-share-button::after {
|
||||
border-radius: 50px;
|
||||
}
|
||||
</style>
|
||||
7
uni_modules/uni-popup/components/uni-popup/i18n/en.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"uni-popup.cancel": "cancel",
|
||||
"uni-popup.ok": "ok",
|
||||
"uni-popup.placeholder": "pleace enter",
|
||||
"uni-popup.title": "Hint",
|
||||
"uni-popup.shareTitle": "Share to"
|
||||
}
|
||||
8
uni_modules/uni-popup/components/uni-popup/i18n/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "确定",
|
||||
"uni-popup.placeholder": "请输入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "確定",
|
||||
"uni-popup.placeholder": "請輸入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
||||
45
uni_modules/uni-popup/components/uni-popup/keypress.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// document.removeEventListener('keyup', listener)
|
||||
// })
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
||||
26
uni_modules/uni-popup/components/uni-popup/popup.js
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.popup = this.getParent()
|
||||
},
|
||||
methods:{
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getParent(name = 'uniPopup') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
}
|
||||
}
|
||||
90
uni_modules/uni-popup/components/uni-popup/uni-popup.uvue
Normal file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<view class="popup-root" v-if="isOpen" v-show="isShow" @click="clickMask">
|
||||
<view @click.stop>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
type CloseCallBack = ()=> void;
|
||||
let closeCallBack:CloseCallBack = () :void => {};
|
||||
export default {
|
||||
emits:["close","clickMask"],
|
||||
data() {
|
||||
return {
|
||||
isShow:false,
|
||||
isOpen:false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 设置show = true 时,如果没有 open 需要设置为 open
|
||||
isShow:{
|
||||
handler(isShow) {
|
||||
// console.log("isShow",isShow)
|
||||
if(isShow && this.isOpen == false){
|
||||
this.isOpen = true
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
},
|
||||
// 设置isOpen = true 时,如果没有 isShow 需要设置为 isShow
|
||||
isOpen:{
|
||||
handler(isOpen) {
|
||||
// console.log("isOpen",isOpen)
|
||||
if(isOpen && this.isShow == false){
|
||||
this.isShow = true
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
open(){
|
||||
// ...funs : CloseCallBack[]
|
||||
// if(funs.length > 0){
|
||||
// closeCallBack = funs[0]
|
||||
// }
|
||||
this.isOpen = true;
|
||||
},
|
||||
clickMask(){
|
||||
if(this.maskClick == true){
|
||||
this.$emit('clickMask')
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
close(): void{
|
||||
this.isOpen = false;
|
||||
this.$emit('close')
|
||||
closeCallBack()
|
||||
},
|
||||
hiden(){
|
||||
this.isShow = false
|
||||
},
|
||||
show(){
|
||||
this.isShow = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.popup-root {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 750rpx;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
518
uni_modules/uni-popup/components/uni-popup/uni-popup.vue
Normal file
@@ -0,0 +1,518 @@
|
||||
<template>
|
||||
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
|
||||
<view @touchstart="touchstart">
|
||||
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
|
||||
:duration="duration" :show="showTrans" @click="onTap" />
|
||||
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
|
||||
:show="showTrans" @click="onTap">
|
||||
<view class="uni-popup__wrapper" :style="getStyles" :class="[popupstyle]" @click="clear">
|
||||
<slot />
|
||||
</view>
|
||||
</uni-transition>
|
||||
</view>
|
||||
<!-- #ifdef H5 -->
|
||||
<keypress v-if="maskShow" @esc="onTap" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef H5
|
||||
import keypress from './keypress.js'
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* PopUp 弹出层
|
||||
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
|
||||
* @value top 顶部弹出
|
||||
* @value center 中间弹出
|
||||
* @value bottom 底部弹出
|
||||
* @value left 左侧弹出
|
||||
* @value right 右侧弹出
|
||||
* @value message 消息提示
|
||||
* @value dialog 对话框
|
||||
* @value share 底部分享示例
|
||||
* @property {Boolean} animation = [true|false] 是否开启动画
|
||||
* @property {Boolean} maskClick = [true|false] 蒙版点击是否关闭弹窗(废弃)
|
||||
* @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗
|
||||
* @property {String} backgroundColor 主窗口背景色
|
||||
* @property {String} maskBackgroundColor 蒙版颜色
|
||||
* @property {String} borderRadius 设置圆角(左上、右上、右下和左下) 示例:"10px 10px 10px 10px"
|
||||
* @property {Boolean} safeArea 是否适配底部安全区
|
||||
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||
* @event {Function} maskClick 点击遮罩触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniPopup',
|
||||
components: {
|
||||
// #ifdef H5
|
||||
keypress
|
||||
// #endif
|
||||
},
|
||||
emits: ['change', 'maskClick'],
|
||||
props: {
|
||||
// 开启动画
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
// message: 消息提示 ; dialog : 对话框
|
||||
type: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// maskClick
|
||||
isMaskClick: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
// TODO 2 个版本后废弃属性 ,使用 isMaskClick
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: 'none'
|
||||
},
|
||||
safeArea: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maskBackgroundColor: {
|
||||
type: String,
|
||||
default: 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
borderRadius:{
|
||||
type: String,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* 监听type类型
|
||||
*/
|
||||
type: {
|
||||
handler: function(type) {
|
||||
if (!this.config[type]) return
|
||||
this[this.config[type]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isDesktop: {
|
||||
handler: function(newVal) {
|
||||
if (!this.config[newVal]) return
|
||||
this[this.config[this.type]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
/**
|
||||
* 监听遮罩是否可点击
|
||||
* @param {Object} val
|
||||
*/
|
||||
maskClick: {
|
||||
handler: function(val) {
|
||||
this.mkclick = val
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isMaskClick: {
|
||||
handler: function(val) {
|
||||
this.mkclick = val
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
// H5 下禁止底部滚动
|
||||
showPopup(show) {
|
||||
// #ifdef H5
|
||||
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||
document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
duration: 300,
|
||||
ani: [],
|
||||
showPopup: false,
|
||||
showTrans: false,
|
||||
popupWidth: 0,
|
||||
popupHeight: 0,
|
||||
config: {
|
||||
top: 'top',
|
||||
bottom: 'bottom',
|
||||
center: 'center',
|
||||
left: 'left',
|
||||
right: 'right',
|
||||
message: 'top',
|
||||
dialog: 'center',
|
||||
share: 'bottom'
|
||||
},
|
||||
maskClass: {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
transClass: {
|
||||
backgroundColor: 'transparent',
|
||||
borderRadius: this.borderRadius || "0",
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
maskShow: true,
|
||||
mkclick: true,
|
||||
popupstyle: 'top'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getStyles() {
|
||||
let res = { backgroundColor: this.bg };
|
||||
if (this.borderRadius || "0") {
|
||||
res = Object.assign(res, { borderRadius: this.borderRadius })
|
||||
}
|
||||
return res;
|
||||
},
|
||||
isDesktop() {
|
||||
return this.popupWidth >= 500 && this.popupHeight >= 500
|
||||
},
|
||||
bg() {
|
||||
if (this.backgroundColor === '' || this.backgroundColor === 'none') {
|
||||
return 'transparent'
|
||||
}
|
||||
return this.backgroundColor
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const fixSize = () => {
|
||||
// #ifdef MP-WEIXIN
|
||||
const {
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
windowTop,
|
||||
safeArea,
|
||||
screenHeight,
|
||||
safeAreaInsets
|
||||
} = uni.getWindowInfo()
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
const {
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
windowTop,
|
||||
safeArea,
|
||||
screenHeight,
|
||||
safeAreaInsets
|
||||
} = uni.getSystemInfoSync()
|
||||
// #endif
|
||||
this.popupWidth = windowWidth
|
||||
this.popupHeight = windowHeight + (windowTop || 0)
|
||||
// TODO fix by mehaotian 是否适配底部安全区 ,目前微信ios 、和 app ios 计算有差异,需要框架修复
|
||||
if (safeArea && this.safeArea) {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.safeAreaInsets = screenHeight - safeArea.bottom
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
this.safeAreaInsets = safeAreaInsets.bottom
|
||||
// #endif
|
||||
} else {
|
||||
this.safeAreaInsets = 0
|
||||
}
|
||||
}
|
||||
fixSize()
|
||||
// #ifdef H5
|
||||
// window.addEventListener('resize', fixSize)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// window.removeEventListener('resize', fixSize)
|
||||
// })
|
||||
// #endif
|
||||
},
|
||||
// #ifndef VUE3
|
||||
// TODO vue2
|
||||
destroyed() {
|
||||
this.setH5Visible()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
// TODO vue3
|
||||
unmounted() {
|
||||
this.setH5Visible()
|
||||
},
|
||||
// #endif
|
||||
activated() {
|
||||
this.setH5Visible(!this.showPopup);
|
||||
},
|
||||
deactivated() {
|
||||
this.setH5Visible(true);
|
||||
},
|
||||
created() {
|
||||
// this.mkclick = this.isMaskClick || this.maskClick
|
||||
if (this.isMaskClick === null && this.maskClick === null) {
|
||||
this.mkclick = true
|
||||
} else {
|
||||
this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
|
||||
}
|
||||
if (this.animation) {
|
||||
this.duration = 300
|
||||
} else {
|
||||
this.duration = 0
|
||||
}
|
||||
// TODO 处理 message 组件生命周期异常的问题
|
||||
this.messageChild = null
|
||||
// TODO 解决头条冒泡的问题
|
||||
this.clearPropagation = false
|
||||
this.maskClass.backgroundColor = this.maskBackgroundColor
|
||||
},
|
||||
methods: {
|
||||
setH5Visible(visible = true) {
|
||||
// #ifdef H5
|
||||
// fix by mehaotian 处理 h5 滚动穿透的问题
|
||||
document.getElementsByTagName('body')[0].style.overflow = visible ? "visible" : "hidden";
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 公用方法,不显示遮罩层
|
||||
*/
|
||||
closeMask() {
|
||||
this.maskShow = false
|
||||
},
|
||||
/**
|
||||
* 公用方法,遮罩层禁止点击
|
||||
*/
|
||||
disableMask() {
|
||||
this.mkclick = false
|
||||
},
|
||||
// TODO nvue 取消冒泡
|
||||
clear(e) {
|
||||
// #ifndef APP-NVUE
|
||||
e.stopPropagation()
|
||||
// #endif
|
||||
this.clearPropagation = true
|
||||
},
|
||||
|
||||
open(direction) {
|
||||
// fix by mehaotian 处理快速打开关闭的情况
|
||||
if (this.showPopup) {
|
||||
return
|
||||
}
|
||||
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
|
||||
if (!(direction && innerType.indexOf(direction) !== -1)) {
|
||||
direction = this.type
|
||||
}
|
||||
if (!this.config[direction]) {
|
||||
console.error('缺少类型:', direction)
|
||||
return
|
||||
}
|
||||
this[this.config[direction]]()
|
||||
this.$emit('change', {
|
||||
show: true,
|
||||
type: direction
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
this.showTrans = false
|
||||
this.$emit('change', {
|
||||
show: false,
|
||||
type: this.type
|
||||
})
|
||||
clearTimeout(this.timer)
|
||||
// // 自定义关闭事件
|
||||
// this.customOpen && this.customClose()
|
||||
this.timer = setTimeout(() => {
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
},
|
||||
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
|
||||
touchstart() {
|
||||
this.clearPropagation = false
|
||||
},
|
||||
|
||||
onTap() {
|
||||
if (this.clearPropagation) {
|
||||
// fix by mehaotian 兼容 nvue
|
||||
this.clearPropagation = false
|
||||
return
|
||||
}
|
||||
this.$emit('maskClick')
|
||||
if (!this.mkclick) return
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* 顶部弹出样式处理
|
||||
*/
|
||||
top(type) {
|
||||
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
|
||||
this.ani = ['slide-top']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: this.bg,
|
||||
borderRadius:this.borderRadius || "0"
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
this.$nextTick(() => {
|
||||
this.showPoptrans()
|
||||
if (this.messageChild && this.type === 'message') {
|
||||
this.messageChild.timerClose()
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 底部弹出样式处理
|
||||
*/
|
||||
bottom(type) {
|
||||
this.popupstyle = 'bottom'
|
||||
this.ani = ['slide-bottom']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
// paddingBottom: this.safeAreaInsets + 'px',
|
||||
backgroundColor: this.bg,
|
||||
borderRadius:this.borderRadius || "0",
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPoptrans()
|
||||
},
|
||||
/**
|
||||
* 中间弹出样式处理
|
||||
*/
|
||||
center(type) {
|
||||
this.popupstyle = 'center'
|
||||
//微信小程序下,组合动画会出现文字向上闪动问题,再此做特殊处理
|
||||
// #ifdef MP-WEIXIN
|
||||
this.ani = ['fade']
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
this.ani = ['zoom-out', 'fade']
|
||||
// #endif
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
/* #endif */
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
borderRadius:this.borderRadius || "0"
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPoptrans()
|
||||
},
|
||||
left(type) {
|
||||
this.popupstyle = 'left'
|
||||
this.ani = ['slide-left']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
borderRadius:this.borderRadius || "0",
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPoptrans()
|
||||
},
|
||||
right(type) {
|
||||
this.popupstyle = 'right'
|
||||
this.ani = ['slide-right']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
borderRadius:this.borderRadius || "0",
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPoptrans()
|
||||
},
|
||||
showPoptrans(){
|
||||
this.$nextTick(()=>{
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.uni-popup {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
|
||||
/* #endif */
|
||||
&.top,
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-popup__wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
|
||||
/* iphonex 等安全区设置,底部安全区适配 */
|
||||
/* #ifndef APP-NVUE */
|
||||
// padding-bottom: constant(safe-area-inset-bottom);
|
||||
// padding-bottom: env(safe-area-inset-bottom);
|
||||
/* #endif */
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
padding-top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
padding-top: 0;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fixforpc-z-index {
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fixforpc-top {
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
107
uni_modules/uni-popup/package.json
Normal file
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"id": "uni-popup",
|
||||
"displayName": "uni-popup 弹出层",
|
||||
"version": "1.9.10",
|
||||
"description": " Popup 组件,提供常用的弹层",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"弹出层",
|
||||
"弹窗",
|
||||
"popup",
|
||||
"弹框"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": "",
|
||||
"uni-app": "^4.06",
|
||||
"uni-app-x": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue",
|
||||
"darkmode": "x",
|
||||
"i18n": "x",
|
||||
"widescreen": "x"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-scss",
|
||||
"uni-transition"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "x",
|
||||
"aliyun": "x",
|
||||
"alipay": "x"
|
||||
},
|
||||
"client": {
|
||||
"uni-app": {
|
||||
"vue": {
|
||||
"vue2": "√",
|
||||
"vue3": "√"
|
||||
},
|
||||
"web": {
|
||||
"safari": "√",
|
||||
"chrome": "√"
|
||||
},
|
||||
"app": {
|
||||
"vue": "√",
|
||||
"nvue": "√",
|
||||
"android": "√",
|
||||
"ios": "√",
|
||||
"harmony": "√"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "√",
|
||||
"alipay": "√",
|
||||
"toutiao": "√",
|
||||
"baidu": "√",
|
||||
"kuaishou": "-",
|
||||
"jd": "-",
|
||||
"harmony": "-",
|
||||
"qq": "√",
|
||||
"lark": "-"
|
||||
},
|
||||
"quickapp": {
|
||||
"huawei": "-",
|
||||
"union": "-"
|
||||
}
|
||||
},
|
||||
"uni-app-x": {
|
||||
"web": {
|
||||
"safari": "√",
|
||||
"chrome": "√"
|
||||
},
|
||||
"app": {
|
||||
"android": "√",
|
||||
"ios": "√",
|
||||
"harmony": "√"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "√"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
uni_modules/uni-popup/readme.md
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
## Popup 弹出层
|
||||
> **组件名:uni-popup**
|
||||
> 代码块: `uPopup`
|
||||
> 关联组件:`uni-transition`
|
||||
|
||||
|
||||
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
25
uni_modules/uni-rate/changelog.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## 1.3.1(2022-02-25)
|
||||
- 修复 条件判断 `NaN` 错误的 bug
|
||||
## 1.3.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate)
|
||||
## 1.2.2(2021-09-10)
|
||||
- 优化 默认值修改为 0 颗星
|
||||
## 1.2.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.2.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.1.2(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.1.1(2021-04-21)
|
||||
- 修复 布局变化后 uni-rate 星星计算不准确的 bug
|
||||
- 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖
|
||||
## 1.1.0(2021-04-16)
|
||||
- 修复 uni-rate 属性 margin 值为 string 组件失效的 bug
|
||||
|
||||
## 1.0.9(2021-02-05)
|
||||
- 优化 组件引用关系,通过uni_modules引用组件
|
||||
|
||||
## 1.0.8(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 支持 pc 端
|
||||
361
uni_modules/uni-rate/components/uni-rate/uni-rate.vue
Normal file
@@ -0,0 +1,361 @@
|
||||
<template>
|
||||
<view>
|
||||
<view ref="uni-rate" class="uni-rate">
|
||||
<view class="uni-rate__icon" :class="{'uni-cursor-not-allowed': disabled}"
|
||||
:style="{ 'margin-right': marginNumber + 'px' }" v-for="(star, index) in stars" :key="index"
|
||||
@touchstart.stop="touchstart" @touchmove.stop="touchmove" @mousedown.stop="mousedown"
|
||||
@mousemove.stop="mousemove" @mouseleave="mouseleave">
|
||||
<uni-icons :color="color" :size="size" :type="isFill ? 'star-filled' : 'star'" />
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view :style="{ width: star.activeWitch.replace('%','')*size/100+'px'}" class="uni-rate__icon-on">
|
||||
<uni-icons style="text-align: left;" :color="disabled?'#ccc':activeColor" :size="size"
|
||||
type="star-filled" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view :style="{ width: star.activeWitch}" class="uni-rate__icon-on">
|
||||
<uni-icons :color="disabled?disabledColor:activeColor" :size="size" type="star-filled" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const dom = uni.requireNativePlugin('dom');
|
||||
// #endif
|
||||
/**
|
||||
* Rate 评分
|
||||
* @description 评分组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=33
|
||||
* @property {Boolean} isFill = [true|false] 星星的类型,是否为实心类型, 默认为实心
|
||||
* @property {String} color 未选中状态的星星颜色,默认为 "#ececec"
|
||||
* @property {String} activeColor 选中状态的星星颜色,默认为 "#ffca3e"
|
||||
* @property {String} disabledColor 禁用状态的星星颜色,默认为 "#c0c0c0"
|
||||
* @property {Number} size 星星的大小
|
||||
* @property {Number} value/v-model 当前评分
|
||||
* @property {Number} max 最大评分评分数量,目前一分一颗星
|
||||
* @property {Number} margin 星星的间距,单位 px
|
||||
* @property {Boolean} disabled = [true|false] 是否为禁用状态,默认为 false
|
||||
* @property {Boolean} readonly = [true|false] 是否为只读状态,默认为 false
|
||||
* @property {Boolean} allowHalf = [true|false] 是否实现半星,默认为 false
|
||||
* @property {Boolean} touchable = [true|false] 是否支持滑动手势,默认为 true
|
||||
* @event {Function} change uniRate 的 value 改变时触发事件,e={value:Number}
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "UniRate",
|
||||
props: {
|
||||
isFill: {
|
||||
// 星星的类型,是否镂空
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
color: {
|
||||
// 星星未选中的颜色
|
||||
type: String,
|
||||
default: "#ececec"
|
||||
},
|
||||
activeColor: {
|
||||
// 星星选中状态颜色
|
||||
type: String,
|
||||
default: "#ffca3e"
|
||||
},
|
||||
disabledColor: {
|
||||
// 星星禁用状态颜色
|
||||
type: String,
|
||||
default: "#c0c0c0"
|
||||
},
|
||||
size: {
|
||||
// 星星的大小
|
||||
type: [Number, String],
|
||||
default: 24
|
||||
},
|
||||
value: {
|
||||
// 当前评分
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
modelValue: {
|
||||
// 当前评分
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
max: {
|
||||
// 最大评分
|
||||
type: [Number, String],
|
||||
default: 5
|
||||
},
|
||||
margin: {
|
||||
// 星星的间距
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
disabled: {
|
||||
// 是否可点击
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
// 是否只读
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
allowHalf: {
|
||||
// 是否显示半星
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
touchable: {
|
||||
// 是否支持滑动手势
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
valueSync: "",
|
||||
userMouseFristMove: true,
|
||||
userRated: false,
|
||||
userLastRate: 1
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
this.valueSync = Number(newVal);
|
||||
},
|
||||
modelValue(newVal) {
|
||||
this.valueSync = Number(newVal);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
stars() {
|
||||
const value = this.valueSync ? this.valueSync : 0;
|
||||
const starList = [];
|
||||
const floorValue = Math.floor(value);
|
||||
const ceilValue = Math.ceil(value);
|
||||
for (let i = 0; i < this.max; i++) {
|
||||
if (floorValue > i) {
|
||||
starList.push({
|
||||
activeWitch: "100%"
|
||||
});
|
||||
} else if (ceilValue - 1 === i) {
|
||||
starList.push({
|
||||
activeWitch: (value - floorValue) * 100 + "%"
|
||||
});
|
||||
} else {
|
||||
starList.push({
|
||||
activeWitch: "0"
|
||||
});
|
||||
}
|
||||
}
|
||||
return starList;
|
||||
},
|
||||
|
||||
marginNumber() {
|
||||
return Number(this.margin)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.valueSync = Number(this.value || this.modelValue);
|
||||
this._rateBoxLeft = 0
|
||||
this._oldValue = null
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
this._getSize()
|
||||
}, 100)
|
||||
// #ifdef H5
|
||||
this.PC = this.IsPC()
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
touchstart(e) {
|
||||
// #ifdef H5
|
||||
if (this.IsPC()) return
|
||||
// #endif
|
||||
if (this.readonly || this.disabled) return
|
||||
const {
|
||||
clientX,
|
||||
screenX
|
||||
} = e.changedTouches[0]
|
||||
// TODO 做一下兼容,只有 Nvue 下才有 screenX,其他平台式 clientX
|
||||
this._getRateCount(clientX || screenX)
|
||||
},
|
||||
touchmove(e) {
|
||||
// #ifdef H5
|
||||
if (this.IsPC()) return
|
||||
// #endif
|
||||
if (this.readonly || this.disabled || !this.touchable) return
|
||||
const {
|
||||
clientX,
|
||||
screenX
|
||||
} = e.changedTouches[0]
|
||||
this._getRateCount(clientX || screenX)
|
||||
},
|
||||
|
||||
/**
|
||||
* 兼容 PC @tian
|
||||
*/
|
||||
|
||||
mousedown(e) {
|
||||
// #ifdef H5
|
||||
if (!this.IsPC()) return
|
||||
if (this.readonly || this.disabled) return
|
||||
const {
|
||||
clientX,
|
||||
} = e
|
||||
this.userLastRate = this.valueSync
|
||||
this._getRateCount(clientX)
|
||||
this.userRated = true
|
||||
// #endif
|
||||
},
|
||||
mousemove(e) {
|
||||
// #ifdef H5
|
||||
if (!this.IsPC()) return
|
||||
if (this.userRated) return
|
||||
if (this.userMouseFristMove) {
|
||||
console.log('---mousemove----', this.valueSync);
|
||||
this.userLastRate = this.valueSync
|
||||
this.userMouseFristMove = false
|
||||
}
|
||||
if (this.readonly || this.disabled || !this.touchable) return
|
||||
const {
|
||||
clientX,
|
||||
} = e
|
||||
this._getRateCount(clientX)
|
||||
// #endif
|
||||
},
|
||||
mouseleave(e) {
|
||||
// #ifdef H5
|
||||
if (!this.IsPC()) return
|
||||
if (this.readonly || this.disabled || !this.touchable) return
|
||||
if (this.userRated) {
|
||||
this.userRated = false
|
||||
return
|
||||
}
|
||||
this.valueSync = this.userLastRate
|
||||
// #endif
|
||||
},
|
||||
// #ifdef H5
|
||||
IsPC() {
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
|
||||
var flag = true;
|
||||
for (let v = 0; v < Agents.length - 1; v++) {
|
||||
if (userAgentInfo.indexOf(Agents[v]) > 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
},
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 获取星星个数
|
||||
*/
|
||||
_getRateCount(clientX) {
|
||||
this._getSize()
|
||||
const size = Number(this.size)
|
||||
if (isNaN(size)) {
|
||||
return new Error('size 属性只能设置为数字')
|
||||
}
|
||||
const rateMoveRange = clientX - this._rateBoxLeft
|
||||
let index = parseInt(rateMoveRange / (size + this.marginNumber))
|
||||
index = index < 0 ? 0 : index;
|
||||
index = index > this.max ? this.max : index;
|
||||
const range = parseInt(rateMoveRange - (size + this.marginNumber) * index);
|
||||
let value = 0;
|
||||
if (this._oldValue === index && !this.PC) return;
|
||||
this._oldValue = index;
|
||||
if (this.allowHalf) {
|
||||
if (range > (size / 2)) {
|
||||
value = index + 1
|
||||
} else {
|
||||
value = index + 0.5
|
||||
}
|
||||
} else {
|
||||
value = index + 1
|
||||
}
|
||||
|
||||
value = Math.max(0.5, Math.min(value, this.max))
|
||||
this.valueSync = value
|
||||
this._onChange()
|
||||
},
|
||||
|
||||
/**
|
||||
* 触发动态修改
|
||||
*/
|
||||
_onChange() {
|
||||
|
||||
this.$emit("input", this.valueSync);
|
||||
this.$emit("update:modelValue", this.valueSync);
|
||||
this.$emit("change", {
|
||||
value: this.valueSync
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 获取星星距离屏幕左侧距离
|
||||
*/
|
||||
_getSize() {
|
||||
// #ifndef APP-NVUE
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.uni-rate')
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
if (ret) {
|
||||
this._rateBoxLeft = ret[0].left
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['uni-rate'], (ret) => {
|
||||
const size = ret.size
|
||||
if (size) {
|
||||
this._rateBoxLeft = size.left
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-rate {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
line-height: 1;
|
||||
font-size: 0;
|
||||
flex-direction: row;
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-rate__icon {
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.uni-rate__icon-on {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.uni-cursor-not-allowed {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed !important;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
88
uni_modules/uni-rate/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"id": "uni-rate",
|
||||
"displayName": "uni-rate 评分",
|
||||
"version": "1.3.1",
|
||||
"description": "Rate 评分组件,可自定义评分星星图标的大小、间隔、评分数。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"评分"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-scss",
|
||||
"uni-icons"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
uni_modules/uni-rate/readme.md
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
## Rate 评分
|
||||
> **组件名:uni-rate**
|
||||
> 代码块: `uRate`
|
||||
> 关联组件:`uni-icons`
|
||||
|
||||
|
||||
评分组件,多用于购买商品后,对商品进行评价等场景
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-rate)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
8
uni_modules/uni-scss/changelog.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## 1.0.3(2022-01-21)
|
||||
- 优化 组件示例
|
||||
## 1.0.2(2021-11-22)
|
||||
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
|
||||
## 1.0.1(2021-11-22)
|
||||
- 修复 vue3中scss语法兼容问题
|
||||
## 1.0.0(2021-11-18)
|
||||
- init
|
||||
1
uni_modules/uni-scss/index.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import './styles/index.scss';
|
||||
82
uni_modules/uni-scss/package.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"id": "uni-scss",
|
||||
"displayName": "uni-scss 辅助样式",
|
||||
"version": "1.0.3",
|
||||
"description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。",
|
||||
"keywords": [
|
||||
"uni-scss",
|
||||
"uni-ui",
|
||||
"辅助样式"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"JS SDK",
|
||||
"通用 SDK"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "n",
|
||||
"联盟": "n"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4
uni_modules/uni-scss/readme.md
Normal file
@@ -0,0 +1,4 @@
|
||||
`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
7
uni_modules/uni-scss/styles/index.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
@import './setting/_variables.scss';
|
||||
@import './setting/_border.scss';
|
||||
@import './setting/_color.scss';
|
||||
@import './setting/_space.scss';
|
||||
@import './setting/_radius.scss';
|
||||
@import './setting/_text.scss';
|
||||
@import './setting/_styles.scss';
|
||||
3
uni_modules/uni-scss/styles/setting/_border.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.uni-border {
|
||||
border: 1px $uni-border-1 solid;
|
||||
}
|
||||
66
uni_modules/uni-scss/styles/setting/_color.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
|
||||
// @mixin get-styles($k,$c) {
|
||||
// @if $k == size or $k == weight{
|
||||
// font-#{$k}:#{$c}
|
||||
// }@else{
|
||||
// #{$k}:#{$c}
|
||||
// }
|
||||
// }
|
||||
$uni-ui-color:(
|
||||
// 主色
|
||||
primary: $uni-primary,
|
||||
primary-disable: $uni-primary-disable,
|
||||
primary-light: $uni-primary-light,
|
||||
// 辅助色
|
||||
success: $uni-success,
|
||||
success-disable: $uni-success-disable,
|
||||
success-light: $uni-success-light,
|
||||
warning: $uni-warning,
|
||||
warning-disable: $uni-warning-disable,
|
||||
warning-light: $uni-warning-light,
|
||||
error: $uni-error,
|
||||
error-disable: $uni-error-disable,
|
||||
error-light: $uni-error-light,
|
||||
info: $uni-info,
|
||||
info-disable: $uni-info-disable,
|
||||
info-light: $uni-info-light,
|
||||
// 中性色
|
||||
main-color: $uni-main-color,
|
||||
base-color: $uni-base-color,
|
||||
secondary-color: $uni-secondary-color,
|
||||
extra-color: $uni-extra-color,
|
||||
// 背景色
|
||||
bg-color: $uni-bg-color,
|
||||
// 边框颜色
|
||||
border-1: $uni-border-1,
|
||||
border-2: $uni-border-2,
|
||||
border-3: $uni-border-3,
|
||||
border-4: $uni-border-4,
|
||||
// 黑色
|
||||
black:$uni-black,
|
||||
// 白色
|
||||
white:$uni-white,
|
||||
// 透明
|
||||
transparent:$uni-transparent
|
||||
) !default;
|
||||
@each $key, $child in $uni-ui-color {
|
||||
.uni-#{"" + $key} {
|
||||
color: $child;
|
||||
}
|
||||
.uni-#{"" + $key}-bg {
|
||||
background-color: $child;
|
||||
}
|
||||
}
|
||||
.uni-shadow-sm {
|
||||
box-shadow: $uni-shadow-sm;
|
||||
}
|
||||
.uni-shadow-base {
|
||||
box-shadow: $uni-shadow-base;
|
||||
}
|
||||
.uni-shadow-lg {
|
||||
box-shadow: $uni-shadow-lg;
|
||||
}
|
||||
.uni-mask {
|
||||
background-color:$uni-mask;
|
||||
}
|
||||
55
uni_modules/uni-scss/styles/setting/_radius.scss
Normal file
@@ -0,0 +1,55 @@
|
||||
@mixin radius($r,$d:null ,$important: false){
|
||||
$radius-value:map-get($uni-radius, $r) if($important, !important, null);
|
||||
// Key exists within the $uni-radius variable
|
||||
@if (map-has-key($uni-radius, $r) and $d){
|
||||
@if $d == t {
|
||||
border-top-left-radius:$radius-value;
|
||||
border-top-right-radius:$radius-value;
|
||||
}@else if $d == r {
|
||||
border-top-right-radius:$radius-value;
|
||||
border-bottom-right-radius:$radius-value;
|
||||
}@else if $d == b {
|
||||
border-bottom-left-radius:$radius-value;
|
||||
border-bottom-right-radius:$radius-value;
|
||||
}@else if $d == l {
|
||||
border-top-left-radius:$radius-value;
|
||||
border-bottom-left-radius:$radius-value;
|
||||
}@else if $d == tl {
|
||||
border-top-left-radius:$radius-value;
|
||||
}@else if $d == tr {
|
||||
border-top-right-radius:$radius-value;
|
||||
}@else if $d == br {
|
||||
border-bottom-right-radius:$radius-value;
|
||||
}@else if $d == bl {
|
||||
border-bottom-left-radius:$radius-value;
|
||||
}
|
||||
}@else{
|
||||
border-radius:$radius-value;
|
||||
}
|
||||
}
|
||||
|
||||
@each $key, $child in $uni-radius {
|
||||
@if($key){
|
||||
.uni-radius-#{"" + $key} {
|
||||
@include radius($key)
|
||||
}
|
||||
}@else{
|
||||
.uni-radius {
|
||||
@include radius($key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $direction in t, r, b, l,tl, tr, br, bl {
|
||||
@each $key, $child in $uni-radius {
|
||||
@if($key){
|
||||
.uni-radius-#{"" + $direction}-#{"" + $key} {
|
||||
@include radius($key,$direction,false)
|
||||
}
|
||||
}@else{
|
||||
.uni-radius-#{$direction} {
|
||||
@include radius($key,$direction,false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
uni_modules/uni-scss/styles/setting/_space.scss
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
@mixin fn($space,$direction,$size,$n) {
|
||||
@if $n {
|
||||
#{$space}-#{$direction}: #{$size*$uni-space-root}px
|
||||
} @else {
|
||||
#{$space}-#{$direction}: #{-$size*$uni-space-root}px
|
||||
}
|
||||
}
|
||||
@mixin get-styles($direction,$i,$space,$n){
|
||||
@if $direction == t {
|
||||
@include fn($space, top,$i,$n);
|
||||
}
|
||||
@if $direction == r {
|
||||
@include fn($space, right,$i,$n);
|
||||
}
|
||||
@if $direction == b {
|
||||
@include fn($space, bottom,$i,$n);
|
||||
}
|
||||
@if $direction == l {
|
||||
@include fn($space, left,$i,$n);
|
||||
}
|
||||
@if $direction == x {
|
||||
@include fn($space, left,$i,$n);
|
||||
@include fn($space, right,$i,$n);
|
||||
}
|
||||
@if $direction == y {
|
||||
@include fn($space, top,$i,$n);
|
||||
@include fn($space, bottom,$i,$n);
|
||||
}
|
||||
@if $direction == a {
|
||||
@if $n {
|
||||
#{$space}:#{$i*$uni-space-root}px;
|
||||
} @else {
|
||||
#{$space}:#{-$i*$uni-space-root}px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $orientation in m,p {
|
||||
$space: margin;
|
||||
@if $orientation == m {
|
||||
$space: margin;
|
||||
} @else {
|
||||
$space: padding;
|
||||
}
|
||||
@for $i from 0 through 16 {
|
||||
@each $direction in t, r, b, l, x, y, a {
|
||||
.uni-#{$orientation}#{$direction}-#{$i} {
|
||||
@include get-styles($direction,$i,$space,true);
|
||||
}
|
||||
.uni-#{$orientation}#{$direction}-n#{$i} {
|
||||
@include get-styles($direction,$i,$space,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
uni_modules/uni-scss/styles/setting/_styles.scss
Normal file
@@ -0,0 +1,167 @@
|
||||
/* #ifndef APP-NVUE */
|
||||
|
||||
$-color-white:#fff;
|
||||
$-color-black:#000;
|
||||
@mixin base-style($color) {
|
||||
color: #fff;
|
||||
background-color: $color;
|
||||
border-color: mix($-color-black, $color, 8%);
|
||||
&:not([hover-class]):active {
|
||||
background: mix($-color-black, $color, 10%);
|
||||
border-color: mix($-color-black, $color, 20%);
|
||||
color: $-color-white;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
@mixin is-color($color) {
|
||||
@include base-style($color);
|
||||
&[loading] {
|
||||
@include base-style($color);
|
||||
&::before {
|
||||
margin-right:5px;
|
||||
}
|
||||
}
|
||||
&[disabled] {
|
||||
&,
|
||||
&[loading],
|
||||
&:not([hover-class]):active {
|
||||
color: $-color-white;
|
||||
border-color: mix(darken($color,10%), $-color-white);
|
||||
background-color: mix($color, $-color-white);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@mixin base-plain-style($color) {
|
||||
color:$color;
|
||||
background-color: mix($-color-white, $color, 90%);
|
||||
border-color: mix($-color-white, $color, 70%);
|
||||
&:not([hover-class]):active {
|
||||
background: mix($-color-white, $color, 80%);
|
||||
color: $color;
|
||||
outline: none;
|
||||
border-color: mix($-color-white, $color, 50%);
|
||||
}
|
||||
}
|
||||
@mixin is-plain($color){
|
||||
&[plain] {
|
||||
@include base-plain-style($color);
|
||||
&[loading] {
|
||||
@include base-plain-style($color);
|
||||
&::before {
|
||||
margin-right:5px;
|
||||
}
|
||||
}
|
||||
&[disabled] {
|
||||
&,
|
||||
&:active {
|
||||
color: mix($-color-white, $color, 40%);
|
||||
background-color: mix($-color-white, $color, 90%);
|
||||
border-color: mix($-color-white, $color, 80%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.uni-btn {
|
||||
margin: 5px;
|
||||
color: #393939;
|
||||
border:1px solid #ccc;
|
||||
font-size: 16px;
|
||||
font-weight: 200;
|
||||
background-color: #F9F9F9;
|
||||
// TODO 暂时处理边框隐藏一边的问题
|
||||
overflow: visible;
|
||||
&::after{
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:not([type]),&[type=default] {
|
||||
color: #999;
|
||||
&[loading] {
|
||||
background: none;
|
||||
&::before {
|
||||
margin-right:5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
&[disabled]{
|
||||
color: mix($-color-white, #999, 60%);
|
||||
&,
|
||||
&[loading],
|
||||
&:active {
|
||||
color: mix($-color-white, #999, 60%);
|
||||
background-color: mix($-color-white,$-color-black , 98%);
|
||||
border-color: mix($-color-white, #999, 85%);
|
||||
}
|
||||
}
|
||||
|
||||
&[plain] {
|
||||
color: #999;
|
||||
background: none;
|
||||
border-color: $uni-border-1;
|
||||
&:not([hover-class]):active {
|
||||
background: none;
|
||||
color: mix($-color-white, $-color-black, 80%);
|
||||
border-color: mix($-color-white, $-color-black, 90%);
|
||||
outline: none;
|
||||
}
|
||||
&[disabled]{
|
||||
&,
|
||||
&[loading],
|
||||
&:active {
|
||||
background: none;
|
||||
color: mix($-color-white, #999, 60%);
|
||||
border-color: mix($-color-white, #999, 85%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not([hover-class]):active {
|
||||
color: mix($-color-white, $-color-black, 50%);
|
||||
}
|
||||
|
||||
&[size=mini] {
|
||||
font-size: 16px;
|
||||
font-weight: 200;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
&.uni-btn-small {
|
||||
font-size: 14px;
|
||||
}
|
||||
&.uni-btn-mini {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&.uni-btn-radius {
|
||||
border-radius: 999px;
|
||||
}
|
||||
&[type=primary] {
|
||||
@include is-color($uni-primary);
|
||||
@include is-plain($uni-primary)
|
||||
}
|
||||
&[type=success] {
|
||||
@include is-color($uni-success);
|
||||
@include is-plain($uni-success)
|
||||
}
|
||||
&[type=error] {
|
||||
@include is-color($uni-error);
|
||||
@include is-plain($uni-error)
|
||||
}
|
||||
&[type=warning] {
|
||||
@include is-color($uni-warning);
|
||||
@include is-plain($uni-warning)
|
||||
}
|
||||
&[type=info] {
|
||||
@include is-color($uni-info);
|
||||
@include is-plain($uni-info)
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||