@ -0,0 +1,16 @@ |
|||
###################################################################### |
|||
# Build Tools |
|||
|
|||
/unpackage/* |
|||
/node_modules/* |
|||
|
|||
###################################################################### |
|||
# Development Tools |
|||
|
|||
/.idea/* |
|||
/.vscode/* |
|||
/.hbuilderx/* |
|||
|
|||
package-lock.json |
|||
yarn.lock |
|||
|
@ -0,0 +1,34 @@ |
|||
<script> |
|||
import config from './config' |
|||
import store from '@/store' |
|||
import { getAccessToken } from '@/utils/auth' |
|||
|
|||
export default { |
|||
onLaunch: function() { |
|||
this.initApp() |
|||
}, |
|||
methods: { |
|||
// 初始化应用 |
|||
initApp() { |
|||
// 初始化应用配置 |
|||
this.initConfig() |
|||
// 检查用户登录状态 |
|||
//#ifdef H5 |
|||
this.checkLogin() |
|||
//#endif |
|||
}, |
|||
initConfig() { |
|||
this.globalData.config = config |
|||
}, |
|||
checkLogin() { |
|||
if (!getAccessToken()) { |
|||
this.$tab.reLaunch('/pages/login') |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
@import '@/static/scss/index.scss' |
|||
</style> |
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2022 闻荫 |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,34 @@ |
|||
import request from '@/utils/request' |
|||
|
|||
// 登录方法
|
|||
export function login(username, password, captchaVerification) { |
|||
const data = { |
|||
username, |
|||
password, |
|||
captchaVerification |
|||
} |
|||
return request({ |
|||
url: '/system/auth/login', |
|||
headers: { |
|||
isToken: false |
|||
}, |
|||
'method': 'POST', |
|||
'data': data |
|||
}) |
|||
} |
|||
|
|||
// 获取用户详细信息
|
|||
export function getInfo() { |
|||
return request({ |
|||
url: '/system/auth/get-permission-info', |
|||
'method': 'GET' |
|||
}) |
|||
} |
|||
|
|||
// 退出方法
|
|||
export function logout() { |
|||
return request({ |
|||
url: '/system/auth/logout', |
|||
'method': 'POST' |
|||
}) |
|||
} |
@ -0,0 +1,42 @@ |
|||
import upload from '@/utils/upload' |
|||
import request from '@/utils/request' |
|||
|
|||
// 用户密码重置
|
|||
export function updateUserPwd(oldPassword, newPassword) { |
|||
const data = { |
|||
oldPassword, |
|||
newPassword |
|||
} |
|||
return request({ |
|||
url: '/system/user/profile/update-password', |
|||
method: 'PUT', |
|||
params: data |
|||
}) |
|||
} |
|||
|
|||
// 查询用户个人信息
|
|||
export function getUserProfile() { |
|||
return request({ |
|||
url: '/system/user/profile/get', |
|||
method: 'GET' |
|||
}) |
|||
} |
|||
|
|||
// 修改用户个人信息
|
|||
export function updateUserProfile(data) { |
|||
return request({ |
|||
url: '/system/user/profile/update', |
|||
method: 'PUT', |
|||
data: data |
|||
}) |
|||
} |
|||
|
|||
// 用户头像上传
|
|||
export function uploadAvatar(data) { |
|||
return upload({ |
|||
url: '/system/user/profile/update-avatar', |
|||
method: 'PUT', |
|||
name: data.name, |
|||
filePath: data.filePath |
|||
}) |
|||
} |
@ -0,0 +1,167 @@ |
|||
<template> |
|||
<view class="uni-section"> |
|||
<view class="uni-section-header" @click="onClick"> |
|||
<view class="uni-section-header__decoration" v-if="type" :class="type" /> |
|||
<slot v-else name="decoration"></slot> |
|||
|
|||
<view class="uni-section-header__content"> |
|||
<text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text> |
|||
<text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text> |
|||
</view> |
|||
|
|||
<view class="uni-section-header__slot-right"> |
|||
<slot name="right"></slot> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="uni-section-content" :style="{padding: _padding}"> |
|||
<slot /> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
|
|||
/** |
|||
* Section 标题栏 |
|||
* @description 标题栏 |
|||
* @property {String} type = [line|circle|square] 标题装饰类型 |
|||
* @value line 竖线 |
|||
* @value circle 圆形 |
|||
* @value square 正方形 |
|||
* @property {String} title 主标题 |
|||
* @property {String} titleFontSize 主标题字体大小 |
|||
* @property {String} titleColor 主标题字体颜色 |
|||
* @property {String} subTitle 副标题 |
|||
* @property {String} subTitleFontSize 副标题字体大小 |
|||
* @property {String} subTitleColor 副标题字体颜色 |
|||
* @property {String} padding 默认插槽 padding |
|||
*/ |
|||
|
|||
export default { |
|||
name: 'UniSection', |
|||
emits:['click'], |
|||
props: { |
|||
type: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
required: true, |
|||
default: '' |
|||
}, |
|||
titleFontSize: { |
|||
type: String, |
|||
default: '14px' |
|||
}, |
|||
titleColor:{ |
|||
type: String, |
|||
default: '#333' |
|||
}, |
|||
subTitle: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
subTitleFontSize: { |
|||
type: String, |
|||
default: '12px' |
|||
}, |
|||
subTitleColor: { |
|||
type: String, |
|||
default: '#999' |
|||
}, |
|||
padding: { |
|||
type: [Boolean, String], |
|||
default: false |
|||
} |
|||
}, |
|||
computed:{ |
|||
_padding(){ |
|||
if(typeof this.padding === 'string'){ |
|||
return this.padding |
|||
} |
|||
|
|||
return this.padding?'10px':'' |
|||
} |
|||
}, |
|||
watch: { |
|||
title(newVal) { |
|||
if (uni.report && newVal !== '') { |
|||
uni.report('title', newVal) |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
onClick() { |
|||
this.$emit('click') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" > |
|||
$uni-primary: #2979ff !default; |
|||
|
|||
.uni-section { |
|||
background-color: #fff; |
|||
.uni-section-header { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
align-items: center; |
|||
padding: 12px 10px; |
|||
font-weight: normal; |
|||
|
|||
&__decoration{ |
|||
margin-right: 6px; |
|||
background-color: $uni-primary; |
|||
&.line { |
|||
width: 4px; |
|||
height: 12px; |
|||
border-radius: 10px; |
|||
} |
|||
|
|||
&.circle { |
|||
width: 8px; |
|||
height: 8px; |
|||
border-top-right-radius: 50px; |
|||
border-top-left-radius: 50px; |
|||
border-bottom-left-radius: 50px; |
|||
border-bottom-right-radius: 50px; |
|||
} |
|||
|
|||
&.square { |
|||
width: 8px; |
|||
height: 8px; |
|||
} |
|||
} |
|||
|
|||
&__content { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
flex: 1; |
|||
color: #333; |
|||
|
|||
.distraction { |
|||
flex-direction: row; |
|||
align-items: center; |
|||
} |
|||
&-sub { |
|||
margin-top: 2px; |
|||
} |
|||
} |
|||
|
|||
&__slot-right{ |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
|
|||
.uni-section-content{ |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,14 @@ |
|||
import CryptoJS from 'crypto-js' |
|||
/** |
|||
* @word 要加密的内容 |
|||
* @keyWord String 服务器随机返回的关键字 |
|||
* */ |
|||
export function aesEncrypt(word, keyWord = "XwKsGlMcdPMEhR1B") { |
|||
var key = CryptoJS.enc.Utf8.parse(keyWord); |
|||
var srcs = CryptoJS.enc.Utf8.parse(word); |
|||
var encrypted = CryptoJS.AES.encrypt(srcs, key, { |
|||
mode: CryptoJS.mode.ECB, |
|||
padding: CryptoJS.pad.Pkcs7 |
|||
}); |
|||
return encrypted.toString(); |
|||
} |
@ -0,0 +1,17 @@ |
|||
import config from '@/config' |
|||
const baseUrl = config.baseUrl |
|||
export const myRequest = (option = {}) => { |
|||
return new Promise((reslove, reject) => { |
|||
uni.request({ |
|||
url: baseUrl + option.url, |
|||
data: option.data, |
|||
method: option.method || "GET", |
|||
success: (result) => { |
|||
reslove(result) |
|||
}, |
|||
fail: (error) => { |
|||
reject(error) |
|||
} |
|||
}) |
|||
}) |
|||
} |
@ -0,0 +1,27 @@ |
|||
// 应用全局配置
|
|||
module.exports = { |
|||
// baseUrl: 'http://api-dashboard.win.iocoder.cn',
|
|||
baseUrl: 'http://localhost:48080', |
|||
baseApi: '/admin-api', |
|||
// 应用信息
|
|||
appInfo: { |
|||
// 应用名称
|
|||
name: "win-app", |
|||
// 应用版本
|
|||
version: "1.0.0", |
|||
// 应用logo
|
|||
logo: "/static/logo.png", |
|||
// 官方网站
|
|||
site_url: "https://iocoder.cn", |
|||
// 政策协议
|
|||
agreements: [{ |
|||
title: "隐私政策", |
|||
url: "https://iocoder.cn" |
|||
}, |
|||
{ |
|||
title: "用户服务协议", |
|||
url: "https://iocoder.cn" |
|||
} |
|||
] |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
import Vue from 'vue' |
|||
import App from './App' |
|||
import store from './store' // store
|
|||
import plugins from './plugins' // plugins
|
|||
import './permission' // permission
|
|||
Vue.use(plugins) |
|||
|
|||
Vue.config.productionTip = false |
|||
Vue.prototype.$store = store |
|||
|
|||
App.mpType = 'app' |
|||
|
|||
const app = new Vue({ |
|||
...App |
|||
}) |
|||
|
|||
app.$mount() |
@ -0,0 +1,69 @@ |
|||
{ |
|||
"name" : "闻荫移动端", |
|||
"appid" : "__UNI__25A9D80", |
|||
"description" : "", |
|||
"versionName" : "1.0.0", |
|||
"versionCode" : "100", |
|||
"transformPx" : false, |
|||
"app-plus" : { |
|||
"usingComponents" : true, |
|||
"nvueCompiler" : "uni-app", |
|||
"splashscreen" : { |
|||
"alwaysShowBeforeRender" : true, |
|||
"waiting" : true, |
|||
"autoclose" : true, |
|||
"delay" : 0 |
|||
}, |
|||
"modules" : {}, |
|||
"distribute" : { |
|||
"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" : {}, |
|||
"sdkConfigs" : {} |
|||
} |
|||
}, |
|||
"quickapp" : {}, |
|||
"mp-weixin" : { |
|||
"appid" : "wxccd7e2a0911b3397", |
|||
"setting" : { |
|||
"urlCheck" : false, |
|||
"es6" : false, |
|||
"minified" : true, |
|||
"postcss" : true |
|||
}, |
|||
"optimization" : { |
|||
"subPackages" : true |
|||
}, |
|||
"usingComponents" : true |
|||
}, |
|||
"vueVersion" : "2", |
|||
"h5" : { |
|||
"template" : "static/index.html", |
|||
"devServer" : { |
|||
"port" : 9090, |
|||
"https" : false |
|||
}, |
|||
"title" : "win-App", |
|||
"router" : { |
|||
"mode" : "hash", |
|||
"base" : "./" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"dependencies": { |
|||
"crypto-js": "^4.0.0" |
|||
} |
|||
} |
@ -0,0 +1,97 @@ |
|||
{ |
|||
"pages": [{ |
|||
"path": "pages/login", |
|||
"style": { |
|||
"navigationBarTitleText": "登录" |
|||
} |
|||
}, { |
|||
"path": "pages/index", |
|||
"style": { |
|||
"navigationBarTitleText": "闻荫移动端框架", |
|||
"navigationStyle": "custom" |
|||
} |
|||
}, { |
|||
"path": "pages/work/index", |
|||
"style": { |
|||
"navigationBarTitleText": "工作台" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/index", |
|||
"style": { |
|||
"navigationBarTitleText": "我的" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/avatar/index", |
|||
"style": { |
|||
"navigationBarTitleText": "修改头像" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/info/index", |
|||
"style": { |
|||
"navigationBarTitleText": "个人信息" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/info/edit", |
|||
"style": { |
|||
"navigationBarTitleText": "编辑资料" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/pwd/index", |
|||
"style": { |
|||
"navigationBarTitleText": "修改密码" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/setting/index", |
|||
"style": { |
|||
"navigationBarTitleText": "应用设置" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/help/index", |
|||
"style": { |
|||
"navigationBarTitleText": "常见问题" |
|||
} |
|||
}, { |
|||
"path": "pages/mine/about/index", |
|||
"style": { |
|||
"navigationBarTitleText": "关于我们" |
|||
} |
|||
}, { |
|||
"path": "pages/common/webview/index", |
|||
"style": { |
|||
"navigationBarTitleText": "浏览网页" |
|||
} |
|||
}, { |
|||
"path": "pages/common/textview/index", |
|||
"style": { |
|||
"navigationBarTitleText": "浏览文本" |
|||
} |
|||
}], |
|||
"tabBar": { |
|||
"color": "#000000", |
|||
"selectedColor": "#000000", |
|||
"borderStyle": "white", |
|||
"backgroundColor": "#ffffff", |
|||
"list": [{ |
|||
"pagePath": "pages/index", |
|||
"iconPath": "static/images/tabbar/home.png", |
|||
"selectedIconPath": "static/images/tabbar/home_.png", |
|||
"text": "首页" |
|||
}, { |
|||
"pagePath": "pages/work/index", |
|||
"iconPath": "static/images/tabbar/work.png", |
|||
"selectedIconPath": "static/images/tabbar/work_.png", |
|||
"text": "工作台" |
|||
}, { |
|||
"pagePath": "pages/mine/index", |
|||
"iconPath": "static/images/tabbar/mine.png", |
|||
"selectedIconPath": "static/images/tabbar/mine_.png", |
|||
"text": "我的" |
|||
} |
|||
] |
|||
}, |
|||
"globalStyle": { |
|||
"navigationBarTextStyle": "black", |
|||
"navigationBarTitleText": "RuoYi", |
|||
"navigationBarBackgroundColor": "#FFFFFF" |
|||
} |
|||
} |
@ -0,0 +1,43 @@ |
|||
<template> |
|||
<view> |
|||
<uni-card class="view-title" :title="title"> |
|||
<text class="uni-body view-content">{{ content }}</text> |
|||
</uni-card> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
title: '', |
|||
content: '' |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
this.title = options.title |
|||
this.content = options.content |
|||
uni.setNavigationBarTitle({ |
|||
title: options.title |
|||
}) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
page { |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.view-title { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.view-content { |
|||
font-size: 26rpx; |
|||
padding: 12px 5px 0; |
|||
color: #333; |
|||
line-height: 24px; |
|||
font-weight: normal; |
|||
} |
|||
</style> |
@ -0,0 +1,34 @@ |
|||
<template> |
|||
<view v-if="params.url"> |
|||
<web-view :webview-styles="webviewStyles" :src="`${params.url}`"></web-view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
params: {}, |
|||
webviewStyles: { |
|||
progress: { |
|||
color: "#FF3333" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
props: { |
|||
src: { |
|||
type: [String], |
|||
default: null |
|||
} |
|||
}, |
|||
onLoad(event) { |
|||
this.params = event |
|||
if (event.title) { |
|||
uni.setNavigationBarTitle({ |
|||
title: event.title |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,43 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<image class="logo" src="/static/logo.png"></image> |
|||
<view class="text-area"> |
|||
<text class="title">Hello 闻荫</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
onLoad: function() { |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.content { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.logo { |
|||
height: 200rpx; |
|||
width: 200rpx; |
|||
margin-top: 200rpx; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
margin-bottom: 50rpx; |
|||
} |
|||
|
|||
.text-area { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 36rpx; |
|||
color: #8f8f94; |
|||
} |
|||
</style> |
@ -0,0 +1,168 @@ |
|||
<template> |
|||
<view class="normal-login-container"> |
|||
<view class="logo-content align-center justify-center flex"> |
|||
<image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix"> |
|||
</image> |
|||
<text class="title">闻荫移动端登录</text> |
|||
</view> |
|||
<view class="login-form-content"> |
|||
<view class="input-item flex align-center"> |
|||
<view class="iconfont icon-user icon"></view> |
|||
<input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" /> |
|||
</view> |
|||
<view class="input-item flex align-center"> |
|||
<view class="iconfont icon-password icon"></view> |
|||
<input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" /> |
|||
</view> |
|||
<Verify @success="pwdLogin" :mode="'pop'" :captchaType="'blockPuzzle'" |
|||
:imgSize="{ width: '330px', height: '155px' }" ref="verify"></Verify> |
|||
<view class="action-btn"> |
|||
<button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="xieyi text-center"> |
|||
<text class="text-grey1">登录即代表同意</text> |
|||
<text @click="handleUserAgrement" class="text-blue">《用户协议》</text> |
|||
<text @click="handlePrivacy" class="text-blue">《隐私协议》</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import Verify from "@/components/verifition/Verify" |
|||
|
|||
export default { |
|||
name: 'Login', |
|||
components: { |
|||
Verify |
|||
}, |
|||
data() { |
|||
return { |
|||
captchaEnabled: true, // 验证码开关 TODO 芋艿:需要抽到配置里 |
|||
globalConfig: getApp().globalData.config, |
|||
loginForm: { |
|||
username: "admin", |
|||
password: "admin123", |
|||
captchaVerification: "" |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
// 隐私协议 |
|||
handlePrivacy() { |
|||
let site = this.globalConfig.appInfo.agreements[0] |
|||
this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`) |
|||
}, |
|||
// 用户协议 |
|||
handleUserAgrement() { |
|||
let site = this.globalConfig.appInfo.agreements[1] |
|||
this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`) |
|||
}, |
|||
// 登录方法 |
|||
async handleLogin(params) { |
|||
if (this.loginForm.username === "") { |
|||
this.$modal.msgError("请输入您的账号") |
|||
} else if (this.loginForm.password === "") { |
|||
this.$modal.msgError("请输入您的密码") |
|||
} else { |
|||
// 显示验证码 |
|||
if (this.captchaEnabled) { |
|||
this.$refs.verify.show() |
|||
} else { // 直接登录 |
|||
await this.pwdLogin({}) |
|||
} |
|||
} |
|||
}, |
|||
// 密码登录 |
|||
async pwdLogin(captchaParams) { |
|||
this.$modal.loading("登录中,请耐心等待...") |
|||
// 执行登录 |
|||
this.loginForm.captchaVerification = captchaParams.captchaVerification |
|||
this.$store.dispatch('Login', this.loginForm).then(() => { |
|||
this.$modal.closeLoading() |
|||
this.loginSuccess() |
|||
}) |
|||
}, |
|||
// 登录成功后,处理函数 |
|||
loginSuccess(result) { |
|||
// 设置用户信息 |
|||
this.$store.dispatch('GetInfo').then(res => { |
|||
this.$tab.reLaunch('/pages/index') |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.normal-login-container { |
|||
width: 100%; |
|||
|
|||
.logo-content { |
|||
width: 100%; |
|||
font-size: 21px; |
|||
text-align: center; |
|||
padding-top: 15%; |
|||
|
|||
image { |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.title { |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
|
|||
.login-form-content { |
|||
text-align: center; |
|||
margin: 20px auto; |
|||
margin-top: 15%; |
|||
width: 80%; |
|||
|
|||
.input-item { |
|||
margin: 20px auto; |
|||
background-color: #f5f6f7; |
|||
height: 45px; |
|||
border-radius: 20px; |
|||
|
|||
.icon { |
|||
font-size: 38rpx; |
|||
margin-left: 10px; |
|||
color: #999; |
|||
} |
|||
|
|||
.input { |
|||
width: 100%; |
|||
font-size: 14px; |
|||
line-height: 20px; |
|||
text-align: left; |
|||
padding-left: 15px; |
|||
} |
|||
|
|||
} |
|||
|
|||
.login-btn { |
|||
margin-top: 40px; |
|||
height: 45px; |
|||
} |
|||
|
|||
.xieyi { |
|||
color: #333; |
|||
margin-top: 20px; |
|||
} |
|||
} |
|||
|
|||
.easyinput { |
|||
width: 100%; |
|||
} |
|||
} |
|||
|
|||
.login-code-img { |
|||
height: 45px; |
|||
} |
|||
</style> |
@ -0,0 +1,75 @@ |
|||
<template> |
|||
<view class="about-container"> |
|||
<view class="header-section text-center"> |
|||
<image style="width: 150rpx;height: 150rpx;" src="/static/logo200.png" mode="widthFix"> |
|||
</image> |
|||
<uni-title type="h2" title="闻荫移动端"></uni-title> |
|||
</view> |
|||
|
|||
<view class="content-section"> |
|||
<view class="menu-list"> |
|||
<view class="list-cell list-cell-arrow"> |
|||
<view class="menu-item-box"> |
|||
<view>版本信息</view> |
|||
<view class="text-right">v{{version}}</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow"> |
|||
<view class="menu-item-box"> |
|||
<view>官方邮箱</view> |
|||
<view class="text-right">7685413@qq.com</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow"> |
|||
<view class="menu-item-box"> |
|||
<view>服务热线</view> |
|||
<view class="text-right">400-999-9999</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow"> |
|||
<view class="menu-item-box"> |
|||
<view>公司网站</view> |
|||
<view class="text-right"> |
|||
<uni-link :href="url" :text="url" showUnderLine="false"></uni-link> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="copyright"> |
|||
<view>Copyright © 2022 iocoder.cn All Rights Reserved.</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
url: getApp().globalData.config.appInfo.site_url, |
|||
version: getApp().globalData.config.appInfo.version |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #f8f8f8; |
|||
} |
|||
|
|||
.copyright { |
|||
margin-top: 50rpx; |
|||
text-align: center; |
|||
line-height: 60rpx; |
|||
color: #999; |
|||
} |
|||
|
|||
.header-section { |
|||
display: flex; |
|||
padding: 30rpx 0 0; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
} |
|||
</style> |
@ -0,0 +1,631 @@ |
|||
<template> |
|||
<view class="container"> |
|||
<view class="page-body uni-content-info"> |
|||
<view class='cropper-content'> |
|||
<view v-if="isShowImg" class="uni-corpper" :style="'width:'+cropperInitW+'px;height:'+cropperInitH+'px;background:#000'"> |
|||
<view class="uni-corpper-content" :style="'width:'+cropperW+'px;height:'+cropperH+'px;left:'+cropperL+'px;top:'+cropperT+'px'"> |
|||
<image :src="imageSrc" :style="'width:'+cropperW+'px;height:'+cropperH+'px'"></image> |
|||
<view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove" @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd" |
|||
:style="'left:'+cutL+'px;top:'+cutT+'px;right:'+cutR+'px;bottom:'+cutB+'px'"> |
|||
<view class="uni-cropper-view-box"> |
|||
<view class="uni-cropper-dashed-h"></view> |
|||
<view class="uni-cropper-dashed-v"></view> |
|||
<view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-point point-tr" data-drag="topTight"></view> |
|||
<view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-point point-rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view> |
|||
<view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view> |
|||
<view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view> |
|||
<view class="uni-cropper-point point-lt" data-drag="leftTop"></view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class='cropper-config'> |
|||
<button type="primary reverse" @click="getImage" style='margin-top: 30rpx;'> 选择头像 </button> |
|||
<button type="warn" @click="getImageInfo" style='margin-top: 30rpx;'> 提交 </button> |
|||
</view> |
|||
<canvas canvas-id="myCanvas" :style="'position:absolute;border: 1px solid red; width:'+imageW+'px;height:'+imageH+'px;top:-9999px;left:-9999px;'"></canvas> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import config from '@/config' |
|||
import store from "@/store" |
|||
import { uploadAvatar } from "@/api/system/user" |
|||
|
|||
const baseUrl = config.baseUrl |
|||
let sysInfo = uni.getSystemInfoSync() |
|||
let SCREEN_WIDTH = sysInfo.screenWidth |
|||
let PAGE_X, // 手按下的x位置 |
|||
PAGE_Y, // 手按下y的位置 |
|||
PR = sysInfo.pixelRatio, // dpi |
|||
T_PAGE_X, // 手移动的时候x的位置 |
|||
T_PAGE_Y, // 手移动的时候Y的位置 |
|||
CUT_L, // 初始化拖拽元素的left值 |
|||
CUT_T, // 初始化拖拽元素的top值 |
|||
CUT_R, // 初始化拖拽元素的 |
|||
CUT_B, // 初始化拖拽元素的 |
|||
CUT_W, // 初始化拖拽元素的宽度 |
|||
CUT_H, // 初始化拖拽元素的高度 |
|||
IMG_RATIO, // 图片比例 |
|||
IMG_REAL_W, // 图片实际的宽度 |
|||
IMG_REAL_H, // 图片实际的高度 |
|||
DRAFG_MOVE_RATIO = 1, //移动时候的比例, |
|||
INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度 |
|||
DRAW_IMAGE_W = sysInfo.screenWidth // 设置生成的图片宽度 |
|||
|
|||
export default { |
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data() { |
|||
return { |
|||
imageSrc: store.getters.avatar, |
|||
isShowImg: false, |
|||
// 初始化的宽高 |
|||
cropperInitW: SCREEN_WIDTH, |
|||
cropperInitH: SCREEN_WIDTH, |
|||
// 动态的宽高 |
|||
cropperW: SCREEN_WIDTH, |
|||
cropperH: SCREEN_WIDTH, |
|||
// 动态的left top值 |
|||
cropperL: 0, |
|||
cropperT: 0, |
|||
|
|||
transL: 0, |
|||
transT: 0, |
|||
|
|||
// 图片缩放值 |
|||
scaleP: 0, |
|||
imageW: 0, |
|||
imageH: 0, |
|||
|
|||
// 裁剪框 宽高 |
|||
cutL: 0, |
|||
cutT: 0, |
|||
cutB: SCREEN_WIDTH, |
|||
cutR: '100%', |
|||
qualityWidth: DRAW_IMAGE_W, |
|||
innerAspectRadio: DRAFG_MOVE_RATIO |
|||
} |
|||
}, |
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady: function () { |
|||
this.loadImage() |
|||
}, |
|||
methods: { |
|||
setData: function (obj) { |
|||
let that = this |
|||
Object.keys(obj).forEach(function (key) { |
|||
that.$set(that.$data, key, obj[key]) |
|||
}) |
|||
}, |
|||
getImage: function () { |
|||
var _this = this |
|||
uni.chooseImage({ |
|||
success: function (res) { |
|||
_this.setData({ |
|||
imageSrc: res.tempFilePaths[0], |
|||
}) |
|||
_this.loadImage() |
|||
}, |
|||
}) |
|||
}, |
|||
loadImage: function () { |
|||
var _this = this |
|||
|
|||
uni.getImageInfo({ |
|||
src: _this.imageSrc, |
|||
success: function success(res) { |
|||
IMG_RATIO = 1 / 1 |
|||
if (IMG_RATIO >= 1) { |
|||
IMG_REAL_W = SCREEN_WIDTH |
|||
IMG_REAL_H = SCREEN_WIDTH / IMG_RATIO |
|||
} else { |
|||
IMG_REAL_W = SCREEN_WIDTH * IMG_RATIO |
|||
IMG_REAL_H = SCREEN_WIDTH |
|||
} |
|||
let minRange = IMG_REAL_W > IMG_REAL_H ? IMG_REAL_W : IMG_REAL_H |
|||
INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange |
|||
// 根据图片的宽高显示不同的效果 保证图片可以正常显示 |
|||
if (IMG_RATIO >= 1) { |
|||
let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2) |
|||
let cutB = cutT |
|||
let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2) |
|||
let cutR = cutL |
|||
_this.setData({ |
|||
cropperW: SCREEN_WIDTH, |
|||
cropperH: SCREEN_WIDTH / IMG_RATIO, |
|||
// 初始化left right |
|||
cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2), |
|||
cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH / IMG_RATIO) / 2), |
|||
cutL: cutL, |
|||
cutT: cutT, |
|||
cutR: cutR, |
|||
cutB: cutB, |
|||
// 图片缩放值 |
|||
imageW: IMG_REAL_W, |
|||
imageH: IMG_REAL_H, |
|||
scaleP: IMG_REAL_W / SCREEN_WIDTH, |
|||
qualityWidth: DRAW_IMAGE_W, |
|||
innerAspectRadio: IMG_RATIO |
|||
}) |
|||
} else { |
|||
let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - (SCREEN_WIDTH * IMG_RATIO)) / 2) |
|||
let cutR = cutL |
|||
let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2) |
|||
let cutB = cutT |
|||
_this.setData({ |
|||
cropperW: SCREEN_WIDTH * IMG_RATIO, |
|||
cropperH: SCREEN_WIDTH, |
|||
// 初始化left right |
|||
cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH * IMG_RATIO) / 2), |
|||
cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2), |
|||
|
|||
cutL: cutL, |
|||
cutT: cutT, |
|||
cutR: cutR, |
|||
cutB: cutB, |
|||
// 图片缩放值 |
|||
imageW: IMG_REAL_W, |
|||
imageH: IMG_REAL_H, |
|||
scaleP: IMG_REAL_W / SCREEN_WIDTH, |
|||
qualityWidth: DRAW_IMAGE_W, |
|||
innerAspectRadio: IMG_RATIO |
|||
}) |
|||
} |
|||
_this.setData({ |
|||
isShowImg: true |
|||
}) |
|||
uni.hideLoading() |
|||
} |
|||
}) |
|||
}, |
|||
// 拖动时候触发的touchStart事件 |
|||
contentStartMove(e) { |
|||
PAGE_X = e.touches[0].pageX |
|||
PAGE_Y = e.touches[0].pageY |
|||
}, |
|||
|
|||
// 拖动时候触发的touchMove事件 |
|||
contentMoveing(e) { |
|||
var _this = this |
|||
var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO |
|||
var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO |
|||
// 左移 |
|||
if (dragLengthX > 0) { |
|||
if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL |
|||
} else { |
|||
if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR |
|||
} |
|||
|
|||
if (dragLengthY > 0) { |
|||
if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT |
|||
} else { |
|||
if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB |
|||
} |
|||
this.setData({ |
|||
cutL: this.cutL - dragLengthX, |
|||
cutT: this.cutT - dragLengthY, |
|||
cutR: this.cutR + dragLengthX, |
|||
cutB: this.cutB + dragLengthY |
|||
}) |
|||
|
|||
PAGE_X = e.touches[0].pageX |
|||
PAGE_Y = e.touches[0].pageY |
|||
}, |
|||
|
|||
contentTouchEnd() { |
|||
|
|||
}, |
|||
|
|||
// 获取图片 |
|||
getImageInfo() { |
|||
var _this = this |
|||
uni.showLoading({ |
|||
title: '图片生成中...', |
|||
}) |
|||
// 将图片写入画布 |
|||
const ctx = uni.createCanvasContext('myCanvas') |
|||
ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H) |
|||
ctx.draw(true, () => { |
|||
// 获取画布要裁剪的位置和宽度 均为百分比 * 画布中图片的宽度 保证了在微信小程序中裁剪的图片模糊 位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio) |
|||
var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W |
|||
var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H |
|||
var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W |
|||
var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H |
|||
uni.canvasToTempFilePath({ |
|||
x: canvasL, |
|||
y: canvasT, |
|||
width: canvasW, |
|||
height: canvasH, |
|||
destWidth: canvasW, |
|||
destHeight: canvasH, |
|||
quality: 0.5, |
|||
canvasId: 'myCanvas', |
|||
success: function (res) { |
|||
uni.hideLoading() |
|||
let data = {name: 'avatarFile', filePath: res.tempFilePath} |
|||
uploadAvatar(data).then(response => { |
|||
store.commit('SET_AVATAR', response.data) |
|||
uni.showToast({ title: "修改成功", icon: 'success' }) |
|||
uni.navigateBack() |
|||
}) |
|||
} |
|||
}) |
|||
}) |
|||
}, |
|||
// 设置大小的时候触发的touchStart事件 |
|||
dragStart(e) { |
|||
T_PAGE_X = e.touches[0].pageX |
|||
T_PAGE_Y = e.touches[0].pageY |
|||
CUT_L = this.cutL |
|||
CUT_R = this.cutR |
|||
CUT_B = this.cutB |
|||
CUT_T = this.cutT |
|||
}, |
|||
|
|||
// 设置大小的时候触发的touchMove事件 |
|||
dragMove(e) { |
|||
var _this = this |
|||
var dragType = e.target.dataset.drag |
|||
switch (dragType) { |
|||
case 'right': |
|||
var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO |
|||
if (CUT_R + dragLength < 0) dragLength = -CUT_R |
|||
this.setData({ |
|||
cutR: CUT_R + dragLength |
|||
}) |
|||
break |
|||
case 'left': |
|||
var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO |
|||
if (CUT_L - dragLength < 0) dragLength = CUT_L |
|||
if ((CUT_L - dragLength) > (this.cropperW - this.cutR)) dragLength = CUT_L - (this.cropperW - this.cutR) |
|||
this.setData({ |
|||
cutL: CUT_L - dragLength |
|||
}) |
|||
break |
|||
case 'top': |
|||
var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO |
|||
if (CUT_T - dragLength < 0) dragLength = CUT_T |
|||
if ((CUT_T - dragLength) > (this.cropperH - this.cutB)) dragLength = CUT_T - (this.cropperH - this.cutB) |
|||
this.setData({ |
|||
cutT: CUT_T - dragLength |
|||
}) |
|||
break |
|||
case 'bottom': |
|||
var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO |
|||
if (CUT_B + dragLength < 0) dragLength = -CUT_B |
|||
this.setData({ |
|||
cutB: CUT_B + dragLength |
|||
}) |
|||
break |
|||
case 'rightBottom': |
|||
var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO |
|||
var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO |
|||
|
|||
if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B |
|||
if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R |
|||
let cutB = CUT_B + dragLengthY |
|||
let cutR = CUT_R + dragLengthX |
|||
|
|||
this.setData({ |
|||
cutB: cutB, |
|||
cutR: cutR |
|||
}) |
|||
break |
|||
default: |
|||
break |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
/* pages/uni-cropper/index.wxss */ |
|||
|
|||
.uni-content-info { |
|||
/* position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
display: block; |
|||
align-items: center; |
|||
flex-direction: column; */ |
|||
} |
|||
|
|||
.cropper-config { |
|||
padding: 20rpx 40rpx; |
|||
} |
|||
|
|||
.cropper-content { |
|||
min-height: 750rpx; |
|||
width: 100%; |
|||
} |
|||
|
|||
.uni-corpper { |
|||
position: relative; |
|||
overflow: hidden; |
|||
-webkit-user-select: none; |
|||
-moz-user-select: none; |
|||
-ms-user-select: none; |
|||
user-select: none; |
|||
-webkit-tap-highlight-color: transparent; |
|||
-webkit-touch-callout: none; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.uni-corpper-content { |
|||
position: relative; |
|||
} |
|||
|
|||
.uni-corpper-content image { |
|||
display: block; |
|||
width: 100%; |
|||
min-width: 0 !important; |
|||
max-width: none !important; |
|||
height: 100%; |
|||
min-height: 0 !important; |
|||
max-height: none !important; |
|||
image-orientation: 0deg !important; |
|||
margin: 0 auto; |
|||
} |
|||
/* 移动图片效果 */ |
|||
|
|||
.uni-cropper-drag-box { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
cursor: move; |
|||
background: rgba(0, 0, 0, 0.6); |
|||
z-index: 1; |
|||
} |
|||
/* 内部的信息 */ |
|||
|
|||
.uni-corpper-crop-box { |
|||
position: absolute; |
|||
background: rgba(255, 255, 255, 0.3); |
|||
z-index: 2; |
|||
} |
|||
|
|||
.uni-corpper-crop-box .uni-cropper-view-box { |
|||
position: relative; |
|||
display: block; |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow: visible; |
|||
outline: 1rpx solid #69f; |
|||
outline-color: rgba(102, 153, 255, .75) |
|||
} |
|||
/* 横向虚线 */ |
|||
|
|||
.uni-cropper-dashed-h { |
|||
position: absolute; |
|||
top: 33.33333333%; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 33.33333333%; |
|||
border-top: 1rpx dashed rgba(255, 255, 255, 0.5); |
|||
border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5); |
|||
} |
|||
/* 纵向虚线 */ |
|||
|
|||
.uni-cropper-dashed-v { |
|||
position: absolute; |
|||
left: 33.33333333%; |
|||
top: 0; |
|||
width: 33.33333333%; |
|||
height: 100%; |
|||
border-left: 1rpx dashed rgba(255, 255, 255, 0.5); |
|||
border-right: 1rpx dashed rgba(255, 255, 255, 0.5); |
|||
} |
|||
/* 四个方向的线 为了之后的拖动事件*/ |
|||
|
|||
.uni-cropper-line-t { |
|||
position: absolute; |
|||
display: block; |
|||
width: 100%; |
|||
background-color: #69f; |
|||
top: 0; |
|||
left: 0; |
|||
height: 1rpx; |
|||
opacity: 0.1; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.uni-cropper-line-t::before { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 50%; |
|||
right: 0rpx; |
|||
width: 100%; |
|||
-webkit-transform: translate3d(0, -50%, 0); |
|||
transform: translate3d(0, -50%, 0); |
|||
bottom: 0; |
|||
height: 41rpx; |
|||
background: transparent; |
|||
z-index: 11; |
|||
} |
|||
|
|||
.uni-cropper-line-r { |
|||
position: absolute; |
|||
display: block; |
|||
background-color: #69f; |
|||
top: 0; |
|||
right: 0rpx; |
|||
width: 1rpx; |
|||
opacity: 0.1; |
|||
height: 100%; |
|||
cursor: e-resize; |
|||
} |
|||
|
|||
.uni-cropper-line-r::before { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 50%; |
|||
width: 41rpx; |
|||
-webkit-transform: translate3d(-50%, 0, 0); |
|||
transform: translate3d(-50%, 0, 0); |
|||
bottom: 0; |
|||
height: 100%; |
|||
background: transparent; |
|||
z-index: 11; |
|||
} |
|||
|
|||
.uni-cropper-line-b { |
|||
position: absolute; |
|||
display: block; |
|||
width: 100%; |
|||
background-color: #69f; |
|||
bottom: 0; |
|||
left: 0; |
|||
height: 1rpx; |
|||
opacity: 0.1; |
|||
cursor: s-resize; |
|||
} |
|||
|
|||
.uni-cropper-line-b::before { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 50%; |
|||
right: 0rpx; |
|||
width: 100%; |
|||
-webkit-transform: translate3d(0, -50%, 0); |
|||
transform: translate3d(0, -50%, 0); |
|||
bottom: 0; |
|||
height: 41rpx; |
|||
background: transparent; |
|||
z-index: 11; |
|||
} |
|||
|
|||
.uni-cropper-line-l { |
|||
position: absolute; |
|||
display: block; |
|||
background-color: #69f; |
|||
top: 0; |
|||
left: 0; |
|||
width: 1rpx; |
|||
opacity: 0.1; |
|||
height: 100%; |
|||
cursor: w-resize; |
|||
} |
|||
|
|||
.uni-cropper-line-l::before { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 50%; |
|||
width: 41rpx; |
|||
-webkit-transform: translate3d(-50%, 0, 0); |
|||
transform: translate3d(-50%, 0, 0); |
|||
bottom: 0; |
|||
height: 100%; |
|||
background: transparent; |
|||
z-index: 11; |
|||
} |
|||
|
|||
.uni-cropper-point { |
|||
width: 5rpx; |
|||
height: 5rpx; |
|||
background-color: #69f; |
|||
opacity: .75; |
|||
position: absolute; |
|||
z-index: 3; |
|||
} |
|||
|
|||
.point-t { |
|||
top: -3rpx; |
|||
left: 50%; |
|||
margin-left: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-tr { |
|||
top: -3rpx; |
|||
left: 100%; |
|||
margin-left: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-r { |
|||
top: 50%; |
|||
left: 100%; |
|||
margin-left: -3rpx; |
|||
margin-top: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-rb { |
|||
left: 100%; |
|||
top: 100%; |
|||
-webkit-transform: translate3d(-50%, -50%, 0); |
|||
transform: translate3d(-50%, -50%, 0); |
|||
cursor: n-resize; |
|||
width: 36rpx; |
|||
height: 36rpx; |
|||
background-color: #69f; |
|||
position: absolute; |
|||
z-index: 1112; |
|||
opacity: 1; |
|||
} |
|||
|
|||
.point-b { |
|||
left: 50%; |
|||
top: 100%; |
|||
margin-left: -3rpx; |
|||
margin-top: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-bl { |
|||
left: 0%; |
|||
top: 100%; |
|||
margin-left: -3rpx; |
|||
margin-top: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-l { |
|||
left: 0%; |
|||
top: 50%; |
|||
margin-left: -3rpx; |
|||
margin-top: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
|
|||
.point-lt { |
|||
left: 0%; |
|||
top: 0%; |
|||
margin-left: -3rpx; |
|||
margin-top: -3rpx; |
|||
cursor: n-resize; |
|||
} |
|||
/* 裁剪框预览内容 */ |
|||
|
|||
.uni-cropper-viewer { |
|||
position: relative; |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.uni-cropper-viewer image { |
|||
position: absolute; |
|||
z-index: 2; |
|||
} |
|||
</style> |
@ -0,0 +1,112 @@ |
|||
<template> |
|||
<view class="help-container"> |
|||
<view v-for="(item, findex) in list" :key="findex" :title="item.title" class="list-title"> |
|||
<view class="text-title"> |
|||
<view :class="item.icon"></view>{{ item.title }} |
|||
</view> |
|||
<view class="childList"> |
|||
<view v-for="(child, zindex) in item.childList" :key="zindex" class="question" hover-class="hover" |
|||
@click="handleText(child)"> |
|||
<view class="text-item">{{ child.title }}</view> |
|||
<view class="line" v-if="zindex !== item.childList.length - 1"></view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
list: [{ |
|||
icon: 'iconfont icon-github', |
|||
title: '闻荫问题', |
|||
childList: [{ |
|||
title: '闻荫开源吗?', |
|||
content: '开源' |
|||
}, { |
|||
title: '闻荫可以商用吗?', |
|||
content: '可以' |
|||
}, { |
|||
title: '闻荫官网地址多少?', |
|||
content: 'https://www.iocoder.cn' |
|||
}, { |
|||
title: '闻荫文档地址多少?', |
|||
content: 'https://doc.iocoder.cn' |
|||
}] |
|||
}, |
|||
{ |
|||
icon: 'iconfont icon-help', |
|||
title: '其他问题', |
|||
childList: [{ |
|||
title: '如何退出登录?', |
|||
content: '请点击[我的] - [应用设置] - [退出登录]即可退出登录', |
|||
}, { |
|||
title: '如何修改用户头像?', |
|||
content: '请点击[我的] - [选择头像] - [点击提交]即可更换用户头像', |
|||
}, { |
|||
title: '如何修改登录密码?', |
|||
content: '请点击[我的] - [应用设置] - [修改密码]即可修改登录密码', |
|||
}] |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
methods: { |
|||
handleText(item) { |
|||
this.$tab.navigateTo(`/pages/common/textview/index?title=${item.title}&content=${item.content}`) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
page { |
|||
background-color: #f8f8f8; |
|||
} |
|||
|
|||
.help-container { |
|||
margin-bottom: 100rpx; |
|||
padding: 30rpx; |
|||
} |
|||
|
|||
.list-title { |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.childList { |
|||
background: #ffffff; |
|||
box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2); |
|||
border-radius: 16rpx; |
|||
margin-top: 10rpx; |
|||
} |
|||
|
|||
.line { |
|||
width: 100%; |
|||
height: 1rpx; |
|||
background-color: #F5F5F5; |
|||
} |
|||
|
|||
.text-title { |
|||
color: #303133; |
|||
font-size: 32rpx; |
|||
font-weight: bold; |
|||
margin-left: 10rpx; |
|||
|
|||
.iconfont { |
|||
font-size: 16px; |
|||
margin-right: 10rpx; |
|||
} |
|||
} |
|||
|
|||
.text-item { |
|||
font-size: 28rpx; |
|||
padding: 24rpx; |
|||
} |
|||
|
|||
.question { |
|||
color: #606266; |
|||
font-size: 28rpx; |
|||
} |
|||
</style> |
@ -0,0 +1,198 @@ |
|||
<template> |
|||
<view class="mine-container" :style="{height: `${windowHeight}px`}"> |
|||
<!--顶部个人信息栏--> |
|||
<view class="header-section"> |
|||
<view class="flex padding justify-between"> |
|||
<view class="flex align-center"> |
|||
<view v-if="!avatar" class="cu-avatar xl round bg-white"> |
|||
<view class="iconfont icon-people text-gray icon"></view> |
|||
</view> |
|||
<image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="widthFix"> |
|||
</image> |
|||
<view v-if="!name" @click="handleToLogin" class="login-tip"> |
|||
点击登录 |
|||
</view> |
|||
<view v-if="name" @click="handleToInfo" class="user-info"> |
|||
<view class="u_title"> |
|||
用户名:{{ name }} |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view @click="handleToInfo" class="flex align-center"> |
|||
<text>个人信息</text> |
|||
<view class="iconfont icon-right"></view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="content-section"> |
|||
<view class="mine-actions grid col-4 text-center"> |
|||
<view class="action-item" @click="handleJiaoLiuQun"> |
|||
<view class="iconfont icon-friendfill text-pink icon"></view> |
|||
<text class="text">交流群</text> |
|||
</view> |
|||
<view class="action-item" @click="handleBuilding"> |
|||
<view class="iconfont icon-service text-blue icon"></view> |
|||
<text class="text">在线客服</text> |
|||
</view> |
|||
<view class="action-item" @click="handleBuilding"> |
|||
<view class="iconfont icon-community text-mauve icon"></view> |
|||
<text class="text">反馈社区</text> |
|||
</view> |
|||
<view class="action-item" @click="handleBuilding"> |
|||
<view class="iconfont icon-dianzan text-green icon"></view> |
|||
<text class="text">点赞我们</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="menu-list"> |
|||
<view class="list-cell list-cell-arrow" @click="handleToEditInfo"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-user menu-icon"></view> |
|||
<view>编辑资料</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow" @click="handleHelp"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-help menu-icon"></view> |
|||
<view>常见问题</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow" @click="handleAbout"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-aixin menu-icon"></view> |
|||
<view>关于我们</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow" @click="handleToSetting"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-setting menu-icon"></view> |
|||
<view>应用设置</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import storage from '@/utils/storage' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
name: this.$store.state.user.name, |
|||
version: getApp().globalData.config.appInfo.version |
|||
} |
|||
}, |
|||
computed: { |
|||
avatar() { |
|||
return this.$store.state.user.avatar |
|||
}, |
|||
windowHeight() { |
|||
return uni.getSystemInfoSync().windowHeight - 50 |
|||
} |
|||
}, |
|||
methods: { |
|||
handleToInfo() { |
|||
this.$tab.navigateTo('/pages/mine/info/index') |
|||
}, |
|||
handleToEditInfo() { |
|||
this.$tab.navigateTo('/pages/mine/info/edit') |
|||
}, |
|||
handleToSetting() { |
|||
this.$tab.navigateTo('/pages/mine/setting/index') |
|||
}, |
|||
handleToLogin() { |
|||
this.$tab.reLaunch('/pages/login') |
|||
}, |
|||
handleToAvatar() { |
|||
this.$tab.navigateTo('/pages/mine/avatar/index') |
|||
}, |
|||
handleLogout() { |
|||
this.$modal.confirm('确定注销并退出系统吗?').then(() => { |
|||
this.$store.dispatch('LogOut').then(() => { |
|||
this.$tab.reLaunch('/pages/index') |
|||
}) |
|||
}) |
|||
}, |
|||
handleHelp() { |
|||
this.$tab.navigateTo('/pages/mine/help/index') |
|||
}, |
|||
handleAbout() { |
|||
this.$tab.navigateTo('/pages/mine/about/index') |
|||
}, |
|||
handleJiaoLiuQun() { |
|||
this.$modal.showToast('微信搜索 naidaguo 后,添加好友后拉你进技术交流群') |
|||
}, |
|||
handleBuilding() { |
|||
this.$modal.showToast('模块建设中~') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #f5f6f7; |
|||
} |
|||
|
|||
.mine-container { |
|||
width: 100%; |
|||
height: 100%; |
|||
|
|||
|
|||
.header-section { |
|||
padding: 15px 15px 45px 15px; |
|||
background-color: #3c96f3; |
|||
color: white; |
|||
|
|||
.login-tip { |
|||
font-size: 18px; |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.cu-avatar { |
|||
border: 2px solid #eaeaea; |
|||
|
|||
.icon { |
|||
font-size: 40px; |
|||
} |
|||
} |
|||
|
|||
.user-info { |
|||
margin-left: 15px; |
|||
|
|||
.u_title { |
|||
font-size: 18px; |
|||
line-height: 30px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.content-section { |
|||
position: relative; |
|||
top: -50px; |
|||
|
|||
.mine-actions { |
|||
margin: 15px 15px; |
|||
padding: 20px 0px; |
|||
border-radius: 8px; |
|||
background-color: white; |
|||
|
|||
.action-item { |
|||
.icon { |
|||
font-size: 28px; |
|||
} |
|||
|
|||
.text { |
|||
display: block; |
|||
font-size: 13px; |
|||
margin: 8px 0px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,128 @@ |
|||
<template> |
|||
<view class="container"> |
|||
<view class="example"> |
|||
<uni-forms ref="form" :model="user" labelWidth="80px"> |
|||
<uni-forms-item label="用户昵称" name="nickname"> |
|||
<uni-easyinput v-model="user.nickname" placeholder="请输入昵称" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="手机号码" name="mobile"> |
|||
<uni-easyinput v-model="user.mobile" placeholder="请输入手机号码" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item label="邮箱" name="email"> |
|||
<uni-easyinput v-model="user.email" placeholder="请输入邮箱" /> |
|||
</uni-forms-item> |
|||
<!-- TODO 芋艿:uni-data-checkbox 存在问题 --> |
|||
<uni-forms-item label="性别" name="sex" required> |
|||
<!-- <uni-data-checkbox v-model="user.sex" :localdata="sexs" />--> |
|||
</uni-forms-item> |
|||
</uni-forms> |
|||
<button type="primary" @click="submit">提交</button> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { getUserProfile } from "@/api/system/user" |
|||
import { updateUserProfile } from "@/api/system/user" |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
user: { |
|||
nickname: "", |
|||
mobile: "", |
|||
email: "", |
|||
sex: "" |
|||
}, |
|||
sexs: [{ |
|||
text: '男', |
|||
value: "1" |
|||
}, { |
|||
text: '女', |
|||
value: "2" |
|||
}], |
|||
rules: { |
|||
nickname: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '用户昵称不能为空' |
|||
}] |
|||
}, |
|||
mobile: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '手机号码不能为空' |
|||
}, { |
|||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, |
|||
errorMessage: '请输入正确的手机号码' |
|||
}] |
|||
}, |
|||
email: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '邮箱地址不能为空' |
|||
}, { |
|||
format: 'email', |
|||
errorMessage: '请输入正确的邮箱地址' |
|||
}] |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
onLoad() { |
|||
this.getUser() |
|||
}, |
|||
onReady() { |
|||
this.$refs.form.setRules(this.rules) |
|||
}, |
|||
methods: { |
|||
getUser() { |
|||
getUserProfile().then(response => { |
|||
this.user = response.data |
|||
}) |
|||
}, |
|||
submit(ref) { |
|||
this.$refs.form.validate().then(res => { |
|||
updateUserProfile(this.user).then(response => { |
|||
this.$modal.msgSuccess("修改成功") |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.example { |
|||
padding: 15px; |
|||
background-color: #fff; |
|||
} |
|||
|
|||
.segmented-control { |
|||
margin-bottom: 15px; |
|||
} |
|||
|
|||
.button-group { |
|||
margin-top: 15px; |
|||
display: flex; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.form-item { |
|||
display: flex; |
|||
align-items: center; |
|||
flex: 1; |
|||
} |
|||
|
|||
.button { |
|||
display: flex; |
|||
align-items: center; |
|||
height: 35px; |
|||
line-height: 35px; |
|||
margin-left: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,44 @@ |
|||
<template> |
|||
<view class="container"> |
|||
<uni-list> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'person-filled'}" title="昵称" :rightText="user.nickname" /> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'phone-filled'}" title="手机号码" :rightText="user.mobile" /> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'email-filled'}" title="邮箱" :rightText="user.email" /> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'auth-filled'}" title="岗位" :rightText="(user.posts || []).map(post => post.name).join(',')" /> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'staff-filled'}" title="角色" :rightText="(user.roles || []).map(role => role.name).join(',')" /> |
|||
<uni-list-item showExtraIcon="true" :extraIcon="{type: 'calendar-filled'}" title="创建日期" :rightText="this.parseTime(user.createTime)" /> |
|||
</uni-list> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { getUserProfile } from "@/api/system/user" |
|||
import { parseTime } from "@/utils/ruoyi" |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
user: {} |
|||
} |
|||
}, |
|||
onLoad() { |
|||
this.getUser() |
|||
}, |
|||
methods: { |
|||
getUser() { |
|||
getUserProfile().then(response => { |
|||
this.user = response.data |
|||
}) |
|||
}, |
|||
parseTime(time) { |
|||
return parseTime(time) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #ffffff; |
|||
} |
|||
</style> |
@ -0,0 +1,85 @@ |
|||
<template> |
|||
<view class="pwd-retrieve-container"> |
|||
<uni-forms ref="form" :value="user" labelWidth="80px"> |
|||
<uni-forms-item name="oldPassword" label="旧密码"> |
|||
<uni-easyinput type="password" v-model="user.oldPassword" placeholder="请输入旧密码" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item name="newPassword" label="新密码"> |
|||
<uni-easyinput type="password" v-model="user.newPassword" placeholder="请输入新密码" /> |
|||
</uni-forms-item> |
|||
<uni-forms-item name="confirmPassword" label="确认密码"> |
|||
<uni-easyinput type="password" v-model="user.confirmPassword" placeholder="请确认新密码" /> |
|||
</uni-forms-item> |
|||
<button type="primary" @click="submit">提交</button> |
|||
</uni-forms> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { updateUserPwd } from "@/api/system/user" |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
user: { |
|||
oldPassword: undefined, |
|||
newPassword: undefined, |
|||
confirmPassword: undefined |
|||
}, |
|||
rules: { |
|||
oldPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '旧密码不能为空' |
|||
}] |
|||
}, |
|||
newPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '新密码不能为空', |
|||
}, |
|||
{ |
|||
minLength: 6, |
|||
maxLength: 20, |
|||
errorMessage: '长度在 6 到 20 个字符' |
|||
} |
|||
] |
|||
}, |
|||
confirmPassword: { |
|||
rules: [{ |
|||
required: true, |
|||
errorMessage: '确认密码不能为空' |
|||
}, { |
|||
validateFunction: (rule, value, data) => data.newPassword === value, |
|||
errorMessage: '两次输入的密码不一致' |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
onReady() { |
|||
this.$refs.form.setRules(this.rules) |
|||
}, |
|||
methods: { |
|||
submit() { |
|||
this.$refs.form.validate().then(res => { |
|||
updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => { |
|||
this.$modal.msgSuccess("修改成功") |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
page { |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.pwd-retrieve-container { |
|||
padding-top: 36rpx; |
|||
padding: 15px; |
|||
} |
|||
</style> |
@ -0,0 +1,78 @@ |
|||
<template> |
|||
<view class="setting-container" :style="{height: `${windowHeight}px`}"> |
|||
<view class="menu-list"> |
|||
<view class="list-cell list-cell-arrow" @click="handleToPwd"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-password menu-icon"></view> |
|||
<view>修改密码</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow" @click="handleToUpgrade"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-refresh menu-icon"></view> |
|||
<view>检查更新</view> |
|||
</view> |
|||
</view> |
|||
<view class="list-cell list-cell-arrow" @click="handleCleanTmp"> |
|||
<view class="menu-item-box"> |
|||
<view class="iconfont icon-clean menu-icon"></view> |
|||
<view>清理缓存</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="cu-list menu"> |
|||
<view class="cu-item item-box"> |
|||
<view class="content text-center" @click="handleLogout"> |
|||
<text class="text-black">退出登录</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
windowHeight: uni.getSystemInfoSync().windowHeight |
|||
} |
|||
}, |
|||
methods: { |
|||
handleToPwd() { |
|||
this.$tab.navigateTo('/pages/mine/pwd/index') |
|||
}, |
|||
handleToUpgrade() { |
|||
this.$modal.showToast('模块建设中~') |
|||
}, |
|||
handleCleanTmp() { |
|||
this.$modal.showToast('模块建设中~') |
|||
}, |
|||
handleLogout() { |
|||
this.$modal.confirm('确定注销并退出系统吗?').then(() => { |
|||
this.$store.dispatch('LogOut').then(() => { |
|||
this.$tab.reLaunch('/pages/index') |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.page { |
|||
background-color: #f8f8f8; |
|||
} |
|||
|
|||
.item-box { |
|||
background-color: #FFFFFF; |
|||
margin: 30rpx; |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: center; |
|||
align-items: center; |
|||
padding: 10rpx; |
|||
border-radius: 8rpx; |
|||
color: #303133; |
|||
font-size: 32rpx; |
|||
} |
|||
</style> |
@ -0,0 +1,183 @@ |
|||
<template> |
|||
<view class="work-container"> |
|||
<!-- 轮播图 --> |
|||
<uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content"> |
|||
<swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper"> |
|||
<swiper-item v-for="(item, index) in data" :key="index"> |
|||
<view class="swiper-item" @click="clickBannerItem(item)"> |
|||
<image :src="item.image" mode="aspectFill" :draggable="false" /> |
|||
</view> |
|||
</swiper-item> |
|||
</swiper> |
|||
</uni-swiper-dot> |
|||
|
|||
<!-- 宫格组件 --> |
|||
<uni-section title="系统管理" type="line"></uni-section> |
|||
<view class="grid-body"> |
|||
<uni-grid :column="4" :showBorder="false" @change="changeGrid"> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="person-filled" size="30"></uni-icons> |
|||
<text class="text">用户管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="staff-filled" size="30"></uni-icons> |
|||
<text class="text">角色管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="color" size="30"></uni-icons> |
|||
<text class="text">菜单管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="settings-filled" size="30"></uni-icons> |
|||
<text class="text">部门管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="heart-filled" size="30"></uni-icons> |
|||
<text class="text">岗位管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="bars" size="30"></uni-icons> |
|||
<text class="text">字典管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="gear-filled" size="30"></uni-icons> |
|||
<text class="text">参数设置</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="chat-filled" size="30"></uni-icons> |
|||
<text class="text">通知公告</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
<uni-grid-item> |
|||
<view class="grid-item-box"> |
|||
<uni-icons type="wallet-filled" size="30"></uni-icons> |
|||
<text class="text">日志管理</text> |
|||
</view> |
|||
</uni-grid-item> |
|||
</uni-grid> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
current: 0, |
|||
swiperDotIndex: 0, |
|||
data: [{ |
|||
image: '/static/images/banner/banner01.jpg' |
|||
}, |
|||
{ |
|||
image: '/static/images/banner/banner02.jpg' |
|||
}, |
|||
{ |
|||
image: '/static/images/banner/banner03.jpg' |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
methods: { |
|||
clickBannerItem(item) { |
|||
console.info(item) |
|||
}, |
|||
changeSwiper(e) { |
|||
this.current = e.detail.current |
|||
}, |
|||
changeGrid(e) { |
|||
this.$modal.showToast('模块建设中~') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
/* #ifndef APP-NVUE */ |
|||
page { |
|||
display: flex; |
|||
flex-direction: column; |
|||
box-sizing: border-box; |
|||
background-color: #fff; |
|||
min-height: 100%; |
|||
height: auto; |
|||
} |
|||
|
|||
view { |
|||
font-size: 14px; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
/* #endif */ |
|||
|
|||
.text { |
|||
text-align: center; |
|||
font-size: 26rpx; |
|||
margin-top: 10rpx; |
|||
} |
|||
|
|||
.grid-item-box { |
|||
flex: 1; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 15px 0; |
|||
} |
|||
|
|||
.uni-margin-wrap { |
|||
width: 690rpx; |
|||
width: 100%; |
|||
; |
|||
} |
|||
|
|||
.swiper { |
|||
height: 300rpx; |
|||
} |
|||
|
|||
.swiper-box { |
|||
height: 150px; |
|||
} |
|||
|
|||
.swiper-item { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
color: #fff; |
|||
height: 300rpx; |
|||
line-height: 300rpx; |
|||
} |
|||
|
|||
@media screen and (min-width: 500px) { |
|||
.uni-swiper-dot-box { |
|||
width: 400px; |
|||
/* #ifndef APP-NVUE */ |
|||
margin: 0 auto; |
|||
/* #endif */ |
|||
margin-top: 8px; |
|||
} |
|||
|
|||
.image { |
|||
width: 100%; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,39 @@ |
|||
import { getAccessToken } from '@/utils/auth' |
|||
|
|||
// 登录页面
|
|||
const loginPage = "/pages/login" |
|||
|
|||
// 页面白名单
|
|||
const whiteList = [ |
|||
'/pages/login', '/pages/common/webview/index' |
|||
] |
|||
|
|||
// 检查地址白名单
|
|||
function checkWhite(url) { |
|||
const path = url.split('?')[0] |
|||
return whiteList.indexOf(path) !== -1 |
|||
} |
|||
|
|||
// 页面跳转验证拦截器
|
|||
let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"] |
|||
list.forEach(item => { |
|||
uni.addInterceptor(item, { |
|||
invoke(to) { |
|||
if (getAccessToken()) { |
|||
if (to.path === loginPage) { |
|||
uni.reLaunch({ url: "/" }) |
|||
} |
|||
return true |
|||
} else { |
|||
if (checkWhite(to.url)) { |
|||
return true |
|||
} |
|||
uni.reLaunch({ url: loginPage }) |
|||
return false |
|||
} |
|||
}, |
|||
fail(err) { |
|||
console.log(err) |
|||
} |
|||
}) |
|||
}) |
@ -0,0 +1,60 @@ |
|||
import store from '@/store' |
|||
|
|||
function authPermission(permission) { |
|||
const all_permission = "*:*:*" |
|||
const permissions = store.getters && store.getters.permissions |
|||
if (permission && permission.length > 0) { |
|||
return permissions.some(v => { |
|||
return all_permission === v || v === permission |
|||
}) |
|||
} else { |
|||
return false |
|||
} |
|||
} |
|||
|
|||
function authRole(role) { |
|||
const super_admin = "admin" |
|||
const roles = store.getters && store.getters.roles |
|||
if (role && role.length > 0) { |
|||
return roles.some(v => { |
|||
return super_admin === v || v === role |
|||
}) |
|||
} else { |
|||
return false |
|||
} |
|||
} |
|||
|
|||
export default { |
|||
// 验证用户是否具备某权限
|
|||
hasPermi(permission) { |
|||
return authPermission(permission) |
|||
}, |
|||
// 验证用户是否含有指定权限,只需包含其中一个
|
|||
hasPermiOr(permissions) { |
|||
return permissions.some(item => { |
|||
return authPermission(item) |
|||
}) |
|||
}, |
|||
// 验证用户是否含有指定权限,必须全部拥有
|
|||
hasPermiAnd(permissions) { |
|||
return permissions.every(item => { |
|||
return authPermission(item) |
|||
}) |
|||
}, |
|||
// 验证用户是否具备某角色
|
|||
hasRole(role) { |
|||
return authRole(role) |
|||
}, |
|||
// 验证用户是否含有指定角色,只需包含其中一个
|
|||
hasRoleOr(roles) { |
|||
return roles.some(item => { |
|||
return authRole(item) |
|||
}) |
|||
}, |
|||
// 验证用户是否含有指定角色,必须全部拥有
|
|||
hasRoleAnd(roles) { |
|||
return roles.every(item => { |
|||
return authRole(item) |
|||
}) |
|||
} |
|||
} |
@ -0,0 +1,14 @@ |
|||
import tab from './tab' |
|||
import auth from './auth' |
|||
import modal from './modal' |
|||
|
|||
export default { |
|||
install(Vue) { |
|||
// 页签操作
|
|||
Vue.prototype.$tab = tab |
|||
// 认证对象
|
|||
Vue.prototype.$auth = auth |
|||
// 模态框对象
|
|||
Vue.prototype.$modal = modal |
|||
} |
|||
} |
@ -0,0 +1,74 @@ |
|||
export default { |
|||
// 消息提示
|
|||
msg(content) { |
|||
uni.showToast({ |
|||
title: content, |
|||
icon: 'none' |
|||
}) |
|||
}, |
|||
// 错误消息
|
|||
msgError(content) { |
|||
uni.showToast({ |
|||
title: content, |
|||
icon: 'error' |
|||
}) |
|||
}, |
|||
// 成功消息
|
|||
msgSuccess(content) { |
|||
uni.showToast({ |
|||
title: content, |
|||
icon: 'success' |
|||
}) |
|||
}, |
|||
// 隐藏消息
|
|||
hideMsg(content) { |
|||
uni.hideToast() |
|||
}, |
|||
// 弹出提示
|
|||
alert(content) { |
|||
uni.showModal({ |
|||
title: '提示', |
|||
content: content, |
|||
showCancel: false |
|||
}) |
|||
}, |
|||
// 确认窗体
|
|||
confirm(content) { |
|||
return new Promise((resolve, reject) => { |
|||
uni.showModal({ |
|||
title: '系统提示', |
|||
content: content, |
|||
cancelText: '取消', |
|||
confirmText: '确定', |
|||
success: function(res) { |
|||
if (res.confirm) { |
|||
resolve(res.confirm) |
|||
} |
|||
} |
|||
}) |
|||
}) |
|||
}, |
|||
// 提示信息
|
|||
showToast(option) { |
|||
if (typeof option === "object") { |
|||
uni.showToast(option) |
|||
} else { |
|||
uni.showToast({ |
|||
title: option, |
|||
icon: "none", |
|||
duration: 2500 |
|||
}) |
|||
} |
|||
}, |
|||
// 打开遮罩层
|
|||
loading(content) { |
|||
uni.showLoading({ |
|||
title: content, |
|||
icon: 'none' |
|||
}) |
|||
}, |
|||
// 关闭遮罩层
|
|||
closeLoading() { |
|||
uni.hideLoading() |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
export default { |
|||
// 关闭所有页面,打开到应用内的某个页面
|
|||
reLaunch(url) { |
|||
return uni.reLaunch({ |
|||
url: url |
|||
}) |
|||
}, |
|||
// 跳转到tabBar页面,并关闭其他所有非tabBar页面
|
|||
switchTab(url) { |
|||
return uni.switchTab({ |
|||
url: url |
|||
}) |
|||
}, |
|||
// 关闭当前页面,跳转到应用内的某个页面
|
|||
redirectTo(url) { |
|||
return uni.redirectTo({ |
|||
url: url |
|||
}) |
|||
}, |
|||
// 保留当前页面,跳转到应用内的某个页面
|
|||
navigateTo(url) { |
|||
return uni.navigateTo({ |
|||
url: url |
|||
}) |
|||
}, |
|||
// 关闭当前页面,返回上一页面或多级页面
|
|||
navigateBack() { |
|||
return uni.navigateBack() |
|||
} |
|||
} |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,90 @@ |
|||
@font-face { |
|||
font-family: "iconfont"; |
|||
src: url('/static/font/iconfont.ttf') format('truetype'); |
|||
} |
|||
|
|||
.iconfont { |
|||
font-family: "iconfont" !important; |
|||
font-size: 16px; |
|||
display: inline-block; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
.icon-user:before { |
|||
content: "\e7ae"; |
|||
} |
|||
|
|||
.icon-password:before { |
|||
content: "\e8b2"; |
|||
} |
|||
|
|||
.icon-code:before { |
|||
content: "\e699"; |
|||
} |
|||
|
|||
.icon-setting:before { |
|||
content: "\e6cc"; |
|||
} |
|||
|
|||
.icon-share:before { |
|||
content: "\e739"; |
|||
} |
|||
|
|||
.icon-edit:before { |
|||
content: "\e60c"; |
|||
} |
|||
|
|||
.icon-version:before { |
|||
content: "\e63f"; |
|||
} |
|||
|
|||
.icon-service:before { |
|||
content: "\e6ff"; |
|||
} |
|||
|
|||
.icon-friendfill:before { |
|||
content: "\e726"; |
|||
} |
|||
|
|||
.icon-community:before { |
|||
content: "\e741"; |
|||
} |
|||
|
|||
.icon-people:before { |
|||
content: "\e736"; |
|||
} |
|||
|
|||
.icon-dianzan:before { |
|||
content: "\ec7f"; |
|||
} |
|||
|
|||
.icon-right:before { |
|||
content: "\e7eb"; |
|||
} |
|||
|
|||
.icon-logout:before { |
|||
content: "\e61d"; |
|||
} |
|||
|
|||
.icon-help:before { |
|||
content: "\e616"; |
|||
} |
|||
|
|||
.icon-github:before { |
|||
content: "\e628"; |
|||
} |
|||
|
|||
.icon-aixin:before { |
|||
content: "\e601"; |
|||
} |
|||
|
|||
.icon-clean:before { |
|||
content: "\e607"; |
|||
} |
|||
|
|||
.icon-refresh:before { |
|||
content: "\e604"; |
|||
} |
|||
|
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
@ -0,0 +1,20 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="zh-CN"> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
|||
<meta name="renderer" content="webkit"> |
|||
<title><%= htmlWebpackPlugin.options.title %></title> |
|||
<link rel="shortcut icon" type="image/x-icon" href="<%= BASE_URL %>static/favicon.ico"> |
|||
<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> |
|||
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" /> |
|||
</head> |
|||
<body> |
|||
<noscript> |
|||
<strong>本站点必须要开启JavaScript才能运行.</strong> |
|||
</noscript> |
|||
<div id="app"></div> |
|||
</html> |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 7.8 KiB |
@ -0,0 +1,90 @@ |
|||
.text-center { |
|||
text-align: center; |
|||
} |
|||
|
|||
.font-13 { |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.font-12 { |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.font-11 { |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.text-grey1 { |
|||
color: #888; |
|||
} |
|||
.text-grey2 { |
|||
color: #aaa; |
|||
} |
|||
|
|||
.list-cell-arrow::before { |
|||
content: ' '; |
|||
height: 10px; |
|||
width: 10px; |
|||
border-width: 2px 2px 0 0; |
|||
border-color: #c0c0c0; |
|||
border-style: solid; |
|||
-webkit-transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); |
|||
transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0); |
|||
position: absolute; |
|||
top: 50%; |
|||
margin-top: -6px; |
|||
right: 30rpx; |
|||
} |
|||
|
|||
.list-cell { |
|||
position: relative; |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
background-color: #fff; |
|||
color: #333; |
|||
padding: 26rpx 30rpx; |
|||
} |
|||
|
|||
.list-cell:first-child { |
|||
border-radius: 8rpx 8rpx 0 0; |
|||
} |
|||
|
|||
.list-cell:last-child { |
|||
border-radius: 0 0 8rpx 8rpx; |
|||
} |
|||
|
|||
.list-cell::after { |
|||
content: ''; |
|||
position: absolute; |
|||
border-bottom: 1px solid #eaeef1; |
|||
-webkit-transform: scaleY(0.5) translateZ(0); |
|||
transform: scaleY(0.5) translateZ(0); |
|||
transform-origin: 0 100%; |
|||
bottom: 0; |
|||
right: 0; |
|||
left: 0; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
|
|||
.menu-list { |
|||
margin: 15px 15px; |
|||
|
|||
.menu-item-box { |
|||
width: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
|
|||
.menu-icon { |
|||
color: #007AFF; |
|||
font-size: 16px; |
|||
margin-right: 5px; |
|||
} |
|||
|
|||
.text-right { |
|||
margin-left: auto; |
|||
margin-right: 34rpx; |
|||
color: #999; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
// global |
|||
@import "./global.scss"; |
|||
// color-ui |
|||
@import "@/static/scss/colorui.css"; |
|||
// iconfont |
|||
@import "@/static/font/iconfont.css"; |
@ -0,0 +1,8 @@ |
|||
const getters = { |
|||
token: state => state.user.token, |
|||
avatar: state => state.user.avatar, |
|||
name: state => state.user.name, |
|||
roles: state => state.user.roles, |
|||
permissions: state => state.user.permissions |
|||
} |
|||
export default getters |
@ -0,0 +1,15 @@ |
|||
import Vue from 'vue' |
|||
import Vuex from 'vuex' |
|||
import user from '@/store/modules/user' |
|||
import getters from './getters' |
|||
|
|||
Vue.use(Vuex) |
|||
|
|||
const store = new Vuex.Store({ |
|||
modules: { |
|||
user |
|||
}, |
|||
getters |
|||
}) |
|||
|
|||
export default store |
@ -0,0 +1,98 @@ |
|||
import config from '@/config' |
|||
import storage from '@/utils/storage' |
|||
import constant from '@/utils/constant' |
|||
import { login, logout, getInfo } from '@/api/login' |
|||
import { setToken, removeToken } from '@/utils/auth' |
|||
|
|||
const baseUrl = config.baseUrl |
|||
|
|||
const user = { |
|||
state: { |
|||
id: 0, // 用户编号
|
|||
name: storage.get(constant.name), |
|||
avatar: storage.get(constant.avatar), |
|||
roles: storage.get(constant.roles), |
|||
permissions: storage.get(constant.permissions) |
|||
}, |
|||
|
|||
mutations: { |
|||
SET_ID: (state, id) => { |
|||
state.id = id |
|||
}, |
|||
SET_NAME: (state, name) => { |
|||
state.name = name |
|||
storage.set(constant.name, name) |
|||
}, |
|||
SET_AVATAR: (state, avatar) => { |
|||
state.avatar = avatar |
|||
storage.set(constant.avatar, avatar) |
|||
}, |
|||
SET_ROLES: (state, roles) => { |
|||
state.roles = roles |
|||
storage.set(constant.roles, roles) |
|||
}, |
|||
SET_PERMISSIONS: (state, permissions) => { |
|||
state.permissions = permissions |
|||
storage.set(constant.permissions, permissions) |
|||
} |
|||
}, |
|||
|
|||
actions: { |
|||
// 登录
|
|||
Login({ commit }, userInfo) { |
|||
const username = userInfo.username.trim() |
|||
const password = userInfo.password |
|||
const captchaVerification = userInfo.captchaVerification |
|||
return new Promise((resolve, reject) => { |
|||
login(username, password, captchaVerification).then(res => { |
|||
res = res.data; |
|||
// 设置 token
|
|||
setToken(res) |
|||
resolve() |
|||
}).catch(error => { |
|||
reject(error) |
|||
}) |
|||
}) |
|||
}, |
|||
|
|||
// 获取用户信息
|
|||
GetInfo({ commit, state }) { |
|||
return new Promise((resolve, reject) => { |
|||
getInfo().then(res => { |
|||
res = res.data; // 读取 data 数据
|
|||
const user = res.user |
|||
const avatar = (user == null || user.avatar === "" || user.avatar == null) ? require("@/static/images/profile.jpg") : user.avatar |
|||
const nickname = (user == null || user.nickname === "" || user.nickname == null) ? "" : user.nickname |
|||
if (res.roles && res.roles.length > 0) { |
|||
commit('SET_ROLES', res.roles) |
|||
commit('SET_PERMISSIONS', res.permissions) |
|||
} else { |
|||
commit('SET_ROLES', ['ROLE_DEFAULT']) |
|||
} |
|||
commit('SET_NAME', nickname) |
|||
commit('SET_AVATAR', avatar) |
|||
resolve(res) |
|||
}).catch(error => { |
|||
reject(error) |
|||
}) |
|||
}) |
|||
}, |
|||
|
|||
// 退出系统
|
|||
LogOut({ commit, state }) { |
|||
return new Promise((resolve, reject) => { |
|||
logout(state.token).then(() => { |
|||
commit('SET_ROLES', []) |
|||
commit('SET_PERMISSIONS', []) |
|||
removeToken() |
|||
storage.clean() |
|||
resolve() |
|||
}).catch(error => { |
|||
reject(error) |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
|
|||
export default user |
@ -0,0 +1,64 @@ |
|||
/** |
|||
* uni-app内置的常用样式变量 |
|||
*/ |
|||
|
|||
/* 行为相关颜色 */ |
|||
$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:#e5e5e5; |
|||
|
|||
/* 尺寸变量 */ |
|||
|
|||
/* 文字尺寸 */ |
|||
$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; |
@ -0,0 +1,29 @@ |
|||
## 1.2.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-badge](https://uniapp.dcloud.io/component/uniui/uni-badge) |
|||
## 1.1.7(2021-11-08) |
|||
- 优化 升级ui |
|||
- 修改 size 属性默认值调整为 small |
|||
- 修改 type 属性,默认值调整为 error,info 替换 default |
|||
## 1.1.6(2021-09-22) |
|||
- 修复 在字节小程序上样式不生效的 bug |
|||
## 1.1.5(2021-07-30) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 1.1.4(2021-07-29) |
|||
- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性 |
|||
## 1.1.3(2021-06-24) |
|||
- 优化 示例项目 |
|||
## 1.1.1(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 1.1.0(2021-05-12) |
|||
- 新增 uni-badge 的 absolute 属性,支持定位 |
|||
- 新增 uni-badge 的 offset 属性,支持定位偏移 |
|||
- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点 |
|||
- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+ |
|||
- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式 |
|||
## 1.0.7(2021-05-07) |
|||
- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug |
|||
- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug |
|||
- 新增 uni-badge 属性 custom-style, 支持自定义样式 |
|||
## 1.0.6(2021-02-04) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,268 @@ |
|||
<template> |
|||
<view class="uni-badge--x"> |
|||
<slot /> |
|||
<text v-if="text" :class="classNames" :style="[badgeWidth, positionStyle, customStyle, dotStyle]" |
|||
class="uni-badge" @click="onClick()">{{displayValue}}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
/** |
|||
* Badge 数字角标 |
|||
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21 |
|||
* @property {String} text 角标内容 |
|||
* @property {String} size = [normal|small] 角标内容 |
|||
* @property {String} type = [info|primary|success|warning|error] 颜色类型 |
|||
* @value info 灰色 |
|||
* @value primary 蓝色 |
|||
* @value success 绿色 |
|||
* @value warning 黄色 |
|||
* @value error 红色 |
|||
* @property {String} inverted = [true|false] 是否无需背景颜色 |
|||
* @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+ |
|||
* @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上 |
|||
* @value rightTop 右上 |
|||
* @value rightBottom 右下 |
|||
* @value leftTop 左上 |
|||
* @value leftBottom 左下 |
|||
* @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px |
|||
* @property {String} isDot = [true|false] 是否显示为一个小点 |
|||
* @event {Function} click 点击 Badge 触发事件 |
|||
* @example <uni-badge text="1"></uni-badge> |
|||
*/ |
|||
|
|||
export default { |
|||
name: 'UniBadge', |
|||
emits: ['click'], |
|||
props: { |
|||
type: { |
|||
type: String, |
|||
default: 'error' |
|||
}, |
|||
inverted: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
isDot: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
maxNum: { |
|||
type: Number, |
|||
default: 99 |
|||
}, |
|||
absolute: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
offset: { |
|||
type: Array, |
|||
default () { |
|||
return [0, 0] |
|||
} |
|||
}, |
|||
text: { |
|||
type: [String, Number], |
|||
default: '' |
|||
}, |
|||
size: { |
|||
type: String, |
|||
default: 'small' |
|||
}, |
|||
customStyle: { |
|||
type: Object, |
|||
default () { |
|||
return {} |
|||
} |
|||
} |
|||
}, |
|||
data() { |
|||
return {}; |
|||
}, |
|||
computed: { |
|||
width() { |
|||
return String(this.text).length * 8 + 12 |
|||
}, |
|||
classNames() { |
|||
const { |
|||
inverted, |
|||
type, |
|||
size, |
|||
absolute |
|||
} = this |
|||
return [ |
|||
inverted ? 'uni-badge--' + type + '-inverted' : '', |
|||
'uni-badge--' + type, |
|||
'uni-badge--' + size, |
|||
absolute ? 'uni-badge--absolute' : '' |
|||
].join(' ') |
|||
}, |
|||
positionStyle() { |
|||
if (!this.absolute) return {} |
|||
let w = this.width / 2, |
|||
h = 10 |
|||
if (this.isDot) { |
|||
w = 5 |
|||
h = 5 |
|||
} |
|||
const x = `${- w + this.offset[0]}px` |
|||
const y = `${- h + this.offset[1]}px` |
|||
|
|||
const whiteList = { |
|||
rightTop: { |
|||
right: x, |
|||
top: y |
|||
}, |
|||
rightBottom: { |
|||
right: x, |
|||
bottom: y |
|||
}, |
|||
leftBottom: { |
|||
left: x, |
|||
bottom: y |
|||
}, |
|||
leftTop: { |
|||
left: x, |
|||
top: y |
|||
} |
|||
} |
|||
const match = whiteList[this.absolute] |
|||
return match ? match : whiteList['rightTop'] |
|||
}, |
|||
badgeWidth() { |
|||
return { |
|||
width: `${this.width}px` |
|||
} |
|||
}, |
|||
dotStyle() { |
|||
if (!this.isDot) return {} |
|||
return { |
|||
width: '10px', |
|||
height: '10px', |
|||
borderRadius: '10px' |
|||
} |
|||
}, |
|||
displayValue() { |
|||
const { |
|||
isDot, |
|||
text, |
|||
maxNum |
|||
} = this |
|||
return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text) |
|||
} |
|||
}, |
|||
methods: { |
|||
onClick() { |
|||
this.$emit('click'); |
|||
} |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" > |
|||
$uni-primary: #2979ff !default; |
|||
$uni-success: #4cd964 !default; |
|||
$uni-warning: #f0ad4e !default; |
|||
$uni-error: #dd524d !default; |
|||
$uni-info: #909399 !default; |
|||
|
|||
|
|||
$bage-size: 12px; |
|||
$bage-small: scale(0.8); |
|||
|
|||
.uni-badge--x { |
|||
/* #ifdef APP-NVUE */ |
|||
// align-self: flex-start; |
|||
/* #endif */ |
|||
/* #ifndef APP-NVUE */ |
|||
display: inline-block; |
|||
/* #endif */ |
|||
position: relative; |
|||
} |
|||
|
|||
.uni-badge--absolute { |
|||
position: absolute; |
|||
} |
|||
|
|||
.uni-badge--small { |
|||
transform: $bage-small; |
|||
transform-origin: center center; |
|||
} |
|||
|
|||
.uni-badge { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
overflow: hidden; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
justify-content: center; |
|||
flex-direction: row; |
|||
height: 20px; |
|||
line-height: 18px; |
|||
color: #fff; |
|||
border-radius: 100px; |
|||
background-color: $uni-info; |
|||
background-color: transparent; |
|||
border: 1px solid #fff; |
|||
text-align: center; |
|||
font-family: 'Helvetica Neue', Helvetica, sans-serif; |
|||
font-size: $bage-size; |
|||
/* #ifdef H5 */ |
|||
z-index: 999; |
|||
cursor: pointer; |
|||
/* #endif */ |
|||
|
|||
&--info { |
|||
color: #fff; |
|||
background-color: $uni-info; |
|||
} |
|||
|
|||
&--primary { |
|||
background-color: $uni-primary; |
|||
} |
|||
|
|||
&--success { |
|||
background-color: $uni-success; |
|||
} |
|||
|
|||
&--warning { |
|||
background-color: $uni-warning; |
|||
} |
|||
|
|||
&--error { |
|||
background-color: $uni-error; |
|||
} |
|||
|
|||
&--inverted { |
|||
padding: 0 5px 0 0; |
|||
color: $uni-info; |
|||
} |
|||
|
|||
&--info-inverted { |
|||
color: $uni-info; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
&--primary-inverted { |
|||
color: $uni-primary; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
&--success-inverted { |
|||
color: $uni-success; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
&--warning-inverted { |
|||
color: $uni-warning; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
&--error-inverted { |
|||
color: $uni-error; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,88 @@ |
|||
{ |
|||
"id": "uni-badge", |
|||
"displayName": "uni-badge 数字角标", |
|||
"version": "1.2.0", |
|||
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", |
|||
"keywords": [ |
|||
"", |
|||
"badge", |
|||
"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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,10 @@ |
|||
## Badge 数字角标 |
|||
> **组件名:uni-badge** |
|||
> 代码块: `uBadge` |
|||
|
|||
数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景, |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
|||
|
|||
|
@ -0,0 +1,6 @@ |
|||
## 0.1.2(2022-06-08) |
|||
- 修复 微信小程序 separator 不显示问题 |
|||
## 0.1.1(2022-06-02) |
|||
- 新增 支持 uni.scss 修改颜色 |
|||
## 0.1.0(2022-04-21) |
|||
- 初始化 |
@ -0,0 +1,121 @@ |
|||
<template> |
|||
<view class="uni-breadcrumb-item"> |
|||
<view :class="{ |
|||
'uni-breadcrumb-item--slot': true, |
|||
'uni-breadcrumb-item--slot-link': to && currentPage !== to |
|||
}" @click="navTo"> |
|||
<slot /> |
|||
</view> |
|||
<i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" /> |
|||
<text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
/** |
|||
* BreadcrumbItem 面包屑导航子组件 |
|||
* @property {String/Object} to 路由跳转页面路径/对象 |
|||
* @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) |
|||
*/ |
|||
export default { |
|||
data() { |
|||
return { |
|||
currentPage: "" |
|||
} |
|||
}, |
|||
options: { |
|||
virtualHost: true |
|||
}, |
|||
props: { |
|||
to: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
replace:{ |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
inject: { |
|||
uniBreadcrumb: { |
|||
from: "uniBreadcrumb", |
|||
default: null |
|||
} |
|||
}, |
|||
created(){ |
|||
const pages = getCurrentPages() |
|||
const page = pages[pages.length-1] |
|||
|
|||
if(page){ |
|||
this.currentPage = `/${page.route}` |
|||
} |
|||
}, |
|||
computed: { |
|||
separator() { |
|||
return this.uniBreadcrumb.separator |
|||
}, |
|||
separatorClass() { |
|||
return this.uniBreadcrumb.separatorClass |
|||
} |
|||
}, |
|||
methods: { |
|||
navTo() { |
|||
const { to } = this |
|||
|
|||
if (!to || this.currentPage === to){ |
|||
return |
|||
} |
|||
|
|||
if(this.replace){ |
|||
uni.redirectTo({ |
|||
url:to |
|||
}) |
|||
}else{ |
|||
uni.navigateTo({ |
|||
url:to |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
$uni-primary: #2979ff !default; |
|||
$uni-base-color: #6a6a6a !default; |
|||
$uni-main-color: #3a3a3a !default; |
|||
.uni-breadcrumb-item { |
|||
display: flex; |
|||
align-items: center; |
|||
white-space: nowrap; |
|||
font-size: 14px; |
|||
|
|||
&--slot { |
|||
color: $uni-base-color; |
|||
padding: 0 10px; |
|||
|
|||
&-link { |
|||
color: $uni-main-color; |
|||
font-weight: bold; |
|||
/* #ifndef APP-NVUE */ |
|||
cursor: pointer; |
|||
/* #endif */ |
|||
|
|||
&:hover { |
|||
color: $uni-primary; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&--separator { |
|||
font-size: 12px; |
|||
color: $uni-base-color; |
|||
} |
|||
|
|||
&:first-child &--slot { |
|||
padding-left: 0; |
|||
} |
|||
|
|||
&:last-child &--separator { |
|||
display: none; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,41 @@ |
|||
<template> |
|||
<view class="uni-breadcrumb"> |
|||
<slot /> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
/** |
|||
* Breadcrumb 面包屑导航父组件 |
|||
* @description 显示当前页面的路径,快速返回之前的任意页面 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx |
|||
* @property {String} separator 分隔符,默认为斜杠'/' |
|||
* @property {String} separatorClass 图标分隔符 class |
|||
*/ |
|||
export default { |
|||
options: { |
|||
virtualHost: true |
|||
}, |
|||
props: { |
|||
separator: { |
|||
type: String, |
|||
default: '/' |
|||
}, |
|||
separatorClass: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
|
|||
provide() { |
|||
return { |
|||
uniBreadcrumb: this |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.uni-breadcrumb { |
|||
display: flex; |
|||
} |
|||
</style> |
@ -0,0 +1,88 @@ |
|||
{ |
|||
"id": "uni-breadcrumb", |
|||
"displayName": "uni-breadcrumb 面包屑", |
|||
"version": "0.1.2", |
|||
"description": "Breadcrumb 面包屑", |
|||
"keywords": [ |
|||
"uni-breadcrumb", |
|||
"breadcrumb", |
|||
"uni-ui", |
|||
"面包屑导航", |
|||
"面包屑" |
|||
], |
|||
"repository": "", |
|||
"engines": { |
|||
"HBuilderX": "^3.1.0" |
|||
}, |
|||
"directories": { |
|||
"example": "../../temps/example_temps" |
|||
}, |
|||
"dcloudext": { |
|||
"category": [ |
|||
"前端组件", |
|||
"通用组件" |
|||
], |
|||
"sale": { |
|||
"regular": { |
|||
"price": "0.00" |
|||
}, |
|||
"sourcecode": { |
|||
"price": "0.00" |
|||
} |
|||
}, |
|||
"contact": { |
|||
"qq": "" |
|||
}, |
|||
"declaration": { |
|||
"ads": "无", |
|||
"data": "无", |
|||
"permissions": "无" |
|||
}, |
|||
"npmurl": "" |
|||
}, |
|||
"uni_modules": { |
|||
"dependencies": [], |
|||
"encrypt": [], |
|||
"platforms": { |
|||
"cloud": { |
|||
"tcb": "y", |
|||
"aliyun": "y" |
|||
}, |
|||
"client": { |
|||
"Vue": { |
|||
"vue2": "y", |
|||
"vue3": "y" |
|||
}, |
|||
"App": { |
|||
"app-vue": "y", |
|||
"app-nvue": "n" |
|||
}, |
|||
"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", |
|||
"阿里": "u", |
|||
"百度": "u", |
|||
"字节跳动": "u", |
|||
"QQ": "u", |
|||
"京东": "u" |
|||
}, |
|||
"快应用": { |
|||
"华为": "u", |
|||
"联盟": "u" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,66 @@ |
|||
|
|||
## breadcrumb 面包屑导航 |
|||
> **组件名:uni-breadcrumb** |
|||
> 代码块: `ubreadcrumb` |
|||
|
|||
显示当前页面的路径,快速返回之前的任意页面。 |
|||
|
|||
### 安装方式 |
|||
|
|||
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 |
|||
|
|||
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) |
|||
|
|||
### 基本用法 |
|||
|
|||
在 ``template`` 中使用组件 |
|||
|
|||
```html |
|||
<uni-breadcrumb separator="/"> |
|||
<uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item> |
|||
</uni-breadcrumb> |
|||
``` |
|||
|
|||
```js |
|||
export default { |
|||
name: "uni-stat-breadcrumb", |
|||
data() { |
|||
return { |
|||
routes: [{ |
|||
to: '/A', |
|||
name: 'A页面' |
|||
}, { |
|||
to: '/B', |
|||
name: 'B页面' |
|||
}, { |
|||
to: '/C', |
|||
name: 'C页面' |
|||
}] |
|||
}; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
|
|||
## API |
|||
|
|||
### Breadcrumb Props |
|||
|
|||
|属性名 |类型 |默认值 |说明 | |
|||
|:-: |:-: |:-: |:-: | |
|||
|separator |String |斜杠'/' |分隔符 | |
|||
|separatorClass |String | |图标分隔符 class | |
|||
|
|||
### Breadcrumb Item Props |
|||
|
|||
|属性名 |类型 |默认值 |说明 | |
|||
|:-: |:-: |:-: |:-: | |
|||
|to |String | |路由跳转页面路径 | |
|||
|replace|Boolean | |在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持) | |
|||
|
|||
|
|||
|
|||
|
|||
## 组件示例 |
|||
|
|||
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb) |
@ -0,0 +1,16 @@ |
|||
## 1.4.5(2022-02-25) |
|||
- 修复 条件编译 nvue 不支持的 css 样式 |
|||
## 1.4.4(2022-02-25) |
|||
- 修复 条件编译 nvue 不支持的 css 样式 |
|||
## 1.4.3(2021-09-22) |
|||
- 修复 startDate、 endDate 属性失效的 bug |
|||
## 1.4.2(2021-08-24) |
|||
- 新增 支持国际化 |
|||
## 1.4.1(2021-08-05) |
|||
- 修复 弹出层被 tabbar 遮盖 bug |
|||
## 1.4.0(2021-07-30) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 1.3.16(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 1.3.15(2021-02-04) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,546 @@ |
|||
/** |
|||
* @1900-2100区间内的公历、农历互转 |
|||
* @charset UTF-8 |
|||
* @github https://github.com/jjonline/calendar.js
|
|||
* @Author Jea杨(JJonline@JJonline.Cn) |
|||
* @Time 2014-7-21 |
|||
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals |
|||
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug |
|||
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year |
|||
* @Version 1.0.3 |
|||
* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
|
|||
* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
|
|||
*/ |
|||
/* eslint-disable */ |
|||
var calendar = { |
|||
|
|||
/** |
|||
* 农历1900-2100的润大小信息表 |
|||
* @Array Of Property |
|||
* @return Hex |
|||
*/ |
|||
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
|
|||
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
|
|||
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
|
|||
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
|
|||
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
|
|||
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
|
|||
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
|
|||
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
|
|||
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
|
|||
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
|
|||
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
|
|||
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
|
|||
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
|
|||
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
|
|||
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
|
|||
/** Add By JJonline@JJonline.Cn**/ |
|||
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
|
|||
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
|
|||
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
|
|||
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
|
|||
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
|
|||
0x0d520], // 2100
|
|||
|
|||
/** |
|||
* 公历每个月份的天数普通表 |
|||
* @Array Of Property |
|||
* @return Number |
|||
*/ |
|||
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], |
|||
|
|||
/** |
|||
* 天干地支之天干速查表 |
|||
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] |
|||
* @return Cn string |
|||
*/ |
|||
Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'], |
|||
|
|||
/** |
|||
* 天干地支之地支速查表 |
|||
* @Array Of Property |
|||
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] |
|||
* @return Cn string |
|||
*/ |
|||
Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'], |
|||
|
|||
/** |
|||
* 天干地支之地支速查表<=>生肖 |
|||
* @Array Of Property |
|||
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] |
|||
* @return Cn string |
|||
*/ |
|||
Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'], |
|||
|
|||
/** |
|||
* 24节气速查表 |
|||
* @Array Of Property |
|||
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] |
|||
* @return Cn string |
|||
*/ |
|||
solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'], |
|||
|
|||
/** |
|||
* 1900-2100各年的24节气日期速查表 |
|||
* @Array Of Property |
|||
* @return 0x string For splice |
|||
*/ |
|||
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', |
|||
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
|||
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', |
|||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', |
|||
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f', |
|||
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa', |
|||
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', |
|||
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f', |
|||
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
|||
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', |
|||
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', |
|||
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
|||
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722', |
|||
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f', |
|||
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', |
|||
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', |
|||
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722', |
|||
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
|||
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
|||
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722', |
|||
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', |
|||
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
|||
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', |
|||
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', |
|||
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', |
|||
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', |
|||
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', |
|||
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
|||
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
|||
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', |
|||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa', |
|||
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
|||
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
|||
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721', |
|||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2', |
|||
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', |
|||
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
|||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd', |
|||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', |
|||
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
|||
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
|||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', |
|||
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', |
|||
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
|||
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721', |
|||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5', |
|||
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722', |
|||
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
|||
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', |
|||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', |
|||
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', |
|||
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721', |
|||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd', |
|||
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35', |
|||
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', |
|||
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721', |
|||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5', |
|||
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35', |
|||
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', |
|||
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', |
|||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35', |
|||
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'], |
|||
|
|||
/** |
|||
* 数字转中文速查表 |
|||
* @Array Of Property |
|||
* @trans ['日','一','二','三','四','五','六','七','八','九','十'] |
|||
* @return Cn string |
|||
*/ |
|||
nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'], |
|||
|
|||
/** |
|||
* 日期转农历称呼速查表 |
|||
* @Array Of Property |
|||
* @trans ['初','十','廿','卅'] |
|||
* @return Cn string |
|||
*/ |
|||
nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'], |
|||
|
|||
/** |
|||
* 月份转农历称呼速查表 |
|||
* @Array Of Property |
|||
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] |
|||
* @return Cn string |
|||
*/ |
|||
nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'], |
|||
|
|||
/** |
|||
* 返回农历y年一整年的总天数 |
|||
* @param lunar Year |
|||
* @return Number |
|||
* @eg:var count = calendar.lYearDays(1987) ;//count=387
|
|||
*/ |
|||
lYearDays: function (y) { |
|||
var i; var sum = 348 |
|||
for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 } |
|||
return (sum + this.leapDays(y)) |
|||
}, |
|||
|
|||
/** |
|||
* 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 |
|||
* @param lunar Year |
|||
* @return Number (0-12) |
|||
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
|
|||
*/ |
|||
leapMonth: function (y) { // 闰字编码 \u95f0
|
|||
return (this.lunarInfo[y - 1900] & 0xf) |
|||
}, |
|||
|
|||
/** |
|||
* 返回农历y年闰月的天数 若该年没有闰月则返回0 |
|||
* @param lunar Year |
|||
* @return Number (0、29、30) |
|||
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
|
|||
*/ |
|||
leapDays: function (y) { |
|||
if (this.leapMonth(y)) { |
|||
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29) |
|||
} |
|||
return (0) |
|||
}, |
|||
|
|||
/** |
|||
* 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 |
|||
* @param lunar Year |
|||
* @return Number (-1、29、30) |
|||
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
|
|||
*/ |
|||
monthDays: function (y, m) { |
|||
if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
|
|||
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29) |
|||
}, |
|||
|
|||
/** |
|||
* 返回公历(!)y年m月的天数 |
|||
* @param solar Year |
|||
* @return Number (-1、28、29、30、31) |
|||
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
|
|||
*/ |
|||
solarDays: function (y, m) { |
|||
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
|||
var ms = m - 1 |
|||
if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
|
|||
return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28) |
|||
} else { |
|||
return (this.solarMonth[ms]) |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 农历年份转换为干支纪年 |
|||
* @param lYear 农历年的年份数 |
|||
* @return Cn string |
|||
*/ |
|||
toGanZhiYear: function (lYear) { |
|||
var ganKey = (lYear - 3) % 10 |
|||
var zhiKey = (lYear - 3) % 12 |
|||
if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
|
|||
if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
|
|||
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1] |
|||
}, |
|||
|
|||
/** |
|||
* 公历月、日判断所属星座 |
|||
* @param cMonth [description] |
|||
* @param cDay [description] |
|||
* @return Cn string |
|||
*/ |
|||
toAstro: function (cMonth, cDay) { |
|||
var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf' |
|||
var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] |
|||
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
|
|||
}, |
|||
|
|||
/** |
|||
* 传入offset偏移量返回干支 |
|||
* @param offset 相对甲子的偏移量 |
|||
* @return Cn string |
|||
*/ |
|||
toGanZhi: function (offset) { |
|||
return this.Gan[offset % 10] + this.Zhi[offset % 12] |
|||
}, |
|||
|
|||
/** |
|||
* 传入公历(!)y年获得该年第n个节气的公历日期 |
|||
* @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 |
|||
* @return day Number |
|||
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
|
|||
*/ |
|||
getTerm: function (y, n) { |
|||
if (y < 1900 || y > 2100) { return -1 } |
|||
if (n < 1 || n > 24) { return -1 } |
|||
var _table = this.sTermInfo[y - 1900] |
|||
var _info = [ |
|||
parseInt('0x' + _table.substr(0, 5)).toString(), |
|||
parseInt('0x' + _table.substr(5, 5)).toString(), |
|||
parseInt('0x' + _table.substr(10, 5)).toString(), |
|||
parseInt('0x' + _table.substr(15, 5)).toString(), |
|||
parseInt('0x' + _table.substr(20, 5)).toString(), |
|||
parseInt('0x' + _table.substr(25, 5)).toString() |
|||
] |
|||
var _calday = [ |
|||
_info[0].substr(0, 1), |
|||
_info[0].substr(1, 2), |
|||
_info[0].substr(3, 1), |
|||
_info[0].substr(4, 2), |
|||
|
|||
_info[1].substr(0, 1), |
|||
_info[1].substr(1, 2), |
|||
_info[1].substr(3, 1), |
|||
_info[1].substr(4, 2), |
|||
|
|||
_info[2].substr(0, 1), |
|||
_info[2].substr(1, 2), |
|||
_info[2].substr(3, 1), |
|||
_info[2].substr(4, 2), |
|||
|
|||
_info[3].substr(0, 1), |
|||
_info[3].substr(1, 2), |
|||
_info[3].substr(3, 1), |
|||
_info[3].substr(4, 2), |
|||
|
|||
_info[4].substr(0, 1), |
|||
_info[4].substr(1, 2), |
|||
_info[4].substr(3, 1), |
|||
_info[4].substr(4, 2), |
|||
|
|||
_info[5].substr(0, 1), |
|||
_info[5].substr(1, 2), |
|||
_info[5].substr(3, 1), |
|||
_info[5].substr(4, 2) |
|||
] |
|||
return parseInt(_calday[n - 1]) |
|||
}, |
|||
|
|||
/** |
|||
* 传入农历数字月份返回汉语通俗表示法 |
|||
* @param lunar month |
|||
* @return Cn string |
|||
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
|
|||
*/ |
|||
toChinaMonth: function (m) { // 月 => \u6708
|
|||
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
|||
var s = this.nStr3[m - 1] |
|||
s += '\u6708'// 加上月字
|
|||
return s |
|||
}, |
|||
|
|||
/** |
|||
* 传入农历日期数字返回汉字表示法 |
|||
* @param lunar day |
|||
* @return Cn string |
|||
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
|
|||
*/ |
|||
toChinaDay: function (d) { // 日 => \u65e5
|
|||
var s |
|||
switch (d) { |
|||
case 10: |
|||
s = '\u521d\u5341'; break |
|||
case 20: |
|||
s = '\u4e8c\u5341'; break |
|||
break |
|||
case 30: |
|||
s = '\u4e09\u5341'; break |
|||
break |
|||
default : |
|||
s = this.nStr2[Math.floor(d / 10)] |
|||
s += this.nStr1[d % 10] |
|||
} |
|||
return (s) |
|||
}, |
|||
|
|||
/** |
|||
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” |
|||
* @param y year |
|||
* @return Cn string |
|||
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
|
|||
*/ |
|||
getAnimal: function (y) { |
|||
return this.Animals[(y - 4) % 12] |
|||
}, |
|||
|
|||
/** |
|||
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON |
|||
* @param y solar year |
|||
* @param m solar month |
|||
* @param d solar day |
|||
* @return JSON object |
|||
* @eg:console.log(calendar.solar2lunar(1987,11,01)); |
|||
*/ |
|||
solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
|
|||
// 年份限定、上限
|
|||
if (y < 1900 || y > 2100) { |
|||
return -1// undefined转换为数字变为NaN
|
|||
} |
|||
// 公历传参最下限
|
|||
if (y == 1900 && m == 1 && d < 31) { |
|||
return -1 |
|||
} |
|||
// 未传参 获得当天
|
|||
if (!y) { |
|||
var objDate = new Date() |
|||
} else { |
|||
var objDate = new Date(y, parseInt(m) - 1, d) |
|||
} |
|||
var i; var leap = 0; var temp = 0 |
|||
// 修正ymd参数
|
|||
var y = objDate.getFullYear() |
|||
var m = objDate.getMonth() + 1 |
|||
var d = objDate.getDate() |
|||
var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000 |
|||
for (i = 1900; i < 2101 && offset > 0; i++) { |
|||
temp = this.lYearDays(i) |
|||
offset -= temp |
|||
} |
|||
if (offset < 0) { |
|||
offset += temp; i-- |
|||
} |
|||
|
|||
// 是否今天
|
|||
var isTodayObj = new Date() |
|||
var isToday = false |
|||
if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) { |
|||
isToday = true |
|||
} |
|||
// 星期几
|
|||
var nWeek = objDate.getDay() |
|||
var cWeek = this.nStr1[nWeek] |
|||
// 数字表示周几顺应天朝周一开始的惯例
|
|||
if (nWeek == 0) { |
|||
nWeek = 7 |
|||
} |
|||
// 农历年
|
|||
var year = i |
|||
var leap = this.leapMonth(i) // 闰哪个月
|
|||
var isLeap = false |
|||
|
|||
// 效验闰月
|
|||
for (i = 1; i < 13 && offset > 0; i++) { |
|||
// 闰月
|
|||
if (leap > 0 && i == (leap + 1) && isLeap == false) { |
|||
--i |
|||
isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
|
|||
} else { |
|||
temp = this.monthDays(year, i)// 计算农历普通月天数
|
|||
} |
|||
// 解除闰月
|
|||
if (isLeap == true && i == (leap + 1)) { isLeap = false } |
|||
offset -= temp |
|||
} |
|||
// 闰月导致数组下标重叠取反
|
|||
if (offset == 0 && leap > 0 && i == leap + 1) { |
|||
if (isLeap) { |
|||
isLeap = false |
|||
} else { |
|||
isLeap = true; --i |
|||
} |
|||
} |
|||
if (offset < 0) { |
|||
offset += temp; --i |
|||
} |
|||
// 农历月
|
|||
var month = i |
|||
// 农历日
|
|||
var day = offset + 1 |
|||
// 天干地支处理
|
|||
var sm = m - 1 |
|||
var gzY = this.toGanZhiYear(year) |
|||
|
|||
// 当月的两个节气
|
|||
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
|
|||
var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
|
|||
var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
|
|||
|
|||
// 依据12节气修正干支月
|
|||
var gzM = this.toGanZhi((y - 1900) * 12 + m + 11) |
|||
if (d >= firstNode) { |
|||
gzM = this.toGanZhi((y - 1900) * 12 + m + 12) |
|||
} |
|||
|
|||
// 传入的日期的节气与否
|
|||
var isTerm = false |
|||
var Term = null |
|||
if (firstNode == d) { |
|||
isTerm = true |
|||
Term = this.solarTerm[m * 2 - 2] |
|||
} |
|||
if (secondNode == d) { |
|||
isTerm = true |
|||
Term = this.solarTerm[m * 2 - 1] |
|||
} |
|||
// 日柱 当月一日与 1900/1/1 相差天数
|
|||
var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 |
|||
var gzD = this.toGanZhi(dayCyclical + d - 1) |
|||
// 该日期所属的星座
|
|||
var astro = this.toAstro(m, d) |
|||
|
|||
return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro } |
|||
}, |
|||
|
|||
/** |
|||
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON |
|||
* @param y lunar year |
|||
* @param m lunar month |
|||
* @param d lunar day |
|||
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] |
|||
* @return JSON object |
|||
* @eg:console.log(calendar.lunar2solar(1987,9,10)); |
|||
*/ |
|||
lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
|
|||
var isLeapMonth = !!isLeapMonth |
|||
var leapOffset = 0 |
|||
var leapMonth = this.leapMonth(y) |
|||
var leapDay = this.leapDays(y) |
|||
if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
|
|||
if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
|
|||
var day = this.monthDays(y, m) |
|||
var _day = day |
|||
// bugFix 2016-9-25
|
|||
// if month is leap, _day use leapDays method
|
|||
if (isLeapMonth) { |
|||
_day = this.leapDays(y, m) |
|||
} |
|||
if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
|
|||
|
|||
// 计算农历的时间差
|
|||
var offset = 0 |
|||
for (var i = 1900; i < y; i++) { |
|||
offset += this.lYearDays(i) |
|||
} |
|||
var leap = 0; var isAdd = false |
|||
for (var i = 1; i < m; i++) { |
|||
leap = this.leapMonth(y) |
|||
if (!isAdd) { // 处理闰月
|
|||
if (leap <= i && leap > 0) { |
|||
offset += this.leapDays(y); isAdd = true |
|||
} |
|||
} |
|||
offset += this.monthDays(y, i) |
|||
} |
|||
// 转换闰月农历 需补充该年闰月的前一个月的时差
|
|||
if (isLeapMonth) { offset += day } |
|||
// 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
|
|||
var stmap = Date.UTC(1900, 1, 30, 0, 0, 0) |
|||
var calObj = new Date((offset + d - 31) * 86400000 + stmap) |
|||
var cY = calObj.getUTCFullYear() |
|||
var cM = calObj.getUTCMonth() + 1 |
|||
var cD = calObj.getUTCDate() |
|||
|
|||
return this.solar2lunar(cY, cM, cD) |
|||
} |
|||
} |
|||
|
|||
export default calendar |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"uni-calender.ok": "ok", |
|||
"uni-calender.cancel": "cancel", |
|||
"uni-calender.today": "today", |
|||
"uni-calender.MON": "MON", |
|||
"uni-calender.TUE": "TUE", |
|||
"uni-calender.WED": "WED", |
|||
"uni-calender.THU": "THU", |
|||
"uni-calender.FRI": "FRI", |
|||
"uni-calender.SAT": "SAT", |
|||
"uni-calender.SUN": "SUN" |
|||
} |
@ -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,12 @@ |
|||
{ |
|||
"uni-calender.ok": "确定", |
|||
"uni-calender.cancel": "取消", |
|||
"uni-calender.today": "今日", |
|||
"uni-calender.SUN": "日", |
|||
"uni-calender.MON": "一", |
|||
"uni-calender.TUE": "二", |
|||
"uni-calender.WED": "三", |
|||
"uni-calender.THU": "四", |
|||
"uni-calender.FRI": "五", |
|||
"uni-calender.SAT": "六" |
|||
} |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"uni-calender.ok": "確定", |
|||
"uni-calender.cancel": "取消", |
|||
"uni-calender.today": "今日", |
|||
"uni-calender.SUN": "日", |
|||
"uni-calender.MON": "一", |
|||
"uni-calender.TUE": "二", |
|||
"uni-calender.WED": "三", |
|||
"uni-calender.THU": "四", |
|||
"uni-calender.FRI": "五", |
|||
"uni-calender.SAT": "六" |
|||
} |
@ -0,0 +1,188 @@ |
|||
<template> |
|||
<view class="uni-calendar-item__weeks-box" :class="{ |
|||
'uni-calendar-item--disable':weeks.disable, |
|||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
|||
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) , |
|||
'uni-calendar-item--before-checked':weeks.beforeMultiple, |
|||
'uni-calendar-item--multiple': weeks.multiple, |
|||
'uni-calendar-item--after-checked':weeks.afterMultiple, |
|||
}" |
|||
@click="choiceDate(weeks)"> |
|||
<view class="uni-calendar-item__weeks-box-item"> |
|||
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text> |
|||
<text class="uni-calendar-item__weeks-box-text" :class="{ |
|||
'uni-calendar-item--isDay-text': weeks.isDay, |
|||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
|||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
|||
'uni-calendar-item--before-checked':weeks.beforeMultiple, |
|||
'uni-calendar-item--multiple': weeks.multiple, |
|||
'uni-calendar-item--after-checked':weeks.afterMultiple, |
|||
'uni-calendar-item--disable':weeks.disable, |
|||
}">{{weeks.date}}</text> |
|||
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{ |
|||
'uni-calendar-item--isDay-text':weeks.isDay, |
|||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
|||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
|||
'uni-calendar-item--before-checked':weeks.beforeMultiple, |
|||
'uni-calendar-item--multiple': weeks.multiple, |
|||
'uni-calendar-item--after-checked':weeks.afterMultiple, |
|||
}">{{todayText}}</text> |
|||
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{ |
|||
'uni-calendar-item--isDay-text':weeks.isDay, |
|||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
|||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
|||
'uni-calendar-item--before-checked':weeks.beforeMultiple, |
|||
'uni-calendar-item--multiple': weeks.multiple, |
|||
'uni-calendar-item--after-checked':weeks.afterMultiple, |
|||
'uni-calendar-item--disable':weeks.disable, |
|||
}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text> |
|||
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{ |
|||
'uni-calendar-item--extra':weeks.extraInfo.info, |
|||
'uni-calendar-item--isDay-text':weeks.isDay, |
|||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay, |
|||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay, |
|||
'uni-calendar-item--before-checked':weeks.beforeMultiple, |
|||
'uni-calendar-item--multiple': weeks.multiple, |
|||
'uni-calendar-item--after-checked':weeks.afterMultiple, |
|||
'uni-calendar-item--disable':weeks.disable, |
|||
}">{{weeks.extraInfo.info}}</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
initVueI18n |
|||
} from '@dcloudio/uni-i18n' |
|||
import messages from './i18n/index.js' |
|||
const { t } = initVueI18n(messages) |
|||
export default { |
|||
emits:['change'], |
|||
props: { |
|||
weeks: { |
|||
type: Object, |
|||
default () { |
|||
return {} |
|||
} |
|||
}, |
|||
calendar: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
selected: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
lunar: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
computed: { |
|||
todayText() { |
|||
return t("uni-calender.today") |
|||
}, |
|||
}, |
|||
methods: { |
|||
choiceDate(weeks) { |
|||
this.$emit('change', weeks) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
$uni-font-size-base:14px; |
|||
$uni-text-color:#333; |
|||
$uni-font-size-sm:12px; |
|||
$uni-color-error: #e43d33; |
|||
$uni-opacity-disabled: 0.3; |
|||
$uni-text-color-disable:#c0c0c0; |
|||
$uni-color-primary: #2979ff; |
|||
.uni-calendar-item__weeks-box { |
|||
flex: 1; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.uni-calendar-item__weeks-box-text { |
|||
font-size: $uni-font-size-base; |
|||
color: $uni-text-color; |
|||
} |
|||
|
|||
.uni-calendar-item__weeks-lunar-text { |
|||
font-size: $uni-font-size-sm; |
|||
color: $uni-text-color; |
|||
} |
|||
|
|||
.uni-calendar-item__weeks-box-item { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
width: 100rpx; |
|||
height: 100rpx; |
|||
} |
|||
|
|||
.uni-calendar-item__weeks-box-circle { |
|||
position: absolute; |
|||
top: 5px; |
|||
right: 5px; |
|||
width: 8px; |
|||
height: 8px; |
|||
border-radius: 8px; |
|||
background-color: $uni-color-error; |
|||
|
|||
} |
|||
|
|||
.uni-calendar-item--disable { |
|||
background-color: rgba(249, 249, 249, $uni-opacity-disabled); |
|||
color: $uni-text-color-disable; |
|||
} |
|||
|
|||
.uni-calendar-item--isDay-text { |
|||
color: $uni-color-primary; |
|||
} |
|||
|
|||
.uni-calendar-item--isDay { |
|||
background-color: $uni-color-primary; |
|||
opacity: 0.8; |
|||
color: #fff; |
|||
} |
|||
|
|||
.uni-calendar-item--extra { |
|||
color: $uni-color-error; |
|||
opacity: 0.8; |
|||
} |
|||
|
|||
.uni-calendar-item--checked { |
|||
background-color: $uni-color-primary; |
|||
color: #fff; |
|||
opacity: 0.8; |
|||
} |
|||
|
|||
.uni-calendar-item--multiple { |
|||
background-color: $uni-color-primary; |
|||
color: #fff; |
|||
opacity: 0.8; |
|||
} |
|||
.uni-calendar-item--before-checked { |
|||
background-color: #ff5a5f; |
|||
color: #fff; |
|||
} |
|||
.uni-calendar-item--after-checked { |
|||
background-color: #ff5a5f; |
|||
color: #fff; |
|||
} |
|||
</style> |
@ -0,0 +1,562 @@ |
|||
<template> |
|||
<view class="uni-calendar"> |
|||
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view> |
|||
<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}"> |
|||
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top"> |
|||
<view class="uni-calendar__header-btn-box" @click="close"> |
|||
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__header-btn-box" @click="confirm"> |
|||
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text> |
|||
</view> |
|||
</view> |
|||
<view class="uni-calendar__header"> |
|||
<view class="uni-calendar__header-btn-box" @click.stop="pre"> |
|||
<view class="uni-calendar__header-btn uni-calendar--left"></view> |
|||
</view> |
|||
<picker mode="date" :value="date" fields="month" @change="bindDateChange"> |
|||
<text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text> |
|||
</picker> |
|||
<view class="uni-calendar__header-btn-box" @click.stop="next"> |
|||
<view class="uni-calendar__header-btn uni-calendar--right"></view> |
|||
</view> |
|||
<text class="uni-calendar__backtoday" @click="backtoday">{{todayText}}</text> |
|||
|
|||
</view> |
|||
<view class="uni-calendar__box"> |
|||
<view v-if="showMonth" class="uni-calendar__box-bg"> |
|||
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks"> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{monText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{THUText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text> |
|||
</view> |
|||
<view class="uni-calendar__weeks-day"> |
|||
<text class="uni-calendar__weeks-day-text">{{SATText}}</text> |
|||
</view> |
|||
</view> |
|||
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex"> |
|||
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex"> |
|||
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import Calendar from './util.js'; |
|||
import calendarItem from './uni-calendar-item.vue' |
|||
import { |
|||
initVueI18n |
|||
} from '@dcloudio/uni-i18n' |
|||
import messages from './i18n/index.js' |
|||
const { t } = initVueI18n(messages) |
|||
/** |
|||
* Calendar 日历 |
|||
* @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=56 |
|||
* @property {String} date 自定义当前时间,默认为今天 |
|||
* @property {Boolean} lunar 显示农历 |
|||
* @property {String} startDate 日期选择范围-开始日期 |
|||
* @property {String} endDate 日期选择范围-结束日期 |
|||
* @property {Boolean} range 范围选择 |
|||
* @property {Boolean} insert = [true|false] 插入模式,默认为false |
|||
* @value true 弹窗模式 |
|||
* @value false 插入模式 |
|||
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容 |
|||
* @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
|||
* @property {Boolean} showMonth 是否选择月份为背景 |
|||
* @event {Function} change 日期改变,`insert :ture` 时生效 |
|||
* @event {Function} confirm 确认选择`insert :false` 时生效 |
|||
* @event {Function} monthSwitch 切换月份时触发 |
|||
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" /> |
|||
*/ |
|||
export default { |
|||
components: { |
|||
calendarItem |
|||
}, |
|||
emits:['close','confirm','change','monthSwitch'], |
|||
props: { |
|||
date: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
selected: { |
|||
type: Array, |
|||
default () { |
|||
return [] |
|||
} |
|||
}, |
|||
lunar: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
startDate: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
endDate: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
range: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
insert: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
showMonth: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
clearDate: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
show: false, |
|||
weeks: [], |
|||
calendar: {}, |
|||
nowDate: '', |
|||
aniMaskShow: false |
|||
} |
|||
}, |
|||
computed:{ |
|||
/** |
|||
* for i18n |
|||
*/ |
|||
|
|||
okText() { |
|||
return t("uni-calender.ok") |
|||
}, |
|||
cancelText() { |
|||
return t("uni-calender.cancel") |
|||
}, |
|||
todayText() { |
|||
return t("uni-calender.today") |
|||
}, |
|||
monText() { |
|||
return t("uni-calender.MON") |
|||
}, |
|||
TUEText() { |
|||
return t("uni-calender.TUE") |
|||
}, |
|||
WEDText() { |
|||
return t("uni-calender.WED") |
|||
}, |
|||
THUText() { |
|||
return t("uni-calender.THU") |
|||
}, |
|||
FRIText() { |
|||
return t("uni-calender.FRI") |
|||
}, |
|||
SATText() { |
|||
return t("uni-calender.SAT") |
|||
}, |
|||
SUNText() { |
|||
return t("uni-calender.SUN") |
|||
}, |
|||
}, |
|||
watch: { |
|||
date(newVal) { |
|||
// this.cale.setDate(newVal) |
|||
this.init(newVal) |
|||
}, |
|||
startDate(val){ |
|||
this.cale.resetSatrtDate(val) |
|||
this.cale.setDate(this.nowDate.fullDate) |
|||
this.weeks = this.cale.weeks |
|||
}, |
|||
endDate(val){ |
|||
this.cale.resetEndDate(val) |
|||
this.cale.setDate(this.nowDate.fullDate) |
|||
this.weeks = this.cale.weeks |
|||
}, |
|||
selected(newVal) { |
|||
this.cale.setSelectInfo(this.nowDate.fullDate, newVal) |
|||
this.weeks = this.cale.weeks |
|||
} |
|||
}, |
|||
created() { |
|||
// 获取日历方法实例 |
|||
this.cale = new Calendar({ |
|||
// date: new Date(), |
|||
selected: this.selected, |
|||
startDate: this.startDate, |
|||
endDate: this.endDate, |
|||
range: this.range, |
|||
}) |
|||
// 选中某一天 |
|||
// this.cale.setDate(this.date) |
|||
this.init(this.date) |
|||
// this.setDay |
|||
}, |
|||
methods: { |
|||
// 取消穿透 |
|||
clean() {}, |
|||
bindDateChange(e) { |
|||
const value = e.detail.value + '-1' |
|||
console.log(this.cale.getDate(value)); |
|||
this.init(value) |
|||
}, |
|||
/** |
|||
* 初始化日期显示 |
|||
* @param {Object} date |
|||
*/ |
|||
init(date) { |
|||
this.cale.setDate(date) |
|||
this.weeks = this.cale.weeks |
|||
this.nowDate = this.calendar = this.cale.getInfo(date) |
|||
}, |
|||
/** |
|||
* 打开日历弹窗 |
|||
*/ |
|||
open() { |
|||
// 弹窗模式并且清理数据 |
|||
if (this.clearDate && !this.insert) { |
|||
this.cale.cleanMultipleStatus() |
|||
// this.cale.setDate(this.date) |
|||
this.init(this.date) |
|||
} |
|||
this.show = true |
|||
this.$nextTick(() => { |
|||
setTimeout(() => { |
|||
this.aniMaskShow = true |
|||
}, 50) |
|||
}) |
|||
}, |
|||
/** |
|||
* 关闭日历弹窗 |
|||
*/ |
|||
close() { |
|||
this.aniMaskShow = false |
|||
this.$nextTick(() => { |
|||
setTimeout(() => { |
|||
this.show = false |
|||
this.$emit('close') |
|||
}, 300) |
|||
}) |
|||
}, |
|||
/** |
|||
* 确认按钮 |
|||
*/ |
|||
confirm() { |
|||
this.setEmit('confirm') |
|||
this.close() |
|||
}, |
|||
/** |
|||
* 变化触发 |
|||
*/ |
|||
change() { |
|||
if (!this.insert) return |
|||
this.setEmit('change') |
|||
}, |
|||
/** |
|||
* 选择月份触发 |
|||
*/ |
|||
monthSwitch() { |
|||
let { |
|||
year, |
|||
month |
|||
} = this.nowDate |
|||
this.$emit('monthSwitch', { |
|||
year, |
|||
month: Number(month) |
|||
}) |
|||
}, |
|||
/** |
|||
* 派发事件 |
|||
* @param {Object} name |
|||
*/ |
|||
setEmit(name) { |
|||
let { |
|||
year, |
|||
month, |
|||
date, |
|||
fullDate, |
|||
lunar, |
|||
extraInfo |
|||
} = this.calendar |
|||
this.$emit(name, { |
|||
range: this.cale.multipleStatus, |
|||
year, |
|||
month, |
|||
date, |
|||
fulldate: fullDate, |
|||
lunar, |
|||
extraInfo: extraInfo || {} |
|||
}) |
|||
}, |
|||
/** |
|||
* 选择天触发 |
|||
* @param {Object} weeks |
|||
*/ |
|||
choiceDate(weeks) { |
|||
if (weeks.disable) return |
|||
this.calendar = weeks |
|||
// 设置多选 |
|||
this.cale.setMultiple(this.calendar.fullDate) |
|||
this.weeks = this.cale.weeks |
|||
this.change() |
|||
}, |
|||
/** |
|||
* 回到今天 |
|||
*/ |
|||
backtoday() { |
|||
console.log(this.cale.getDate(new Date()).fullDate); |
|||
let date = this.cale.getDate(new Date()).fullDate |
|||
// this.cale.setDate(date) |
|||
this.init(date) |
|||
this.change() |
|||
}, |
|||
/** |
|||
* 上个月 |
|||
*/ |
|||
pre() { |
|||
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate |
|||
this.setDate(preDate) |
|||
this.monthSwitch() |
|||
|
|||
}, |
|||
/** |
|||
* 下个月 |
|||
*/ |
|||
next() { |
|||
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate |
|||
this.setDate(nextDate) |
|||
this.monthSwitch() |
|||
}, |
|||
/** |
|||
* 设置日期 |
|||
* @param {Object} date |
|||
*/ |
|||
setDate(date) { |
|||
this.cale.setDate(date) |
|||
this.weeks = this.cale.weeks |
|||
this.nowDate = this.cale.getInfo(date) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4); |
|||
$uni-border-color: #EDEDED; |
|||
$uni-text-color: #333; |
|||
$uni-bg-color-hover:#f1f1f1; |
|||
$uni-font-size-base:14px; |
|||
$uni-text-color-placeholder: #808080; |
|||
$uni-color-subtitle: #555555; |
|||
$uni-text-color-grey:#999; |
|||
.uni-calendar { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.uni-calendar__mask { |
|||
position: fixed; |
|||
bottom: 0; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
background-color: $uni-bg-color-mask; |
|||
transition-property: opacity; |
|||
transition-duration: 0.3s; |
|||
opacity: 0; |
|||
/* #ifndef APP-NVUE */ |
|||
z-index: 99; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.uni-calendar--mask-show { |
|||
opacity: 1 |
|||
} |
|||
|
|||
.uni-calendar--fixed { |
|||
position: fixed; |
|||
/* #ifdef APP-NVUE */ |
|||
bottom: 0; |
|||
/* #endif */ |
|||
left: 0; |
|||
right: 0; |
|||
transition-property: transform; |
|||
transition-duration: 0.3s; |
|||
transform: translateY(460px); |
|||
/* #ifndef APP-NVUE */ |
|||
bottom: calc(var(--window-bottom)); |
|||
z-index: 99; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.uni-calendar--ani-show { |
|||
transform: translateY(0); |
|||
} |
|||
|
|||
.uni-calendar__content { |
|||
background-color: #fff; |
|||
} |
|||
|
|||
.uni-calendar__header { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
justify-content: center; |
|||
align-items: center; |
|||
height: 50px; |
|||
border-bottom-color: $uni-border-color; |
|||
border-bottom-style: solid; |
|||
border-bottom-width: 1px; |
|||
} |
|||
|
|||
.uni-calendar--fixed-top { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
border-top-color: $uni-border-color; |
|||
border-top-style: solid; |
|||
border-top-width: 1px; |
|||
} |
|||
|
|||
.uni-calendar--fixed-width { |
|||
width: 50px; |
|||
// padding: 0 15px; |
|||
} |
|||
|
|||
.uni-calendar__backtoday { |
|||
position: absolute; |
|||
right: 0; |
|||
top: 25rpx; |
|||
padding: 0 5px; |
|||
padding-left: 10px; |
|||
height: 25px; |
|||
line-height: 25px; |
|||
font-size: 12px; |
|||
border-top-left-radius: 25px; |
|||
border-bottom-left-radius: 25px; |
|||
color: $uni-text-color; |
|||
background-color: $uni-bg-color-hover; |
|||
} |
|||
|
|||
.uni-calendar__header-text { |
|||
text-align: center; |
|||
width: 100px; |
|||
font-size: $uni-font-size-base; |
|||
color: $uni-text-color; |
|||
} |
|||
|
|||
.uni-calendar__header-btn-box { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
align-items: center; |
|||
justify-content: center; |
|||
width: 50px; |
|||
height: 50px; |
|||
} |
|||
|
|||
.uni-calendar__header-btn { |
|||
width: 10px; |
|||
height: 10px; |
|||
border-left-color: $uni-text-color-placeholder; |
|||
border-left-style: solid; |
|||
border-left-width: 2px; |
|||
border-top-color: $uni-color-subtitle; |
|||
border-top-style: solid; |
|||
border-top-width: 2px; |
|||
} |
|||
|
|||
.uni-calendar--left { |
|||
transform: rotate(-45deg); |
|||
} |
|||
|
|||
.uni-calendar--right { |
|||
transform: rotate(135deg); |
|||
} |
|||
|
|||
|
|||
.uni-calendar__weeks { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
} |
|||
|
|||
.uni-calendar__weeks-item { |
|||
flex: 1; |
|||
} |
|||
|
|||
.uni-calendar__weeks-day { |
|||
flex: 1; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
height: 45px; |
|||
border-bottom-color: #F5F5F5; |
|||
border-bottom-style: solid; |
|||
border-bottom-width: 1px; |
|||
} |
|||
|
|||
.uni-calendar__weeks-day-text { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.uni-calendar__box { |
|||
position: relative; |
|||
} |
|||
|
|||
.uni-calendar__box-bg { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
justify-content: center; |
|||
align-items: center; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
} |
|||
|
|||
.uni-calendar__box-bg-text { |
|||
font-size: 200px; |
|||
font-weight: bold; |
|||
color: $uni-text-color-grey; |
|||
opacity: 0.1; |
|||
text-align: center; |
|||
/* #ifndef APP-NVUE */ |
|||
line-height: 1; |
|||
/* #endif */ |
|||
} |
|||
</style> |
@ -0,0 +1,350 @@ |
|||
import CALENDAR from './calendar.js' |
|||
|
|||
class Calendar { |
|||
constructor({ |
|||
date, |
|||
selected, |
|||
startDate, |
|||
endDate, |
|||
range |
|||
} = {}) { |
|||
// 当前日期
|
|||
this.date = this.getDate(new Date()) // 当前初入日期
|
|||
// 打点信息
|
|||
this.selected = selected || []; |
|||
// 范围开始
|
|||
this.startDate = startDate |
|||
// 范围结束
|
|||
this.endDate = endDate |
|||
this.range = range |
|||
// 多选状态
|
|||
this.cleanMultipleStatus() |
|||
// 每周日期
|
|||
this.weeks = {} |
|||
// this._getWeek(this.date.fullDate)
|
|||
} |
|||
/** |
|||
* 设置日期 |
|||
* @param {Object} date |
|||
*/ |
|||
setDate(date) { |
|||
this.selectDate = this.getDate(date) |
|||
this._getWeek(this.selectDate.fullDate) |
|||
} |
|||
|
|||
/** |
|||
* 清理多选状态 |
|||
*/ |
|||
cleanMultipleStatus() { |
|||
this.multipleStatus = { |
|||
before: '', |
|||
after: '', |
|||
data: [] |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 重置开始日期 |
|||
*/ |
|||
resetSatrtDate(startDate) { |
|||
// 范围开始
|
|||
this.startDate = startDate |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 重置结束日期 |
|||
*/ |
|||
resetEndDate(endDate) { |
|||
// 范围结束
|
|||
this.endDate = endDate |
|||
} |
|||
|
|||
/** |
|||
* 获取任意时间 |
|||
*/ |
|||
getDate(date, AddDayCount = 0, str = 'day') { |
|||
if (!date) { |
|||
date = new Date() |
|||
} |
|||
if (typeof date !== 'object') { |
|||
date = date.replace(/-/g, '/') |
|||
} |
|||
const dd = new Date(date) |
|||
switch (str) { |
|||
case 'day': |
|||
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
|
|||
break |
|||
case 'month': |
|||
if (dd.getDate() === 31) { |
|||
dd.setDate(dd.getDate() + AddDayCount) |
|||
} else { |
|||
dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
|
|||
} |
|||
break |
|||
case 'year': |
|||
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
|
|||
break |
|||
} |
|||
const y = dd.getFullYear() |
|||
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
|
|||
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
|
|||
return { |
|||
fullDate: y + '-' + m + '-' + d, |
|||
year: y, |
|||
month: m, |
|||
date: d, |
|||
day: dd.getDay() |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取上月剩余天数 |
|||
*/ |
|||
_getLastMonthDays(firstDay, full) { |
|||
let dateArr = [] |
|||
for (let i = firstDay; i > 0; i--) { |
|||
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() |
|||
dateArr.push({ |
|||
date: beforeDate, |
|||
month: full.month - 1, |
|||
lunar: this.getlunar(full.year, full.month - 1, beforeDate), |
|||
disable: true |
|||
}) |
|||
} |
|||
return dateArr |
|||
} |
|||
/** |
|||
* 获取本月天数 |
|||
*/ |
|||
_currentMonthDys(dateData, full) { |
|||
let dateArr = [] |
|||
let fullDate = this.date.fullDate |
|||
for (let i = 1; i <= dateData; i++) { |
|||
let nowDate = full.year + '-' + (full.month < 10 ? |
|||
full.month : full.month) + '-' + (i < 10 ? |
|||
'0' + i : i) |
|||
// 是否今天
|
|||
let isDay = fullDate === nowDate |
|||
// 获取打点信息
|
|||
let info = this.selected && this.selected.find((item) => { |
|||
if (this.dateEqual(nowDate, item.date)) { |
|||
return item |
|||
} |
|||
}) |
|||
|
|||
// 日期禁用
|
|||
let disableBefore = true |
|||
let disableAfter = true |
|||
if (this.startDate) { |
|||
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
|
|||
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
|
|||
disableBefore = this.dateCompare(this.startDate, nowDate) |
|||
} |
|||
|
|||
if (this.endDate) { |
|||
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
|
|||
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
|
|||
disableAfter = this.dateCompare(nowDate, this.endDate) |
|||
} |
|||
let multiples = this.multipleStatus.data |
|||
let checked = false |
|||
let multiplesStatus = -1 |
|||
if (this.range) { |
|||
if (multiples) { |
|||
multiplesStatus = multiples.findIndex((item) => { |
|||
return this.dateEqual(item, nowDate) |
|||
}) |
|||
} |
|||
if (multiplesStatus !== -1) { |
|||
checked = true |
|||
} |
|||
} |
|||
let data = { |
|||
fullDate: nowDate, |
|||
year: full.year, |
|||
date: i, |
|||
multiple: this.range ? checked : false, |
|||
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate), |
|||
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate), |
|||
month: full.month, |
|||
lunar: this.getlunar(full.year, full.month, i), |
|||
disable: !(disableBefore && disableAfter), |
|||
isDay |
|||
} |
|||
if (info) { |
|||
data.extraInfo = info |
|||
} |
|||
|
|||
dateArr.push(data) |
|||
} |
|||
return dateArr |
|||
} |
|||
/** |
|||
* 获取下月天数 |
|||
*/ |
|||
_getNextMonthDays(surplus, full) { |
|||
let dateArr = [] |
|||
for (let i = 1; i < surplus + 1; i++) { |
|||
dateArr.push({ |
|||
date: i, |
|||
month: Number(full.month) + 1, |
|||
lunar: this.getlunar(full.year, Number(full.month) + 1, i), |
|||
disable: true |
|||
}) |
|||
} |
|||
return dateArr |
|||
} |
|||
|
|||
/** |
|||
* 获取当前日期详情 |
|||
* @param {Object} date |
|||
*/ |
|||
getInfo(date) { |
|||
if (!date) { |
|||
date = new Date() |
|||
} |
|||
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) |
|||
return dateInfo |
|||
} |
|||
|
|||
/** |
|||
* 比较时间大小 |
|||
*/ |
|||
dateCompare(startDate, endDate) { |
|||
// 计算截止时间
|
|||
startDate = new Date(startDate.replace('-', '/').replace('-', '/')) |
|||
// 计算详细项的截止时间
|
|||
endDate = new Date(endDate.replace('-', '/').replace('-', '/')) |
|||
if (startDate <= endDate) { |
|||
return true |
|||
} else { |
|||
return false |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 比较时间是否相等 |
|||
*/ |
|||
dateEqual(before, after) { |
|||
// 计算截止时间
|
|||
before = new Date(before.replace('-', '/').replace('-', '/')) |
|||
// 计算详细项的截止时间
|
|||
after = new Date(after.replace('-', '/').replace('-', '/')) |
|||
if (before.getTime() - after.getTime() === 0) { |
|||
return true |
|||
} else { |
|||
return false |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取日期范围内所有日期 |
|||
* @param {Object} begin |
|||
* @param {Object} end |
|||
*/ |
|||
geDateAll(begin, end) { |
|||
var arr = [] |
|||
var ab = begin.split('-') |
|||
var ae = end.split('-') |
|||
var db = new Date() |
|||
db.setFullYear(ab[0], ab[1] - 1, ab[2]) |
|||
var de = new Date() |
|||
de.setFullYear(ae[0], ae[1] - 1, ae[2]) |
|||
var unixDb = db.getTime() - 24 * 60 * 60 * 1000 |
|||
var unixDe = de.getTime() - 24 * 60 * 60 * 1000 |
|||
for (var k = unixDb; k <= unixDe;) { |
|||
k = k + 24 * 60 * 60 * 1000 |
|||
arr.push(this.getDate(new Date(parseInt(k))).fullDate) |
|||
} |
|||
return arr |
|||
} |
|||
/** |
|||
* 计算阴历日期显示 |
|||
*/ |
|||
getlunar(year, month, date) { |
|||
return CALENDAR.solar2lunar(year, month, date) |
|||
} |
|||
/** |
|||
* 设置打点 |
|||
*/ |
|||
setSelectInfo(data, value) { |
|||
this.selected = value |
|||
this._getWeek(data) |
|||
} |
|||
|
|||
/** |
|||
* 获取多选状态 |
|||
*/ |
|||
setMultiple(fullDate) { |
|||
let { |
|||
before, |
|||
after |
|||
} = this.multipleStatus |
|||
|
|||
if (!this.range) return |
|||
if (before && after) { |
|||
this.multipleStatus.before = '' |
|||
this.multipleStatus.after = '' |
|||
this.multipleStatus.data = [] |
|||
} else { |
|||
if (!before) { |
|||
this.multipleStatus.before = fullDate |
|||
} else { |
|||
this.multipleStatus.after = fullDate |
|||
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { |
|||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); |
|||
} else { |
|||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); |
|||
} |
|||
} |
|||
} |
|||
this._getWeek(fullDate) |
|||
} |
|||
|
|||
/** |
|||
* 获取每周数据 |
|||
* @param {Object} dateData |
|||
*/ |
|||
_getWeek(dateData) { |
|||
const { |
|||
year, |
|||
month |
|||
} = this.getDate(dateData) |
|||
let firstDay = new Date(year, month - 1, 1).getDay() |
|||
let currentDay = new Date(year, month, 0).getDate() |
|||
let dates = { |
|||
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
|
|||
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
|
|||
nextMonthDays: [], // 下个月开始几天
|
|||
weeks: [] |
|||
} |
|||
let canlender = [] |
|||
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) |
|||
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) |
|||
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) |
|||
let weeks = {} |
|||
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
|
|||
for (let i = 0; i < canlender.length; i++) { |
|||
if (i % 7 === 0) { |
|||
weeks[parseInt(i / 7)] = new Array(7) |
|||
} |
|||
weeks[parseInt(i / 7)][i % 7] = canlender[i] |
|||
} |
|||
this.canlender = canlender |
|||
this.weeks = weeks |
|||
} |
|||
|
|||
//静态方法
|
|||
// static init(date) {
|
|||
// if (!this.instance) {
|
|||
// this.instance = new Calendar(date);
|
|||
// }
|
|||
// return this.instance;
|
|||
// }
|
|||
} |
|||
|
|||
|
|||
export default Calendar |
@ -0,0 +1,88 @@ |
|||
{ |
|||
"id": "uni-calendar", |
|||
"displayName": "uni-calendar 日历", |
|||
"version": "1.4.5", |
|||
"description": "日历组件", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"uniui", |
|||
"日历", |
|||
"", |
|||
"打卡", |
|||
"日历选择" |
|||
], |
|||
"repository": "https://github.com/dcloudio/uni-ui", |
|||
"engines": { |
|||
"HBuilderX": "" |
|||
}, |
|||
"directories": { |
|||
"example": "../../temps/example_temps" |
|||
}, |
|||
"dcloudext": { |
|||
"category": [ |
|||
"前端组件", |
|||
"通用组件" |
|||
], |
|||
"sale": { |
|||
"regular": { |
|||
"price": "0.00" |
|||
}, |
|||
"sourcecode": { |
|||
"price": "0.00" |
|||
} |
|||
}, |
|||
"contact": { |
|||
"qq": "" |
|||
}, |
|||
"declaration": { |
|||
"ads": "无", |
|||
"data": "无", |
|||
"permissions": "无" |
|||
}, |
|||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
|||
}, |
|||
"uni_modules": { |
|||
"dependencies": [], |
|||
"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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,103 @@ |
|||
|
|||
|
|||
## Calendar 日历 |
|||
> **组件名:uni-calendar** |
|||
> 代码块: `uCalendar` |
|||
|
|||
|
|||
日历组件 |
|||
|
|||
> **注意事项** |
|||
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 |
|||
> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js) |
|||
> - 仅支持自定义组件模式 |
|||
> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date() |
|||
> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意 |
|||
> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动 |
|||
|
|||
|
|||
### 安装方式 |
|||
|
|||
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 |
|||
|
|||
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) |
|||
|
|||
### 基本用法 |
|||
|
|||
在 ``template`` 中使用组件 |
|||
|
|||
```html |
|||
<view> |
|||
<uni-calendar |
|||
:insert="true" |
|||
:lunar="true" |
|||
:start-date="'2019-3-2'" |
|||
:end-date="'2019-5-20'" |
|||
@change="change" |
|||
/> |
|||
</view> |
|||
``` |
|||
|
|||
### 通过方法打开日历 |
|||
|
|||
需要设置 `insert` 为 `false` |
|||
|
|||
```html |
|||
<view> |
|||
<uni-calendar |
|||
ref="calendar" |
|||
:insert="false" |
|||
@confirm="confirm" |
|||
/> |
|||
<button @click="open">打开日历</button> |
|||
</view> |
|||
``` |
|||
|
|||
```javascript |
|||
|
|||
export default { |
|||
data() { |
|||
return {}; |
|||
}, |
|||
methods: { |
|||
open(){ |
|||
this.$refs.calendar.open(); |
|||
}, |
|||
confirm(e) { |
|||
console.log(e); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
``` |
|||
|
|||
|
|||
## API |
|||
|
|||
### Calendar Props |
|||
|
|||
| 属性名 | 类型 | 默认值| 说明 | |
|||
| | | |
|||
| date | String |- | 自定义当前时间,默认为今天 | |
|||
| lunar | Boolean | false | 显示农历 | |
|||
| startDate | String |- | 日期选择范围-开始日期 | |
|||
| endDate | String |- | 日期选择范围-结束日期 | |
|||
| range | Boolean | false | 范围选择 | |
|||
| insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 | |
|||
|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 | |
|||
| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] | |
|||
|showMonth | Boolean | true | 是否显示月份为背景 | |
|||
|
|||
### Calendar Events |
|||
|
|||
| 事件名 | 说明 |返回值| |
|||
| | | | |
|||
| open | 弹出日历组件,`insert :false` 时生效|- | |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
## 组件示例 |
|||
|
|||
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar) |
@ -0,0 +1,26 @@ |
|||
## 1.3.1(2021-12-20) |
|||
- 修复 在vue页面下略缩图显示不正常的bug |
|||
## 1.3.0(2021-11-19) |
|||
- 重构插槽的用法 ,header 替换为 title |
|||
- 新增 actions 插槽 |
|||
- 新增 cover 封面图属性和插槽 |
|||
- 新增 padding 内容默认内边距离 |
|||
- 新增 margin 卡片默认外边距离 |
|||
- 新增 spacing 卡片默认内边距 |
|||
- 新增 shadow 卡片阴影属性 |
|||
- 取消 mode 属性,可使用组合插槽代替 |
|||
- 取消 note 属性 ,使用actions插槽代替 |
|||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
|||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card) |
|||
## 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.8(2021-07-01) |
|||
- 优化 图文卡片无图片加载时,提供占位图标 |
|||
- 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持) |
|||
- 修复 thumbnail 不存在仍然占位的 bug |
|||
## 1.1.7(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 1.1.6(2021-02-04) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,270 @@ |
|||
<template> |
|||
<view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}" |
|||
:style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}"> |
|||
<!-- 封面 --> |
|||
<slot name="cover"> |
|||
<view v-if="cover" class="uni-card__cover"> |
|||
<image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image> |
|||
</view> |
|||
</slot> |
|||
<slot name="title"> |
|||
<view v-if="title || extra" class="uni-card__header"> |
|||
<!-- 卡片标题 --> |
|||
<view class="uni-card__header-box" @click="onClick('title')"> |
|||
<view v-if="thumbnail" class="uni-card__header-avatar"> |
|||
<image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" /> |
|||
</view> |
|||
<view class="uni-card__header-content"> |
|||
<text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text> |
|||
<text v-if="title&&subTitle" |
|||
class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text> |
|||
</view> |
|||
</view> |
|||
<view class="uni-card__header-extra" @click="onClick('extra')"> |
|||
<text class="uni-card__header-extra-text">{{ extra }}</text> |
|||
</view> |
|||
</view> |
|||
</slot> |
|||
<!-- 卡片内容 --> |
|||
<view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')"> |
|||
<slot></slot> |
|||
</view> |
|||
<view class="uni-card__actions" @click="onClick('actions')"> |
|||
<slot name="actions"></slot> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
/** |
|||
* Card 卡片 |
|||
* @description 卡片视图组件 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=22 |
|||
* @property {String} title 标题文字 |
|||
* @property {String} subTitle 副标题 |
|||
* @property {Number} padding 内容内边距 |
|||
* @property {Number} margin 卡片外边距 |
|||
* @property {Number} spacing 卡片内边距 |
|||
* @property {String} extra 标题额外信息 |
|||
* @property {String} cover 封面图(本地路径需要引入) |
|||
* @property {String} thumbnail 标题左侧缩略图 |
|||
* @property {Boolean} is-full = [true | false] 卡片内容是否通栏,为 true 时将去除padding值 |
|||
* @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影 |
|||
* @property {String} shadow 卡片阴影 |
|||
* @property {Boolean} border 卡片边框 |
|||
* @event {Function} click 点击 Card 触发事件 |
|||
*/ |
|||
export default { |
|||
name: 'UniCard', |
|||
emits: ['click'], |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
subTitle: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
padding: { |
|||
type: String, |
|||
default: '10px' |
|||
}, |
|||
margin: { |
|||
type: String, |
|||
default: '15px' |
|||
}, |
|||
spacing: { |
|||
type: String, |
|||
default: '0 10px' |
|||
}, |
|||
extra: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
cover: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
thumbnail: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
isFull: { |
|||
// 内容区域是否通栏 |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
isShadow: { |
|||
// 是否开启阴影 |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
shadow: { |
|||
type: String, |
|||
default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)' |
|||
}, |
|||
border: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}, |
|||
methods: { |
|||
onClick(type) { |
|||
this.$emit('click', type) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
$uni-border-3: #EBEEF5 !default; |
|||
$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; |
|||
$uni-main-color: #3a3a3a !default; |
|||
$uni-base-color: #6a6a6a !default; |
|||
$uni-secondary-color: #909399 !default; |
|||
$uni-spacing-sm: 8px !default; |
|||
$uni-border-color:$uni-border-3; |
|||
$uni-shadow: $uni-shadow-base; |
|||
$uni-card-title: 15px; |
|||
$uni-cart-title-color:$uni-main-color; |
|||
$uni-card-subtitle: 12px; |
|||
$uni-cart-subtitle-color:$uni-secondary-color; |
|||
$uni-card-spacing: 10px; |
|||
$uni-card-content-color: $uni-base-color; |
|||
|
|||
.uni-card { |
|||
margin: $uni-card-spacing; |
|||
padding: 0 $uni-spacing-sm; |
|||
border-radius: 4px; |
|||
overflow: hidden; |
|||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; |
|||
background-color: #fff; |
|||
flex: 1; |
|||
|
|||
.uni-card__cover { |
|||
position: relative; |
|||
margin-top: $uni-card-spacing; |
|||
flex-direction: row; |
|||
overflow: hidden; |
|||
border-radius: 4px; |
|||
.uni-card__cover-image { |
|||
flex: 1; |
|||
// width: 100%; |
|||
/* #ifndef APP-PLUS */ |
|||
vertical-align: middle; |
|||
/* #endif */ |
|||
} |
|||
} |
|||
|
|||
.uni-card__header { |
|||
display: flex; |
|||
border-bottom: 1px $uni-border-color solid; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
padding: $uni-card-spacing; |
|||
overflow: hidden; |
|||
|
|||
.uni-card__header-box { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex: 1; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.uni-card__header-avatar { |
|||
width: 40px; |
|||
height: 40px; |
|||
overflow: hidden; |
|||
border-radius: 5px; |
|||
margin-right: $uni-card-spacing; |
|||
.uni-card__header-avatar-image { |
|||
flex: 1; |
|||
width: 40px; |
|||
height: 40px; |
|||
} |
|||
} |
|||
|
|||
.uni-card__header-content { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
flex: 1; |
|||
// height: 40px; |
|||
overflow: hidden; |
|||
|
|||
.uni-card__header-content-title { |
|||
font-size: $uni-card-title; |
|||
color: $uni-cart-title-color; |
|||
// line-height: 22px; |
|||
} |
|||
|
|||
.uni-card__header-content-subtitle { |
|||
font-size: $uni-card-subtitle; |
|||
margin-top: 5px; |
|||
color: $uni-cart-subtitle-color; |
|||
} |
|||
} |
|||
|
|||
.uni-card__header-extra { |
|||
line-height: 12px; |
|||
|
|||
.uni-card__header-extra-text { |
|||
font-size: 12px; |
|||
color: $uni-cart-subtitle-color; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.uni-card__content { |
|||
padding: $uni-card-spacing; |
|||
font-size: 14px; |
|||
color: $uni-card-content-color; |
|||
line-height: 22px; |
|||
} |
|||
|
|||
.uni-card__actions { |
|||
font-size: 12px; |
|||
} |
|||
} |
|||
|
|||
.uni-card--border { |
|||
border: 1px solid $uni-border-color; |
|||
} |
|||
|
|||
.uni-card--shadow { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
box-shadow: $uni-shadow; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.uni-card--full { |
|||
margin: 0; |
|||
border-left-width: 0; |
|||
border-left-width: 0; |
|||
border-radius: 0; |
|||
} |
|||
|
|||
/* #ifndef APP-NVUE */ |
|||
.uni-card--full:after { |
|||
border-radius: 0; |
|||
} |
|||
|
|||
/* #endif */ |
|||
.uni-ellipsis { |
|||
/* #ifndef APP-NVUE */ |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
/* #endif */ |
|||
/* #ifdef APP-NVUE */ |
|||
lines: 1; |
|||
/* #endif */ |
|||
} |
|||
</style> |
@ -0,0 +1,90 @@ |
|||
{ |
|||
"id": "uni-card", |
|||
"displayName": "uni-card 卡片", |
|||
"version": "1.3.1", |
|||
"description": "Card 组件,提供常见的卡片样式。", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"uniui", |
|||
"card", |
|||
"", |
|||
"卡片" |
|||
], |
|||
"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-icons", |
|||
"uni-scss" |
|||
], |
|||
"encrypt": [], |
|||
"platforms": { |
|||
"cloud": { |
|||
"tcb": "y", |
|||
"aliyun": "y" |
|||
}, |
|||
"client": { |
|||
"App": { |
|||
"app-vue": "y", |
|||
"app-nvue": "y" |
|||
}, |
|||
"H5-mobile": { |
|||
"Safari": "y", |
|||
"Android Browser": "y", |
|||
"微信浏览器(Android)": "y", |
|||
"QQ浏览器(Android)": "y" |
|||
}, |
|||
"H5-pc": { |
|||
"Chrome": "y", |
|||
"IE": "y", |
|||
"Edge": "y", |
|||
"Firefox": "y", |
|||
"Safari": "y" |
|||
}, |
|||
"小程序": { |
|||
"微信": "y", |
|||
"阿里": "y", |
|||
"百度": "y", |
|||
"字节跳动": "y", |
|||
"QQ": "y" |
|||
}, |
|||
"快应用": { |
|||
"华为": "u", |
|||
"联盟": "u" |
|||
}, |
|||
"Vue": { |
|||
"vue2": "y", |
|||
"vue3": "y" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
|
|||
|
|||
## Card 卡片 |
|||
> **组件名:uni-card** |
|||
> 代码块: `uCard` |
|||
|
|||
卡片视图组件。 |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
|||
|
|||
|
@ -0,0 +1,36 @@ |
|||
## 1.4.3(2022-01-25) |
|||
- 修复 初始化的时候 ,open 属性失效的bug |
|||
## 1.4.2(2022-01-21) |
|||
- 修复 微信小程序resize后组件收起的bug |
|||
## 1.4.1(2021-11-22) |
|||
- 修复 vue3中个别scss变量无法找到的问题 |
|||
## 1.4.0(2021-11-19) |
|||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
|||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse) |
|||
## 1.3.3(2021-08-17) |
|||
- 优化 show-arrow 属性默认为true |
|||
## 1.3.2(2021-08-17) |
|||
- 新增 show-arrow 属性,控制是否显示右侧箭头 |
|||
## 1.3.1(2021-07-30) |
|||
- 优化 vue3下小程序事件警告的问题 |
|||
## 1.3.0(2021-07-30) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 1.2.2(2021-07-21) |
|||
- 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug |
|||
## 1.2.1(2021-07-21) |
|||
- 优化 组件示例 |
|||
## 1.2.0(2021-07-21) |
|||
- 新增 组件折叠动画 |
|||
- 新增 value\v-model 属性 ,动态修改面板折叠状态 |
|||
- 新增 title 插槽 ,可定义面板标题 |
|||
- 新增 border 属性 ,显示隐藏面板内容分隔线 |
|||
- 新增 title-border 属性 ,显示隐藏面板标题分隔线 |
|||
- 修复 resize 方法失效的Bug |
|||
- 修复 change 事件返回参数不正确的Bug |
|||
- 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法 |
|||
## 1.1.7(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 1.1.6(2021-02-05) |
|||
- 优化 组件引用关系,通过uni_modules引用组件 |
|||
## 1.1.5(2021-02-05) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,402 @@ |
|||
<template> |
|||
<view class="uni-collapse-item"> |
|||
<!-- onClick(!isOpen) --> |
|||
<view @click="onClick(!isOpen)" class="uni-collapse-item__title" |
|||
:class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}"> |
|||
<view class="uni-collapse-item__title-wrap"> |
|||
<slot name="title"> |
|||
<view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}"> |
|||
<image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" /> |
|||
<text class="uni-collapse-item__title-text">{{ title }}</text> |
|||
</view> |
|||
</slot> |
|||
</view> |
|||
<view v-if="showArrow" |
|||
:class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }" |
|||
class="uni-collapse-item__title-arrow"> |
|||
<uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" /> |
|||
</view> |
|||
</view> |
|||
<view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}" |
|||
:style="{height: (isOpen?height:0) +'px'}"> |
|||
<view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content" |
|||
:class="{open:isheight,'uni-collapse-item--border':border&&isOpen}"> |
|||
<slot></slot> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
// #ifdef APP-NVUE |
|||
const dom = weex.requireModule('dom') |
|||
// #endif |
|||
/** |
|||
* CollapseItem 折叠面板子组件 |
|||
* @description 折叠面板子组件 |
|||
* @property {String} title 标题文字 |
|||
* @property {String} thumb 标题左侧缩略图 |
|||
* @property {String} name 唯一标志符 |
|||
* @property {Boolean} open = [true|false] 是否展开组件 |
|||
* @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线 |
|||
* @property {Boolean} border = [true|false] 是否显示分隔线 |
|||
* @property {Boolean} disabled = [true|false] 是否展开面板 |
|||
* @property {Boolean} showAnimation = [true|false] 开启动画 |
|||
* @property {Boolean} showArrow = [true|false] 是否显示右侧箭头 |
|||
*/ |
|||
export default { |
|||
name: 'uniCollapseItem', |
|||
props: { |
|||
// 列表标题 |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
name: { |
|||
type: [Number, String], |
|||
default: '' |
|||
}, |
|||
// 是否禁用 |
|||
disabled: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// #ifdef APP-PLUS |
|||
// 是否显示动画,app 端默认不开启动画,卡顿严重 |
|||
showAnimation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// #endif |
|||
// #ifndef APP-PLUS |
|||
// 是否显示动画 |
|||
showAnimation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// #endif |
|||
// 是否展开 |
|||
open: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 缩略图 |
|||
thumb: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
// 标题分隔线显示类型 |
|||
titleBorder: { |
|||
type: String, |
|||
default: 'auto' |
|||
}, |
|||
border: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
showArrow: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}, |
|||
data() { |
|||
// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug |
|||
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}` |
|||
return { |
|||
isOpen: false, |
|||
isheight: null, |
|||
height: 0, |
|||
elId, |
|||
nameSync: 0 |
|||
} |
|||
}, |
|||
watch: { |
|||
open(val) { |
|||
this.isOpen = val |
|||
this.onClick(val, 'init') |
|||
} |
|||
}, |
|||
updated(e) { |
|||
this.$nextTick(() => { |
|||
this.init(true) |
|||
}) |
|||
}, |
|||
created() { |
|||
this.collapse = this.getCollapse() |
|||
this.oldHeight = 0 |
|||
this.onClick(this.open, 'init') |
|||
}, |
|||
// #ifndef VUE3 |
|||
// TODO vue2 |
|||
destroyed() { |
|||
if (this.__isUnmounted) return |
|||
this.uninstall() |
|||
}, |
|||
// #endif |
|||
// #ifdef VUE3 |
|||
// TODO vue3 |
|||
unmounted() { |
|||
this.__isUnmounted = true |
|||
this.uninstall() |
|||
}, |
|||
// #endif |
|||
mounted() { |
|||
if (!this.collapse) return |
|||
if (this.name !== '') { |
|||
this.nameSync = this.name |
|||
} else { |
|||
this.nameSync = this.collapse.childrens.length + '' |
|||
} |
|||
if (this.collapse.names.indexOf(this.nameSync) === -1) { |
|||
this.collapse.names.push(this.nameSync) |
|||
} else { |
|||
console.warn(`name 值 ${this.nameSync} 重复`); |
|||
} |
|||
if (this.collapse.childrens.indexOf(this) === -1) { |
|||
this.collapse.childrens.push(this) |
|||
} |
|||
this.init() |
|||
}, |
|||
methods: { |
|||
init(type) { |
|||
// #ifndef APP-NVUE |
|||
this.getCollapseHeight(type) |
|||
// #endif |
|||
// #ifdef APP-NVUE |
|||
this.getNvueHwight(type) |
|||
// #endif |
|||
}, |
|||
uninstall() { |
|||
if (this.collapse) { |
|||
this.collapse.childrens.forEach((item, index) => { |
|||
if (item === this) { |
|||
this.collapse.childrens.splice(index, 1) |
|||
} |
|||
}) |
|||
this.collapse.names.forEach((item, index) => { |
|||
if (item === this.nameSync) { |
|||
this.collapse.names.splice(index, 1) |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
onClick(isOpen, type) { |
|||
if (this.disabled) return |
|||
this.isOpen = isOpen |
|||
if (this.isOpen && this.collapse) { |
|||
this.collapse.setAccordion(this) |
|||
} |
|||
if (type !== 'init') { |
|||
this.collapse.onChange(isOpen, this) |
|||
} |
|||
}, |
|||
getCollapseHeight(type, index = 0) { |
|||
const views = uni.createSelectorQuery().in(this) |
|||
views |
|||
.select(`#${this.elId}`) |
|||
.fields({ |
|||
size: true |
|||
}, data => { |
|||
// TODO 百度中可能获取不到节点信息 ,需要循环获取 |
|||
if (index >= 10) return |
|||
if (!data) { |
|||
index++ |
|||
this.getCollapseHeight(false, index) |
|||
return |
|||
} |
|||
// #ifdef APP-NVUE |
|||
this.height = data.height + 1 |
|||
// #endif |
|||
// #ifndef APP-NVUE |
|||
this.height = data.height |
|||
// #endif |
|||
this.isheight = true |
|||
if (type) return |
|||
this.onClick(this.isOpen, 'init') |
|||
}) |
|||
.exec() |
|||
}, |
|||
getNvueHwight(type) { |
|||
const result = dom.getComponentRect(this.$refs['collapse--hook'], option => { |
|||
if (option && option.result && option.size) { |
|||
// #ifdef APP-NVUE |
|||
this.height = option.size.height + 1 |
|||
// #endif |
|||
// #ifndef APP-NVUE |
|||
this.height = option.size.height |
|||
// #endif |
|||
this.isheight = true |
|||
if (type) return |
|||
this.onClick(this.open, 'init') |
|||
} |
|||
}) |
|||
}, |
|||
/** |
|||
* 获取父元素实例 |
|||
*/ |
|||
getCollapse(name = 'uniCollapse') { |
|||
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; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.uni-collapse-item { |
|||
/* #ifndef APP-NVUE */ |
|||
box-sizing: border-box; |
|||
|
|||
/* #endif */ |
|||
&__title { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
align-items: center; |
|||
transition: border-bottom-color .3s; |
|||
|
|||
// transition-property: border-bottom-color; |
|||
// transition-duration: 5s; |
|||
&-wrap { |
|||
width: 100%; |
|||
flex: 1; |
|||
|
|||
} |
|||
|
|||
&-box { |
|||
padding: 0 15px; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
height: 48px; |
|||
line-height: 48px; |
|||
background-color: #fff; |
|||
color: #303133; |
|||
font-size: 13px; |
|||
font-weight: 500; |
|||
/* #ifdef H5 */ |
|||
cursor: pointer; |
|||
outline: none; |
|||
|
|||
/* #endif */ |
|||
&.is-disabled { |
|||
.uni-collapse-item__title-text { |
|||
color: #999; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
&.uni-collapse-item-border { |
|||
border-bottom: 1px solid #ebeef5; |
|||
} |
|||
|
|||
&.is-open { |
|||
border-bottom-color: transparent; |
|||
} |
|||
|
|||
&-img { |
|||
height: 22px; |
|||
width: 22px; |
|||
margin-right: 10px; |
|||
} |
|||
|
|||
&-text { |
|||
flex: 1; |
|||
font-size: 14px; |
|||
/* #ifndef APP-NVUE */ |
|||
white-space: nowrap; |
|||
color: inherit; |
|||
/* #endif */ |
|||
/* #ifdef APP-NVUE */ |
|||
lines: 1; |
|||
/* #endif */ |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
|
|||
&-arrow { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
align-items: center; |
|||
justify-content: center; |
|||
width: 20px; |
|||
height: 20px; |
|||
margin-right: 10px; |
|||
transform: rotate(0deg); |
|||
|
|||
&-active { |
|||
transform: rotate(-180deg); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
&__wrap { |
|||
/* #ifndef APP-NVUE */ |
|||
will-change: height; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
background-color: #fff; |
|||
overflow: hidden; |
|||
position: relative; |
|||
height: 0; |
|||
|
|||
&.is--transition { |
|||
// transition: all 0.3s; |
|||
transition-property: height, border-bottom-width; |
|||
transition-duration: 0.3s; |
|||
/* #ifndef APP-NVUE */ |
|||
will-change: height; |
|||
/* #endif */ |
|||
} |
|||
|
|||
|
|||
|
|||
&-content { |
|||
position: absolute; |
|||
font-size: 13px; |
|||
color: #303133; |
|||
// transition: height 0.3s; |
|||
border-bottom-color: transparent; |
|||
border-bottom-style: solid; |
|||
border-bottom-width: 0; |
|||
|
|||
&.uni-collapse-item--border { |
|||
border-bottom-width: 1px; |
|||
border-bottom-color: red; |
|||
border-bottom-color: #ebeef5; |
|||
} |
|||
|
|||
&.open { |
|||
position: relative; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&--animation { |
|||
transition-property: transform; |
|||
transition-duration: 0.3s; |
|||
transition-timing-function: ease; |
|||
} |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,147 @@ |
|||
<template> |
|||
<view class="uni-collapse"> |
|||
<slot /> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
/** |
|||
* Collapse 折叠面板 |
|||
* @description 展示可以折叠 / 展开的内容区域 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=23 |
|||
* @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array) |
|||
* @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果 |
|||
* @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array |
|||
*/ |
|||
export default { |
|||
name: 'uniCollapse', |
|||
emits:['change','activeItem','input','update:modelValue'], |
|||
props: { |
|||
value: { |
|||
type: [String, Array], |
|||
default: '' |
|||
}, |
|||
modelValue: { |
|||
type: [String, Array], |
|||
default: '' |
|||
}, |
|||
accordion: { |
|||
// 是否开启手风琴效果 |
|||
type: [Boolean, String], |
|||
default: false |
|||
}, |
|||
}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
computed: { |
|||
// TODO 兼容 vue2 和 vue3 |
|||
dataValue() { |
|||
let value = (typeof this.value === 'string' && this.value === '') || |
|||
(Array.isArray(this.value) && this.value.length === 0) |
|||
let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') || |
|||
(Array.isArray(this.modelValue) && this.modelValue.length === 0) |
|||
if (value) { |
|||
return this.modelValue |
|||
} |
|||
if (modelValue) { |
|||
return this.value |
|||
} |
|||
|
|||
return this.value |
|||
} |
|||
}, |
|||
watch: { |
|||
dataValue(val) { |
|||
this.setOpen(val) |
|||
} |
|||
}, |
|||
created() { |
|||
this.childrens = [] |
|||
this.names = [] |
|||
}, |
|||
mounted() { |
|||
this.$nextTick(()=>{ |
|||
this.setOpen(this.dataValue) |
|||
}) |
|||
}, |
|||
methods: { |
|||
setOpen(val) { |
|||
let str = typeof val === 'string' |
|||
let arr = Array.isArray(val) |
|||
this.childrens.forEach((vm, index) => { |
|||
if (str) { |
|||
if (val === vm.nameSync) { |
|||
if (!this.accordion) { |
|||
console.warn('accordion 属性为 false ,v-model 类型应该为 array') |
|||
return |
|||
} |
|||
vm.isOpen = true |
|||
} |
|||
} |
|||
if (arr) { |
|||
val.forEach(v => { |
|||
if (v === vm.nameSync) { |
|||
if (this.accordion) { |
|||
console.warn('accordion 属性为 true ,v-model 类型应该为 string') |
|||
return |
|||
} |
|||
vm.isOpen = true |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
this.emit(val) |
|||
}, |
|||
setAccordion(self) { |
|||
if (!this.accordion) return |
|||
this.childrens.forEach((vm, index) => { |
|||
if (self !== vm) { |
|||
vm.isOpen = false |
|||
} |
|||
}) |
|||
}, |
|||
resize() { |
|||
this.childrens.forEach((vm, index) => { |
|||
// #ifndef APP-NVUE |
|||
vm.getCollapseHeight() |
|||
// #endif |
|||
// #ifdef APP-NVUE |
|||
vm.getNvueHwight() |
|||
// #endif |
|||
}) |
|||
}, |
|||
onChange(isOpen, self) { |
|||
let activeItem = [] |
|||
|
|||
if (this.accordion) { |
|||
activeItem = isOpen ? self.nameSync : '' |
|||
} else { |
|||
this.childrens.forEach((vm, index) => { |
|||
if (vm.isOpen) { |
|||
activeItem.push(vm.nameSync) |
|||
} |
|||
}) |
|||
} |
|||
this.$emit('change', activeItem) |
|||
this.emit(activeItem) |
|||
}, |
|||
emit(val){ |
|||
this.$emit('input', val) |
|||
this.$emit('update:modelValue', val) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" > |
|||
.uni-collapse { |
|||
/* #ifndef APP-NVUE */ |
|||
width: 100%; |
|||
display: flex; |
|||
/* #endif */ |
|||
/* #ifdef APP-NVUE */ |
|||
flex: 1; |
|||
/* #endif */ |
|||
flex-direction: column; |
|||
background-color: #fff; |
|||
} |
|||
</style> |
@ -0,0 +1,89 @@ |
|||
{ |
|||
"id": "uni-collapse", |
|||
"displayName": "uni-collapse 折叠面板", |
|||
"version": "1.4.3", |
|||
"description": "Collapse 组件,可以折叠 / 展开的内容区域。", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"折叠", |
|||
"折叠面板", |
|||
"手风琴" |
|||
], |
|||
"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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
|
|||
|
|||
## Collapse 折叠面板 |
|||
> **组件名:uni-collapse** |
|||
> 代码块: `uCollapse` |
|||
> 关联组件:`uni-collapse-item`、`uni-icons`。 |
|||
|
|||
|
|||
折叠面板用来折叠/显示过长的内容或者是列表。通常是在多内容分类项使用,折叠不重要的内容,显示重要内容。点击可以展开折叠部分。 |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-collapse) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
@ -0,0 +1,15 @@ |
|||
## 1.0.1(2021-11-23) |
|||
- 优化 label、label-width 属性 |
|||
## 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-combox](https://uniapp.dcloud.io/component/uniui/uni-combox) |
|||
## 0.1.0(2021-07-30) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 0.0.6(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 0.0.5(2021-04-21) |
|||
- 优化 添加依赖 uni-icons, 导入后自动下载依赖 |
|||
## 0.0.4(2021-02-05) |
|||
- 优化 组件引用关系,通过uni_modules引用组件 |
|||
## 0.0.3(2021-02-04) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,275 @@ |
|||
<template> |
|||
<view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'"> |
|||
<view v-if="label" class="uni-combox__label" :style="labelStyle"> |
|||
<text>{{label}}</text> |
|||
</view> |
|||
<view class="uni-combox__input-box"> |
|||
<input class="uni-combox__input" type="text" :placeholder="placeholder" |
|||
placeholder-class="uni-combox__input-plac" v-model="inputVal" @input="onInput" @focus="onFocus" |
|||
@blur="onBlur" /> |
|||
<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector"> |
|||
</uni-icons> |
|||
</view> |
|||
<view class="uni-combox__selector" v-if="showSelector"> |
|||
<view class="uni-popper__arrow"></view> |
|||
<scroll-view scroll-y="true" class="uni-combox__selector-scroll"> |
|||
<view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0"> |
|||
<text>{{emptyTips}}</text> |
|||
</view> |
|||
<view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index" |
|||
@click="onSelectorClick(index)"> |
|||
<text>{{item}}</text> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
/** |
|||
* Combox 组合输入框 |
|||
* @description 组合输入框一般用于既可以输入也可以选择的场景 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=1261 |
|||
* @property {String} label 左侧文字 |
|||
* @property {String} labelWidth 左侧内容宽度 |
|||
* @property {String} placeholder 输入框占位符 |
|||
* @property {Array} candidates 候选项列表 |
|||
* @property {String} emptyTips 筛选结果为空时显示的文字 |
|||
* @property {String} value 组合框的值 |
|||
*/ |
|||
export default { |
|||
name: 'uniCombox', |
|||
emits: ['input', 'update:modelValue'], |
|||
props: { |
|||
border: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
label: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
labelWidth: { |
|||
type: String, |
|||
default: 'auto' |
|||
}, |
|||
placeholder: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
candidates: { |
|||
type: Array, |
|||
default () { |
|||
return [] |
|||
} |
|||
}, |
|||
emptyTips: { |
|||
type: String, |
|||
default: '无匹配项' |
|||
}, |
|||
// #ifndef VUE3 |
|||
value: { |
|||
type: [String, Number], |
|||
default: '' |
|||
}, |
|||
// #endif |
|||
// #ifdef VUE3 |
|||
modelValue: { |
|||
type: [String, Number], |
|||
default: '' |
|||
}, |
|||
// #endif |
|||
}, |
|||
data() { |
|||
return { |
|||
showSelector: false, |
|||
inputVal: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
labelStyle() { |
|||
if (this.labelWidth === 'auto') { |
|||
return "" |
|||
} |
|||
return `width: ${this.labelWidth}` |
|||
}, |
|||
filterCandidates() { |
|||
return this.candidates.filter((item) => { |
|||
return item.toString().indexOf(this.inputVal) > -1 |
|||
}) |
|||
}, |
|||
filterCandidatesLength() { |
|||
return this.filterCandidates.length |
|||
} |
|||
}, |
|||
watch: { |
|||
// #ifndef VUE3 |
|||
value: { |
|||
handler(newVal) { |
|||
this.inputVal = newVal |
|||
}, |
|||
immediate: true |
|||
}, |
|||
// #endif |
|||
// #ifdef VUE3 |
|||
modelValue: { |
|||
handler(newVal) { |
|||
this.inputVal = newVal |
|||
}, |
|||
immediate: true |
|||
}, |
|||
// #endif |
|||
}, |
|||
methods: { |
|||
toggleSelector() { |
|||
this.showSelector = !this.showSelector |
|||
}, |
|||
onFocus() { |
|||
this.showSelector = true |
|||
}, |
|||
onBlur() { |
|||
setTimeout(() => { |
|||
this.showSelector = false |
|||
}, 153) |
|||
}, |
|||
onSelectorClick(index) { |
|||
this.inputVal = this.filterCandidates[index] |
|||
this.showSelector = false |
|||
this.$emit('input', this.inputVal) |
|||
this.$emit('update:modelValue', this.inputVal) |
|||
}, |
|||
onInput() { |
|||
setTimeout(() => { |
|||
this.$emit('input', this.inputVal) |
|||
this.$emit('update:modelValue', this.inputVal) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" > |
|||
.uni-combox { |
|||
font-size: 14px; |
|||
border: 1px solid #DCDFE6; |
|||
border-radius: 4px; |
|||
padding: 6px 10px; |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
// height: 40px; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
// border-bottom: solid 1px #DDDDDD; |
|||
} |
|||
|
|||
.uni-combox__label { |
|||
font-size: 16px; |
|||
line-height: 22px; |
|||
padding-right: 10px; |
|||
color: #999999; |
|||
} |
|||
|
|||
.uni-combox__input-box { |
|||
position: relative; |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
/* #endif */ |
|||
flex: 1; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
} |
|||
|
|||
.uni-combox__input { |
|||
flex: 1; |
|||
font-size: 14px; |
|||
height: 22px; |
|||
line-height: 22px; |
|||
} |
|||
|
|||
.uni-combox__input-plac { |
|||
font-size: 14px; |
|||
color: #999; |
|||
} |
|||
|
|||
.uni-combox__selector { |
|||
/* #ifndef APP-NVUE */ |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
position: absolute; |
|||
top: calc(100% + 12px); |
|||
left: 0; |
|||
width: 100%; |
|||
background-color: #FFFFFF; |
|||
border: 1px solid #EBEEF5; |
|||
border-radius: 6px; |
|||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
|||
z-index: 2; |
|||
padding: 4px 0; |
|||
} |
|||
|
|||
.uni-combox__selector-scroll { |
|||
/* #ifndef APP-NVUE */ |
|||
max-height: 200px; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.uni-combox__selector-empty, |
|||
.uni-combox__selector-item { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
cursor: pointer; |
|||
/* #endif */ |
|||
line-height: 36px; |
|||
font-size: 14px; |
|||
text-align: center; |
|||
// border-bottom: solid 1px #DDDDDD; |
|||
padding: 0px 10px; |
|||
} |
|||
|
|||
.uni-combox__selector-item:hover { |
|||
background-color: #f9f9f9; |
|||
} |
|||
|
|||
.uni-combox__selector-empty:last-child, |
|||
.uni-combox__selector-item:last-child { |
|||
/* #ifndef APP-NVUE */ |
|||
border-bottom: none; |
|||
/* #endif */ |
|||
} |
|||
|
|||
// picker 弹出层通用的指示小三角 |
|||
.uni-popper__arrow, |
|||
.uni-popper__arrow::after { |
|||
position: absolute; |
|||
display: block; |
|||
width: 0; |
|||
height: 0; |
|||
border-color: transparent; |
|||
border-style: solid; |
|||
border-width: 6px; |
|||
} |
|||
|
|||
.uni-popper__arrow { |
|||
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
|||
top: -6px; |
|||
left: 10%; |
|||
margin-right: 3px; |
|||
border-top-width: 0; |
|||
border-bottom-color: #EBEEF5; |
|||
} |
|||
|
|||
.uni-popper__arrow::after { |
|||
content: " "; |
|||
top: 1px; |
|||
margin-left: -6px; |
|||
border-top-width: 0; |
|||
border-bottom-color: #fff; |
|||
} |
|||
|
|||
.uni-combox__no-border { |
|||
border: none; |
|||
} |
|||
</style> |
@ -0,0 +1,90 @@ |
|||
{ |
|||
"id": "uni-combox", |
|||
"displayName": "uni-combox 组合框", |
|||
"version": "1.0.1", |
|||
"description": "可以选择也可以输入的表单项 ", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"uniui", |
|||
"combox", |
|||
"组合框", |
|||
"select" |
|||
], |
|||
"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": "n" |
|||
}, |
|||
"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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
|
|||
|
|||
## Combox 组合框 |
|||
> **组件名:uni-combox** |
|||
> 代码块: `uCombox` |
|||
|
|||
|
|||
组合框组件。 |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-combox) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
@ -0,0 +1,24 @@ |
|||
## 1.2.2(2022-01-19) |
|||
- 修复 在微信小程序中样式不生效的bug |
|||
## 1.2.1(2022-01-18) |
|||
- 新增 update 方法 ,在动态更新时间后,刷新组件 |
|||
## 1.2.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-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown) |
|||
## 1.1.3(2021-10-18) |
|||
- 重构 |
|||
- 新增 font-size 支持自定义字体大小 |
|||
## 1.1.2(2021-08-24) |
|||
- 新增 支持国际化 |
|||
## 1.1.1(2021-07-30) |
|||
- 优化 vue3下小程序事件警告的问题 |
|||
## 1.1.0(2021-07-30) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 1.0.5(2021-06-18) |
|||
- 修复 uni-countdown 重复赋值跳两秒的 bug |
|||
## 1.0.4(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 1.0.3(2021-05-08) |
|||
- 修复 uni-countdown 不能控制倒计时的 bug |
|||
## 1.0.2(2021-02-04) |
|||
- 调整为uni_modules目录规范 |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"uni-countdown.day": "day", |
|||
"uni-countdown.h": "h", |
|||
"uni-countdown.m": "m", |
|||
"uni-countdown.s": "s" |
|||
} |
@ -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,6 @@ |
|||
{ |
|||
"uni-countdown.day": "天", |
|||
"uni-countdown.h": "时", |
|||
"uni-countdown.m": "分", |
|||
"uni-countdown.s": "秒" |
|||
} |
@ -0,0 +1,6 @@ |
|||
{ |
|||
"uni-countdown.day": "天", |
|||
"uni-countdown.h": "時", |
|||
"uni-countdown.m": "分", |
|||
"uni-countdown.s": "秒" |
|||
} |
@ -0,0 +1,271 @@ |
|||
<template> |
|||
<view class="uni-countdown"> |
|||
<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text> |
|||
<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text> |
|||
<text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text> |
|||
<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text> |
|||
<text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text> |
|||
<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text> |
|||
<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text> |
|||
<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
import { |
|||
initVueI18n |
|||
} from '@dcloudio/uni-i18n' |
|||
import messages from './i18n/index.js' |
|||
const { |
|||
t |
|||
} = initVueI18n(messages) |
|||
/** |
|||
* Countdown 倒计时 |
|||
* @description 倒计时组件 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=25 |
|||
* @property {String} backgroundColor 背景色 |
|||
* @property {String} color 文字颜色 |
|||
* @property {Number} day 天数 |
|||
* @property {Number} hour 小时 |
|||
* @property {Number} minute 分钟 |
|||
* @property {Number} second 秒 |
|||
* @property {Number} timestamp 时间戳 |
|||
* @property {Boolean} showDay = [true|false] 是否显示天数 |
|||
* @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符 |
|||
* @property {String} splitorColor 分割符号颜色 |
|||
* @event {Function} timeup 倒计时时间到触发事件 |
|||
* @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown> |
|||
*/ |
|||
export default { |
|||
name: 'UniCountdown', |
|||
emits: ['timeup'], |
|||
props: { |
|||
showDay: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
showColon: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
start: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
backgroundColor: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
color: { |
|||
type: String, |
|||
default: '#333' |
|||
}, |
|||
fontSize: { |
|||
type: Number, |
|||
default: 14 |
|||
}, |
|||
splitorColor: { |
|||
type: String, |
|||
default: '#333' |
|||
}, |
|||
day: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
hour: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
minute: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
second: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
timestamp: { |
|||
type: Number, |
|||
default: 0 |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
timer: null, |
|||
syncFlag: false, |
|||
d: '00', |
|||
h: '00', |
|||
i: '00', |
|||
s: '00', |
|||
leftTime: 0, |
|||
seconds: 0 |
|||
} |
|||
}, |
|||
computed: { |
|||
dayText() { |
|||
return t("uni-countdown.day") |
|||
}, |
|||
hourText(val) { |
|||
return t("uni-countdown.h") |
|||
}, |
|||
minuteText(val) { |
|||
return t("uni-countdown.m") |
|||
}, |
|||
secondText(val) { |
|||
return t("uni-countdown.s") |
|||
}, |
|||
timeStyle() { |
|||
const { |
|||
color, |
|||
backgroundColor, |
|||
fontSize |
|||
} = this |
|||
return { |
|||
color, |
|||
backgroundColor, |
|||
fontSize: `${fontSize}px`, |
|||
width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放 |
|||
lineHeight: `${fontSize * 20 / 14}px`, |
|||
borderRadius: `${fontSize * 3 / 14}px`, |
|||
} |
|||
}, |
|||
splitorStyle() { |
|||
const { splitorColor, fontSize, backgroundColor } = this |
|||
return { |
|||
color: splitorColor, |
|||
fontSize: `${fontSize * 12 / 14}px`, |
|||
margin: backgroundColor ? `${fontSize * 4 / 14}px` : '' |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
day(val) { |
|||
this.changeFlag() |
|||
}, |
|||
hour(val) { |
|||
this.changeFlag() |
|||
}, |
|||
minute(val) { |
|||
this.changeFlag() |
|||
}, |
|||
second(val) { |
|||
this.changeFlag() |
|||
}, |
|||
start: { |
|||
immediate: true, |
|||
handler(newVal, oldVal) { |
|||
if (newVal) { |
|||
this.startData(); |
|||
} else { |
|||
if (!oldVal) return |
|||
clearInterval(this.timer) |
|||
} |
|||
} |
|||
|
|||
} |
|||
}, |
|||
created: function(e) { |
|||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
|||
this.countDown() |
|||
}, |
|||
// #ifndef VUE3 |
|||
destroyed() { |
|||
clearInterval(this.timer) |
|||
}, |
|||
// #endif |
|||
// #ifdef VUE3 |
|||
unmounted() { |
|||
clearInterval(this.timer) |
|||
}, |
|||
// #endif |
|||
methods: { |
|||
toSeconds(timestamp, day, hours, minutes, seconds) { |
|||
if (timestamp) { |
|||
return timestamp - parseInt(new Date().getTime() / 1000, 10) |
|||
} |
|||
return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds |
|||
}, |
|||
timeUp() { |
|||
clearInterval(this.timer) |
|||
this.$emit('timeup') |
|||
}, |
|||
countDown() { |
|||
let seconds = this.seconds |
|||
let [day, hour, minute, second] = [0, 0, 0, 0] |
|||
if (seconds > 0) { |
|||
day = Math.floor(seconds / (60 * 60 * 24)) |
|||
hour = Math.floor(seconds / (60 * 60)) - (day * 24) |
|||
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60) |
|||
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60) |
|||
} else { |
|||
this.timeUp() |
|||
} |
|||
if (day < 10) { |
|||
day = '0' + day |
|||
} |
|||
if (hour < 10) { |
|||
hour = '0' + hour |
|||
} |
|||
if (minute < 10) { |
|||
minute = '0' + minute |
|||
} |
|||
if (second < 10) { |
|||
second = '0' + second |
|||
} |
|||
this.d = day |
|||
this.h = hour |
|||
this.i = minute |
|||
this.s = second |
|||
}, |
|||
startData() { |
|||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
|||
if (this.seconds <= 0) { |
|||
this.seconds = this.toSeconds(0, 0, 0, 0, 0) |
|||
this.countDown() |
|||
return |
|||
} |
|||
clearInterval(this.timer) |
|||
this.countDown() |
|||
this.timer = setInterval(() => { |
|||
this.seconds-- |
|||
if (this.seconds < 0) { |
|||
this.timeUp() |
|||
return |
|||
} |
|||
this.countDown() |
|||
}, 1000) |
|||
}, |
|||
update(){ |
|||
this.startData(); |
|||
}, |
|||
changeFlag() { |
|||
if (!this.syncFlag) { |
|||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second) |
|||
this.startData(); |
|||
this.syncFlag = true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
$font-size: 14px; |
|||
|
|||
.uni-countdown { |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
|
|||
&__splitor { |
|||
margin: 0 2px; |
|||
font-size: $font-size; |
|||
color: #333; |
|||
} |
|||
|
|||
&__number { |
|||
border-radius: 3px; |
|||
text-align: center; |
|||
font-size: $font-size; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,86 @@ |
|||
{ |
|||
"id": "uni-countdown", |
|||
"displayName": "uni-countdown 倒计时", |
|||
"version": "1.2.2", |
|||
"description": "CountDown 倒计时组件", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"uniui", |
|||
"countdown", |
|||
"倒计时" |
|||
], |
|||
"repository": "https://github.com/dcloudio/uni-ui", |
|||
"engines": { |
|||
"HBuilderX": "" |
|||
}, |
|||
"directories": { |
|||
"example": "../../temps/example_temps" |
|||
}, |
|||
"dcloudext": { |
|||
"category": [ |
|||
"前端组件", |
|||
"通用组件" |
|||
], |
|||
"sale": { |
|||
"regular": { |
|||
"price": "0.00" |
|||
}, |
|||
"sourcecode": { |
|||
"price": "0.00" |
|||
} |
|||
}, |
|||
"contact": { |
|||
"qq": "" |
|||
}, |
|||
"declaration": { |
|||
"ads": "无", |
|||
"data": "无", |
|||
"permissions": "无" |
|||
}, |
|||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
|||
}, |
|||
"uni_modules": { |
|||
"dependencies": ["uni-scss"], |
|||
"encrypt": [], |
|||
"platforms": { |
|||
"cloud": { |
|||
"tcb": "y", |
|||
"aliyun": "y" |
|||
}, |
|||
"client": { |
|||
"App": { |
|||
"app-vue": "y", |
|||
"app-nvue": "y" |
|||
}, |
|||
"H5-mobile": { |
|||
"Safari": "y", |
|||
"Android Browser": "y", |
|||
"微信浏览器(Android)": "y", |
|||
"QQ浏览器(Android)": "y" |
|||
}, |
|||
"H5-pc": { |
|||
"Chrome": "y", |
|||
"IE": "y", |
|||
"Edge": "y", |
|||
"Firefox": "y", |
|||
"Safari": "y" |
|||
}, |
|||
"小程序": { |
|||
"微信": "y", |
|||
"阿里": "y", |
|||
"百度": "y", |
|||
"字节跳动": "y", |
|||
"QQ": "y" |
|||
}, |
|||
"快应用": { |
|||
"华为": "u", |
|||
"联盟": "u" |
|||
}, |
|||
"Vue": { |
|||
"vue2": "y", |
|||
"vue3": "y" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,10 @@ |
|||
|
|||
|
|||
## CountDown 倒计时 |
|||
> **组件名:uni-countdown** |
|||
> 代码块: `uCountDown` |
|||
|
|||
倒计时组件。 |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
@ -0,0 +1,43 @@ |
|||
## 1.0.2(2022-06-30) |
|||
- 优化 在 uni-forms 中的依赖注入方式 |
|||
## 1.0.1(2022-02-07) |
|||
- 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug |
|||
## 1.0.0(2021-11-19) |
|||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
|||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) |
|||
## 0.2.5(2021-08-23) |
|||
- 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题 |
|||
## 0.2.4(2021-08-17) |
|||
- 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题 |
|||
## 0.2.3(2021-08-11) |
|||
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 |
|||
## 0.2.2(2021-07-30) |
|||
- 优化 在uni-forms组件,与label不对齐的问题 |
|||
## 0.2.1(2021-07-27) |
|||
- 修复 单选默认值为0不能选中的Bug |
|||
## 0.2.0(2021-07-13) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 0.1.11(2021-07-06) |
|||
- 优化 删除无用日志 |
|||
## 0.1.10(2021-07-05) |
|||
- 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题 |
|||
## 0.1.9(2021-07-05) |
|||
- 修复 nvue 黑框样式问题 |
|||
## 0.1.8(2021-06-28) |
|||
- 修复 selectedTextColor 属性不生效的Bug |
|||
## 0.1.7(2021-06-02) |
|||
- 新增 map 属性,可以方便映射text/value属性 |
|||
## 0.1.6(2021-05-26) |
|||
- 修复 不关联服务空间的情况下组件报错的Bug |
|||
## 0.1.5(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 0.1.4(2021-04-09) |
|||
- 修复 nvue 下无法选中的问题 |
|||
## 0.1.3(2021-03-22) |
|||
- 新增 disabled属性 |
|||
## 0.1.2(2021-02-24) |
|||
- 优化 默认颜色显示 |
|||
## 0.1.1(2021-02-24) |
|||
- 新增 支持nvue |
|||
## 0.1.0(2021-02-18) |
|||
- “暂无数据”显示居中 |