-
3.gitignore
-
32App.vue
-
92README.md
-
174components/footerBar.vue
-
20index.html
-
111main.js
-
60manifest.json
-
58pages.json
-
28pages/home/deepExploration.vue
-
28pages/home/deepMate.vue
-
28pages/home/home.vue
-
28pages/home/marketSituation.vue
-
28pages/home/member.vue
-
BINstatic/c1.png
-
BINstatic/c2.png
-
BINstatic/c3.png
-
BINstatic/c4.png
-
BINstatic/c5.png
-
BINstatic/c6.png
-
BINstatic/c7.png
-
BINstatic/c8.png
-
BINstatic/c9.png
-
20static/customicons.css
-
BINstatic/customicons.ttf
-
BINstatic/footBar-image/c1.png
-
BINstatic/footBar-image/c2.png
-
BINstatic/footBar-image/c4.png
-
BINstatic/footBar-image/c5.png
-
BINstatic/footBar-image/logo.png
-
14static/language/en.js
-
14static/language/ms.js
-
14static/language/th.js
-
14static/language/vi.js
-
15static/language/zh_CN.js
-
15static/language/zh_HK.js
-
BINstatic/logo.png
-
BINstatic/uni.png
-
1uni.scss
-
33uni_modules/uni-badge/changelog.md
-
268uni_modules/uni-badge/components/uni-badge/uni-badge.vue
-
85uni_modules/uni-badge/package.json
-
10uni_modules/uni-badge/readme.md
-
6uni_modules/uni-breadcrumb/changelog.md
-
126uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
-
46uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
-
88uni_modules/uni-breadcrumb/package.json
-
66uni_modules/uni-breadcrumb/readme.md
-
28uni_modules/uni-calendar/changelog.md
-
546uni_modules/uni-calendar/components/uni-calendar/calendar.js
-
12uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
-
8uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
-
12uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
-
12uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
-
187uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
-
567uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
-
360uni_modules/uni-calendar/components/uni-calendar/util.js
-
85uni_modules/uni-calendar/package.json
-
103uni_modules/uni-calendar/readme.md
-
26uni_modules/uni-card/changelog.md
-
270uni_modules/uni-card/components/uni-card/uni-card.vue
-
90uni_modules/uni-card/package.json
-
12uni_modules/uni-card/readme.md
-
38uni_modules/uni-collapse/changelog.md
-
402uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
-
147uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
-
86uni_modules/uni-collapse/package.json
-
12uni_modules/uni-collapse/readme.md
-
15uni_modules/uni-combox/changelog.md
-
275uni_modules/uni-combox/components/uni-combox/uni-combox.vue
-
90uni_modules/uni-combox/package.json
-
11uni_modules/uni-combox/readme.md
-
26uni_modules/uni-countdown/changelog.md
-
6uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
-
8uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
-
6uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
-
6uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
-
281uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
-
83uni_modules/uni-countdown/package.json
-
10uni_modules/uni-countdown/readme.md
-
49uni_modules/uni-data-checkbox/changelog.md
-
849uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
-
84uni_modules/uni-data-checkbox/package.json
-
18uni_modules/uni-data-checkbox/readme.md
-
77uni_modules/uni-data-picker/changelog.md
-
45uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
-
380uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue
-
551uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
-
1uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
-
622uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
-
693uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
-
76uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
-
69uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
-
323uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
-
91uni_modules/uni-data-picker/package.json
-
22uni_modules/uni-data-picker/readme.md
-
39uni_modules/uni-data-select/changelog.md
-
562uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
-
86uni_modules/uni-data-select/package.json
-
8uni_modules/uni-data-select/readme.md
-
10uni_modules/uni-dateformat/changelog.md
@ -0,0 +1,3 @@ |
|||||
|
/unpackage/ |
||||
|
/uniCloud-aliyun/ |
||||
|
/node_modules/ |
||||
@ -0,0 +1,32 @@ |
|||||
|
<script> |
||||
|
export default { |
||||
|
onLaunch: function() { |
||||
|
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!') |
||||
|
console.log('App Launch') |
||||
|
}, |
||||
|
onShow: function() { |
||||
|
console.log('App Show') |
||||
|
}, |
||||
|
onHide: function() { |
||||
|
console.log('App Hide') |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
/*每个页面公共css */ |
||||
|
@import '@/uni_modules/uni-scss/index.scss'; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
@import '@/static/customicons.css'; |
||||
|
// 设置整个项目的背景色 |
||||
|
page { |
||||
|
background-color: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
/* #endif */ |
||||
|
.example-info { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
padding: 10px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,92 @@ |
|||||
|
# DeepChartApp |
||||
|
|
||||
|
|
||||
|
|
||||
|
## Getting started |
||||
|
|
||||
|
To make it easy for you to get started with GitLab, here's a list of recommended next steps. |
||||
|
|
||||
|
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! |
||||
|
|
||||
|
## Add your files |
||||
|
|
||||
|
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files |
||||
|
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: |
||||
|
|
||||
|
``` |
||||
|
cd existing_repo |
||||
|
git remote add origin http://e5dd567c94e5/TeachGroup/ClientGroup/deepchartapp.git |
||||
|
git branch -M master |
||||
|
git push -uf origin master |
||||
|
``` |
||||
|
|
||||
|
## Integrate with your tools |
||||
|
|
||||
|
- [ ] [Set up project integrations](http://e5dd567c94e5/TeachGroup/ClientGroup/deepchartapp/-/settings/integrations) |
||||
|
|
||||
|
## Collaborate with your team |
||||
|
|
||||
|
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) |
||||
|
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) |
||||
|
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) |
||||
|
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) |
||||
|
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) |
||||
|
|
||||
|
## Test and Deploy |
||||
|
|
||||
|
Use the built-in continuous integration in GitLab. |
||||
|
|
||||
|
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) |
||||
|
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) |
||||
|
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) |
||||
|
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) |
||||
|
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) |
||||
|
|
||||
|
*** |
||||
|
|
||||
|
# Editing this README |
||||
|
|
||||
|
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. |
||||
|
|
||||
|
## Suggestions for a good README |
||||
|
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. |
||||
|
|
||||
|
## Name |
||||
|
Choose a self-explaining name for your project. |
||||
|
|
||||
|
## Description |
||||
|
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. |
||||
|
|
||||
|
## Badges |
||||
|
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. |
||||
|
|
||||
|
## Visuals |
||||
|
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. |
||||
|
|
||||
|
## Installation |
||||
|
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. |
||||
|
|
||||
|
## Usage |
||||
|
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. |
||||
|
|
||||
|
## Support |
||||
|
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. |
||||
|
|
||||
|
## Roadmap |
||||
|
If you have ideas for releases in the future, it is a good idea to list them in the README. |
||||
|
|
||||
|
## Contributing |
||||
|
State if you are open to contributions and what your requirements are for accepting them. |
||||
|
|
||||
|
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. |
||||
|
|
||||
|
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. |
||||
|
|
||||
|
## Authors and acknowledgment |
||||
|
Show your appreciation to those who have contributed to the project. |
||||
|
|
||||
|
## License |
||||
|
For open source projects, say how it is licensed. |
||||
|
|
||||
|
## Project status |
||||
|
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. |
||||
@ -0,0 +1,174 @@ |
|||||
|
<template> |
||||
|
<view class="static-footer-bar" :style="{ 'padding-bottom': safeAreaInsets.bottom + 'px' }"> |
||||
|
<view class="static-footer-li ellipsis" @click="tabChange(1)"> |
||||
|
<image src="../static/footBar-image/c1.png" class="static-footer-li-icon" v-if="type != 'home'"></image> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" v-if="type == 'home'"></image> |
||||
|
<view :class="type == 'home' ? 'static-footer-li-title1' : 'static-footer-li-title'"> |
||||
|
{{ $t('components.footerBar.homepage') }}</view> |
||||
|
</view> |
||||
|
<view class="static-footer-li ellipsis" @click="tabChange(2)"> |
||||
|
<image src="../static/footBar-image/c2.png" class="static-footer-li-icon" v-if="type != 'marketSituation'"> |
||||
|
</image> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" |
||||
|
v-if="type == 'marketSituation'"></image> |
||||
|
<view :class="type == 'marketSituation' ? 'static-footer-li-title1' : 'static-footer-li-title'"> |
||||
|
{{ $t('components.footerBar.marketSituation') }}</view> |
||||
|
</view> |
||||
|
<view class="static-footer-li ellipsis" @click="tabChange(3)"> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" v-if="type != 'deepMate'"></image> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" v-if="type == 'deepMate'"> |
||||
|
</image> |
||||
|
<view :class="type == 'deepMate' ? 'static-footer-li-title1' : 'static-footer-li-title'"> |
||||
|
{{ $t('components.footerBar.deepMate') }}</view> |
||||
|
</view> |
||||
|
<view class="static-footer-li ellipsis" @click="tabChange(4)"> |
||||
|
<image src="../static/footBar-image/c4.png" class="static-footer-li-icon" v-if="type != 'deepExploration'"> |
||||
|
</image> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" |
||||
|
v-if="type == 'deepExploration'"></image> |
||||
|
<view :class="type == 'deepExploration' ? 'static-footer-li-title1' : 'static-footer-li-title'"> |
||||
|
{{ $t('components.footerBar.deepExploration') }}</view> |
||||
|
</view> |
||||
|
<view class="static-footer-li ellipsis" @click="tabChange(5)"> |
||||
|
<image src="../static/footBar-image/c5.png" class="static-footer-li-icon" v-if="type != 'member'"></image> |
||||
|
<image src="../static/footBar-image/logo.png" class="static-footer-li-icon" v-if="type == 'member'"></image> |
||||
|
<view :class="type == 'member' ? 'static-footer-li-title1' : 'static-footer-li-title'"> |
||||
|
{{ $t('components.footerBar.member') }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed, onMounted } from 'vue' |
||||
|
|
||||
|
// 定义 props |
||||
|
const props = defineProps({ |
||||
|
type: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 计算属性:获取安全区域 |
||||
|
const safeAreaInsets = computed(() => { |
||||
|
// 获取系统信息中的安全区域 |
||||
|
const systemInfo = uni.getSystemInfoSync() |
||||
|
return { |
||||
|
bottom: systemInfo.safeAreaInsets?.bottom || 0 |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 方法:标签切换 |
||||
|
const tabChange = (value) => { |
||||
|
// console.log(value) |
||||
|
if (value == 1) { //首页 |
||||
|
uni.redirectTo({ |
||||
|
url: '/pages/home/home', |
||||
|
animationType: 'fade-in' |
||||
|
}) |
||||
|
} else if (value == 2) { //行情 |
||||
|
uni.redirectTo({ |
||||
|
url: '/pages/home/marketSituation', |
||||
|
animationType: 'fade-in' |
||||
|
}) |
||||
|
} else if (value == 3) { //DeepMate |
||||
|
uni.redirectTo({ |
||||
|
url: '/pages/home/deepMate', |
||||
|
animationType: 'fade-in' |
||||
|
}) |
||||
|
} else if (value == 4) { //深度探索 |
||||
|
if (props.type == 'deepExploration') return; |
||||
|
uni.redirectTo({ |
||||
|
url: '/pages/home/deepExploration', |
||||
|
animationType: 'fade-in' |
||||
|
}) |
||||
|
} else if (value == 5) { //我的 |
||||
|
if (props.type == 'member') return; |
||||
|
uni.redirectTo({ |
||||
|
url: '/pages/home/member', |
||||
|
animationType: 'fade-in' |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 生命周期 |
||||
|
onMounted(() => { |
||||
|
// 组件挂载后的逻辑 |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer-bar { |
||||
|
width: 100%; |
||||
|
height: 100rpx; |
||||
|
border-top: 1px solid #E2E2E2; |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
.static-footer-li { |
||||
|
display: inline-block; |
||||
|
width: 20%; |
||||
|
height: 100%; |
||||
|
text-align: center; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.static-footer-li-icon { |
||||
|
width: 46rpx; |
||||
|
height: 46rpx; |
||||
|
margin: 12rpx 0; |
||||
|
} |
||||
|
|
||||
|
.static-footer-li-title { |
||||
|
width: 100%; |
||||
|
height: 40rpx; |
||||
|
line-height: 40rpx; |
||||
|
font-size: 24rpx; |
||||
|
text-align: center; |
||||
|
margin-top: -20rpx; |
||||
|
color: gray; |
||||
|
} |
||||
|
|
||||
|
.static-footer-li-title1 { |
||||
|
width: 100%; |
||||
|
height: 40rpx; |
||||
|
line-height: 40rpx; |
||||
|
font-size: 24rpx; |
||||
|
text-align: center; |
||||
|
margin-top: -20rpx; |
||||
|
color: black; |
||||
|
} |
||||
|
|
||||
|
.unreadNum { |
||||
|
position: absolute; |
||||
|
right: 15%; |
||||
|
background-color: #f00; |
||||
|
color: #fff; |
||||
|
font-size: 24rpx; |
||||
|
padding: 0 6rpx; |
||||
|
height: 36rpx; |
||||
|
line-height: 36rpx; |
||||
|
min-width: 36rpx; |
||||
|
border-radius: 18rpx; |
||||
|
z-index: 9; |
||||
|
} |
||||
|
|
||||
|
.taskNew { |
||||
|
position: absolute; |
||||
|
right: 15%; |
||||
|
height: 30rpx; |
||||
|
z-index: 9; |
||||
|
} |
||||
|
|
||||
|
.homeWorkUnRead { |
||||
|
position: absolute; |
||||
|
right: 30%; |
||||
|
top: 10%; |
||||
|
background-color: #f00; |
||||
|
color: #fff; |
||||
|
height: 12rpx; |
||||
|
width: 12rpx; |
||||
|
border-radius: 6rpx; |
||||
|
z-index: 9; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8" /> |
||||
|
<script> |
||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
||||
|
CSS.supports('top: constant(a)')) |
||||
|
document.write( |
||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
||||
|
</script> |
||||
|
<title></title> |
||||
|
<!--preload-links--> |
||||
|
<!--app-context--> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="app"><!--app-html--></div> |
||||
|
<script type="module" src="/main.js"></script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,111 @@ |
|||||
|
|
||||
|
// #ifndef VUE3
|
||||
|
import Vue from 'vue' |
||||
|
import App from './App' |
||||
|
|
||||
|
Vue.config.productionTip = false |
||||
|
|
||||
|
App.mpType = 'app' |
||||
|
|
||||
|
const app = new Vue({ |
||||
|
...App |
||||
|
}) |
||||
|
app.$mount() |
||||
|
// #endif
|
||||
|
|
||||
|
// #ifdef VUE3
|
||||
|
import { createSSRApp } from 'vue' |
||||
|
import App from './App.vue' |
||||
|
import { createI18n } from 'vue-i18n' |
||||
|
|
||||
|
// 导入语言文件
|
||||
|
import en from './static/language/en.js' |
||||
|
import ms from './static/language/ms.js' |
||||
|
import th from './static/language/th.js' |
||||
|
import vi from './static/language/vi.js' |
||||
|
import zh_CN from './static/language/zh_CN.js' |
||||
|
import zh_HK from './static/language/zh_HK.js' |
||||
|
|
||||
|
function getCurrentLocale() { |
||||
|
if (uni.getStorageSync('languageData') && uni.getStorageSync('languageData').code && uni |
||||
|
.getStorageSync('languageData').code != 'undefined') { |
||||
|
return uni.getStorageSync('languageData').code; |
||||
|
} else { |
||||
|
let language = uni.getSystemInfoSync().osLanguage; |
||||
|
// language = 'zh_CN'
|
||||
|
if (language.indexOf('th') != -1) { |
||||
|
language = 'th' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} else if (language.indexOf('vi') != -1) { |
||||
|
language = 'vi' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
}else if (language.indexOf('zh') != -1) { |
||||
|
if (language.indexOf('CN') != -1) { |
||||
|
language = 'zh_CN' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} else { |
||||
|
language = 'zh_HK' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} |
||||
|
} else if (language.indexOf('en') != -1) { |
||||
|
language = 'en' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} else if (language.indexOf('ms') != -1) { |
||||
|
language = 'ms' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} else { |
||||
|
language = 'en' |
||||
|
uni.setStorageSync('languageData', { |
||||
|
code: language |
||||
|
}) |
||||
|
console.log(language); |
||||
|
return language |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// 创建 i18n 实例
|
||||
|
const i18n = createI18n({ |
||||
|
locale: getCurrentLocale(), |
||||
|
legacy: false, // 使用 Composition API 模式
|
||||
|
globalInjection: true, // 全局注入 $t 函数
|
||||
|
messages: { |
||||
|
'en': en, |
||||
|
'ms': ms, |
||||
|
'th': th, |
||||
|
'vi': vi, |
||||
|
'zh_CN': zh_CN, |
||||
|
'zh_HK': zh_HK |
||||
|
} |
||||
|
}) |
||||
|
export function createApp() { |
||||
|
const app = createSSRApp(App) |
||||
|
app.use(i18n) |
||||
|
return { |
||||
|
app |
||||
|
} |
||||
|
} |
||||
|
// #endif
|
||||
@ -0,0 +1,60 @@ |
|||||
|
{ |
||||
|
"name" : "DeepChartApp", |
||||
|
"appid" : "__UNI__D8DF433", |
||||
|
"description" : "", |
||||
|
"versionName" : "1.0.0", |
||||
|
"versionCode" : "100", |
||||
|
"transformPx" : false, |
||||
|
"app-plus" : { |
||||
|
/* 5+App特有相关 */ |
||||
|
"usingComponents" : true, |
||||
|
"nvueCompiler" : "uni-app", |
||||
|
"nvueStyleCompiler" : "uni-app", |
||||
|
"splashscreen" : { |
||||
|
"alwaysShowBeforeRender" : true, |
||||
|
"waiting" : true, |
||||
|
"autoclose" : true, |
||||
|
"delay" : 0 |
||||
|
}, |
||||
|
"modules" : {}, |
||||
|
/* 模块配置 */ |
||||
|
"distribute" : { |
||||
|
/* 应用发布信息 */ |
||||
|
"android" : { |
||||
|
/* android打包配置 */ |
||||
|
"permissions" : [ |
||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
||||
|
] |
||||
|
}, |
||||
|
"ios" : {}, |
||||
|
/* ios打包配置 */ |
||||
|
"sdkConfigs" : {} |
||||
|
} |
||||
|
}, |
||||
|
/* SDK配置 */ |
||||
|
"quickapp" : {}, |
||||
|
/* 快应用特有相关 */ |
||||
|
"mp-weixin" : { |
||||
|
/* 小程序特有相关 */ |
||||
|
"appid" : "", |
||||
|
"setting" : { |
||||
|
"urlCheck" : false |
||||
|
}, |
||||
|
"usingComponents" : true |
||||
|
}, |
||||
|
"vueVersion" : "3" |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
{ |
||||
|
"pages": [ |
||||
|
{ |
||||
|
"path": "pages/home/home", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom", |
||||
|
"disableSwipeBack": true, |
||||
|
"titleNView": false, |
||||
|
"bounce": false |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/home/marketSituation", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom", |
||||
|
"disableSwipeBack": true, |
||||
|
"titleNView": false, |
||||
|
"bounce": false |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/home/deepMate", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom", |
||||
|
"disableSwipeBack": true, |
||||
|
"titleNView": false, |
||||
|
"bounce": false |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/home/deepExploration", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom", |
||||
|
"disableSwipeBack": true, |
||||
|
"titleNView": false, |
||||
|
"bounce": false |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/home/member", |
||||
|
"style": { |
||||
|
"navigationStyle": "custom", |
||||
|
"disableSwipeBack": true, |
||||
|
"titleNView": false, |
||||
|
"bounce": false |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"globalStyle": { |
||||
|
"navigationBarTextStyle": "black", |
||||
|
"navigationBarTitleText": "uni-app", |
||||
|
"navigationBarBackgroundColor": "#F8F8F8", |
||||
|
"backgroundColor": "#F8F8F8", |
||||
|
"app-plus": { |
||||
|
"background": "#efeff4" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<view>深度探索</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref,onMounted } from 'vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('deepExploration') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<view>DeepMate</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref,onMounted } from 'vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('deepMate') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<view>首页</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref,onMounted } from 'vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('home') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<view>行情</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref,onMounted } from 'vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('marketSituation') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<view>我的</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref,onMounted } from 'vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('member') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
</style> |
||||
|
After Width: 100 | Height: 100 | Size: 401 B |
|
After Width: 100 | Height: 100 | Size: 470 B |
|
After Width: 100 | Height: 100 | Size: 511 B |
|
After Width: 100 | Height: 100 | Size: 476 B |
|
After Width: 100 | Height: 100 | Size: 472 B |
|
After Width: 100 | Height: 100 | Size: 545 B |
|
After Width: 100 | Height: 100 | Size: 365 B |
|
After Width: 100 | Height: 100 | Size: 587 B |
|
After Width: 100 | Height: 100 | Size: 565 B |
@ -0,0 +1,20 @@ |
|||||
|
@font-face { |
||||
|
font-family: "customicons"; /* Project id 2878519 */ |
||||
|
src:url('/static/customicons.ttf') format('truetype'); |
||||
|
} |
||||
|
|
||||
|
.customicons { |
||||
|
font-family: "customicons" !important; |
||||
|
} |
||||
|
|
||||
|
.youxi:before { |
||||
|
content: "\e60e"; |
||||
|
} |
||||
|
|
||||
|
.wenjian:before { |
||||
|
content: "\e60f"; |
||||
|
} |
||||
|
|
||||
|
.zhuanfa:before { |
||||
|
content: "\e610"; |
||||
|
} |
||||
|
After Width: 100 | Height: 100 | Size: 401 B |
|
After Width: 100 | Height: 100 | Size: 470 B |
|
After Width: 100 | Height: 100 | Size: 476 B |
|
After Width: 100 | Height: 100 | Size: 472 B |
|
After Width: 72 | Height: 72 | Size: 3.9 KiB |
@ -0,0 +1,14 @@ |
|||||
|
export default { |
||||
|
language: { |
||||
|
"name": "Simplified Chinese" |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar: { |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
export default { |
||||
|
language: { |
||||
|
name: "Bahasa Melayu" |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar: { |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
export default { |
||||
|
language: { |
||||
|
name: "ภาษาไทย" |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar: { |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
export default { |
||||
|
language: { |
||||
|
name: "Tiếng Việt" |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar: { |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// 中文简体
|
||||
|
export default { |
||||
|
language: { |
||||
|
name: '中文简体' |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar:{ |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// 中文繁体
|
||||
|
export default { |
||||
|
language: { |
||||
|
name: "中文繁体" |
||||
|
}, |
||||
|
components: { |
||||
|
footerBar: { |
||||
|
homepage: '首页', |
||||
|
marketSituation: '行情', |
||||
|
deepMate: 'DeepMate', |
||||
|
deepExploration: '深度探索', |
||||
|
member: '我的', |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
|
After Width: 72 | Height: 72 | Size: 3.9 KiB |
|
After Width: 96 | Height: 96 | Size: 4.1 KiB |
@ -0,0 +1 @@ |
|||||
|
@import '@/uni_modules/uni-scss/variables.scss'; |
||||
@ -0,0 +1,33 @@ |
|||||
|
## 1.2.2(2023-01-28) |
||||
|
- 修复 运行/打包 控制台警告问题 |
||||
|
## 1.2.1(2022-09-05) |
||||
|
- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473) |
||||
|
## 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="[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'] |
||||
|
}, |
||||
|
dotStyle() { |
||||
|
if (!this.isDot) return {} |
||||
|
return { |
||||
|
width: '10px', |
||||
|
minWidth: '0', |
||||
|
height: '10px', |
||||
|
padding: '0', |
||||
|
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; |
||||
|
font-feature-settings: "tnum"; |
||||
|
min-width: 20px; |
||||
|
/* #endif */ |
||||
|
justify-content: center; |
||||
|
flex-direction: row; |
||||
|
height: 20px; |
||||
|
padding: 0 4px; |
||||
|
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,85 @@ |
|||||
|
{ |
||||
|
"id": "uni-badge", |
||||
|
"displayName": "uni-badge 数字角标", |
||||
|
"version": "1.2.2", |
||||
|
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。", |
||||
|
"keywords": [ |
||||
|
"", |
||||
|
"badge", |
||||
|
"uni-ui", |
||||
|
"uniui", |
||||
|
"数字角标", |
||||
|
"徽章" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": ["uni-scss"], |
||||
|
"encrypt": [], |
||||
|
"platforms": { |
||||
|
"cloud": { |
||||
|
"tcb": "y", |
||||
|
"aliyun": "y" |
||||
|
}, |
||||
|
"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 不显示的Bug |
||||
|
## 0.1.1(2022-06-02) |
||||
|
- 新增 支持 uni.scss 修改颜色 |
||||
|
## 0.1.0(2022-04-21) |
||||
|
- 初始化 |
||||
@ -0,0 +1,126 @@ |
|||||
|
<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: { |
||||
|
// #ifdef MP-TOUTIAO |
||||
|
virtualHost: false, |
||||
|
// #endif |
||||
|
// #ifndef MP-TOUTIAO |
||||
|
virtualHost: true |
||||
|
// #endif |
||||
|
}, |
||||
|
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,46 @@ |
|||||
|
<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: { |
||||
|
// #ifdef MP-TOUTIAO |
||||
|
virtualHost: false, |
||||
|
// #endif |
||||
|
// #ifndef MP-TOUTIAO |
||||
|
virtualHost: true |
||||
|
// #endif |
||||
|
}, |
||||
|
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,28 @@ |
|||||
|
## 1.4.11(2024-01-10) |
||||
|
- 修复 回到今天时,月份显示不一致问题 |
||||
|
## 1.4.10(2023-04-10) |
||||
|
- 修复 某些情况 monthSwitch 未触发的Bug |
||||
|
## 1.4.9(2023-02-02) |
||||
|
- 修复 某些情况切换月份错误的Bug |
||||
|
## 1.4.8(2023-01-30) |
||||
|
- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964) |
||||
|
## 1.4.7(2022-09-16) |
||||
|
- 优化 支持使用 uni-scss 控制主题色 |
||||
|
## 1.4.6(2022-09-08) |
||||
|
- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug |
||||
|
## 1.4.5(2022-02-25) |
||||
|
- 修复 条件编译 nvue 不支持的 css 样式的Bug |
||||
|
## 1.4.4(2022-02-25) |
||||
|
- 修复 条件编译 nvue 不支持的 css 样式的Bug |
||||
|
## 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,187 @@ |
|||||
|
<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 i18nMessages from './i18n/index.js' |
||||
|
const { t } = initVueI18n(i18nMessages) |
||||
|
|
||||
|
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-primary: #2979ff !default; |
||||
|
.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-primary; |
||||
|
} |
||||
|
|
||||
|
.uni-calendar-item--isDay { |
||||
|
background-color: $uni-primary; |
||||
|
opacity: 0.8; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.uni-calendar-item--extra { |
||||
|
color: $uni-color-error; |
||||
|
opacity: 0.8; |
||||
|
} |
||||
|
|
||||
|
.uni-calendar-item--checked { |
||||
|
background-color: $uni-primary; |
||||
|
color: #fff; |
||||
|
opacity: 0.8; |
||||
|
} |
||||
|
|
||||
|
.uni-calendar-item--multiple { |
||||
|
background-color: $uni-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,567 @@ |
|||||
|
<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 i18nMessages from './i18n/index.js' |
||||
|
const { t } = initVueI18n(i18nMessages) |
||||
|
|
||||
|
/** |
||||
|
* 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({ |
||||
|
selected: this.selected, |
||||
|
startDate: this.startDate, |
||||
|
endDate: this.endDate, |
||||
|
range: this.range, |
||||
|
}) |
||||
|
this.init(this.date) |
||||
|
}, |
||||
|
methods: { |
||||
|
// 取消穿透 |
||||
|
clean() {}, |
||||
|
bindDateChange(e) { |
||||
|
const value = e.detail.value + '-1' |
||||
|
this.setDate(value) |
||||
|
|
||||
|
const { year,month } = this.cale.getDate(value) |
||||
|
this.$emit('monthSwitch', { |
||||
|
year, |
||||
|
month |
||||
|
}) |
||||
|
}, |
||||
|
/** |
||||
|
* 初始化日期显示 |
||||
|
* @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() { |
||||
|
const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}` |
||||
|
const date = this.cale.getDate(new Date()) |
||||
|
const todayYearMonth = `${date.year}-${date.month}` |
||||
|
|
||||
|
this.init(date.fullDate) |
||||
|
|
||||
|
if(nowYearMonth !== todayYearMonth) { |
||||
|
this.monthSwitch() |
||||
|
} |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
.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,360 @@ |
|||||
|
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 && AddDayCount>0) { |
||||
|
dd.setDate(dd.getDate() + AddDayCount) |
||||
|
} else { |
||||
|
const preMonth = dd.getMonth() |
||||
|
dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
|
||||
|
const nextMonth = dd.getMonth() |
||||
|
// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||
|
if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){ |
||||
|
dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount)) |
||||
|
} |
||||
|
// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||
|
if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){ |
||||
|
dd.setMonth(nextMonth-(nextMonth-preMonth-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,85 @@ |
|||||
|
{ |
||||
|
"id": "uni-calendar", |
||||
|
"displayName": "uni-calendar 日历", |
||||
|
"version": "1.4.11", |
||||
|
"description": "日历组件", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"uniui", |
||||
|
"日历", |
||||
|
"", |
||||
|
"打卡", |
||||
|
"日历选择" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": [], |
||||
|
"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,38 @@ |
|||||
|
## 1.4.4(2024-03-20) |
||||
|
- 修复 titleBorder类型修正 |
||||
|
## 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 {String} border = ['auto'|'show'|'none'] 是否显示分隔线 |
||||
|
* @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,86 @@ |
|||||
|
{ |
||||
|
"id": "uni-collapse", |
||||
|
"displayName": "uni-collapse 折叠面板", |
||||
|
"version": "1.4.4", |
||||
|
"description": "Collapse 组件,可以折叠 / 展开的内容区域。", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"折叠", |
||||
|
"折叠面板", |
||||
|
"手风琴" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": [ |
||||
|
"uni-scss", |
||||
|
"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" scoped> |
||||
|
.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,26 @@ |
|||||
|
## 1.2.3(2024-02-20) |
||||
|
- 新增 支持控制小时,分钟的显隐:showHour showMinute |
||||
|
## 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,281 @@ |
|||||
|
<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 v-if="showHour" :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text> |
||||
|
<text v-if="showHour" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text> |
||||
|
<text v-if="showMinute" :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text> |
||||
|
<text v-if="showMinute" :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} showHour = [true|false] 是否显示小时 |
||||
|
* @property {Boolean} showMinute = [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 |
||||
|
}, |
||||
|
showHour: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
showMinute: { |
||||
|
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,83 @@ |
|||||
|
{ |
||||
|
"id": "uni-countdown", |
||||
|
"displayName": "uni-countdown 倒计时", |
||||
|
"version": "1.2.3", |
||||
|
"description": "CountDown 倒计时组件", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"uniui", |
||||
|
"countdown", |
||||
|
"倒计时" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": ["uni-scss"], |
||||
|
"encrypt": [], |
||||
|
"platforms": { |
||||
|
"cloud": { |
||||
|
"tcb": "y", |
||||
|
"aliyun": "y" |
||||
|
}, |
||||
|
"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,49 @@ |
|||||
|
## 1.0.5(2024-03-20) |
||||
|
- 修复 单选模式下选中样式不生效的bug |
||||
|
## 1.0.4(2024-01-27) |
||||
|
- 修复 修复错别字chagne为change |
||||
|
## 1.0.3(2022-09-16) |
||||
|
- 可以使用 uni-scss 控制主题色 |
||||
|
## 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) |
||||
|
- “暂无数据”显示居中 |
||||
@ -0,0 +1,849 @@ |
|||||
|
<template> |
||||
|
<view class="uni-data-checklist" :style="{'margin-top':isTop+'px'}"> |
||||
|
<template v-if="!isLocal"> |
||||
|
<view class="uni-data-loading"> |
||||
|
<uni-load-more v-if="!mixinDatacomErrorMessage" status="loading" iconType="snow" :iconSize="18" |
||||
|
:content-text="contentText"></uni-load-more> |
||||
|
<text v-else>{{mixinDatacomErrorMessage}}</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
<template v-else> |
||||
|
<checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" |
||||
|
@change="change"> |
||||
|
<label class="checklist-box" |
||||
|
:class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']" |
||||
|
:style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index"> |
||||
|
<checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" |
||||
|
:checked="item.selected" /> |
||||
|
<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" |
||||
|
class="checkbox__inner" :style="item.styleIcon"> |
||||
|
<view class="checkbox__inner-icon"></view> |
||||
|
</view> |
||||
|
<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}"> |
||||
|
<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text> |
||||
|
<view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view> |
||||
|
</view> |
||||
|
</label> |
||||
|
</checkbox-group> |
||||
|
<radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="change"> |
||||
|
<label class="checklist-box" |
||||
|
:class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']" |
||||
|
:style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index"> |
||||
|
<radio class="hidden" hidden :disabled="disabled || item.disabled" :value="item[map.value]+''" |
||||
|
:checked="item.selected" /> |
||||
|
<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner" |
||||
|
:style="item.styleBackgroud"> |
||||
|
<view class="radio__inner-icon" :style="item.styleIcon"></view> |
||||
|
</view> |
||||
|
<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}"> |
||||
|
<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text> |
||||
|
<view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view> |
||||
|
</view> |
||||
|
</label> |
||||
|
</radio-group> |
||||
|
</template> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
/** |
||||
|
* DataChecklist 数据选择器 |
||||
|
* @description 通过数据渲染 checkbox 和 radio |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx |
||||
|
* @property {String} mode = [default| list | button | tag] 显示模式 |
||||
|
* @value default 默认横排模式 |
||||
|
* @value list 列表模式 |
||||
|
* @value button 按钮模式 |
||||
|
* @value tag 标签模式 |
||||
|
* @property {Boolean} multiple = [true|false] 是否多选 |
||||
|
* @property {Array|String|Number} value 默认值 |
||||
|
* @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}] |
||||
|
* @property {Number|String} min 最小选择个数 ,multiple为true时生效 |
||||
|
* @property {Number|String} max 最大选择个数 ,multiple为true时生效 |
||||
|
* @property {Boolean} wrap 是否换行显示 |
||||
|
* @property {String} icon = [left|right] list 列表模式下icon显示位置 |
||||
|
* @property {Boolean} selectedColor 选中颜色 |
||||
|
* @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效 |
||||
|
* @property {Boolean} selectedTextColor 选中文本颜色,如不填写则自动显示 |
||||
|
* @property {Object} map 字段映射, 默认 map={text:'text',value:'value'} |
||||
|
* @value left 左侧显示 |
||||
|
* @value right 右侧显示 |
||||
|
* @event {Function} change 选中发生变化触发 |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
name: 'uniDataChecklist', |
||||
|
mixins: [uniCloud.mixinDatacom || {}], |
||||
|
emits: ['input', 'update:modelValue', 'change'], |
||||
|
props: { |
||||
|
mode: { |
||||
|
type: String, |
||||
|
default: 'default' |
||||
|
}, |
||||
|
|
||||
|
multiple: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
value: { |
||||
|
type: [Array, String, Number], |
||||
|
default () { |
||||
|
return '' |
||||
|
} |
||||
|
}, |
||||
|
// TODO vue3 |
||||
|
modelValue: { |
||||
|
type: [Array, String, Number], |
||||
|
default () { |
||||
|
return ''; |
||||
|
} |
||||
|
}, |
||||
|
localdata: { |
||||
|
type: Array, |
||||
|
default () { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
min: { |
||||
|
type: [Number, String], |
||||
|
default: '' |
||||
|
}, |
||||
|
max: { |
||||
|
type: [Number, String], |
||||
|
default: '' |
||||
|
}, |
||||
|
wrap: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
icon: { |
||||
|
type: String, |
||||
|
default: 'left' |
||||
|
}, |
||||
|
selectedColor: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
selectedTextColor: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
emptyText: { |
||||
|
type: String, |
||||
|
default: '暂无数据' |
||||
|
}, |
||||
|
disabled: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
map: { |
||||
|
type: Object, |
||||
|
default () { |
||||
|
return { |
||||
|
text: 'text', |
||||
|
value: 'value' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
localdata: { |
||||
|
handler(newVal) { |
||||
|
this.range = newVal |
||||
|
this.dataList = this.getDataList(this.getSelectedValue(newVal)) |
||||
|
}, |
||||
|
deep: true |
||||
|
}, |
||||
|
mixinDatacomResData(newVal) { |
||||
|
this.range = newVal |
||||
|
this.dataList = this.getDataList(this.getSelectedValue(newVal)) |
||||
|
}, |
||||
|
value(newVal) { |
||||
|
this.dataList = this.getDataList(newVal) |
||||
|
// fix by mehaotian is_reset 在 uni-forms 中定义 |
||||
|
// if(!this.is_reset){ |
||||
|
// this.is_reset = false |
||||
|
// this.formItem && this.formItem.setValue(newVal) |
||||
|
// } |
||||
|
}, |
||||
|
modelValue(newVal) { |
||||
|
this.dataList = this.getDataList(newVal); |
||||
|
// if(!this.is_reset){ |
||||
|
// this.is_reset = false |
||||
|
// this.formItem && this.formItem.setValue(newVal) |
||||
|
// } |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
dataList: [], |
||||
|
range: [], |
||||
|
contentText: { |
||||
|
contentdown: '查看更多', |
||||
|
contentrefresh: '加载中', |
||||
|
contentnomore: '没有更多' |
||||
|
}, |
||||
|
isLocal: true, |
||||
|
styles: { |
||||
|
selectedColor: '#2979ff', |
||||
|
selectedTextColor: '#666', |
||||
|
}, |
||||
|
isTop: 0 |
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
dataValue() { |
||||
|
if (this.value === '') return this.modelValue |
||||
|
if (this.modelValue === '') return this.value |
||||
|
return this.value |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
// this.form = this.getForm('uniForms') |
||||
|
// this.formItem = this.getForm('uniFormsItem') |
||||
|
// this.formItem && this.formItem.setValue(this.value) |
||||
|
|
||||
|
// if (this.formItem) { |
||||
|
// this.isTop = 6 |
||||
|
// if (this.formItem.name) { |
||||
|
// // 如果存在name添加默认值,否则formData 中不存在这个字段不校验 |
||||
|
// if(!this.is_reset){ |
||||
|
// this.is_reset = false |
||||
|
// this.formItem.setValue(this.dataValue) |
||||
|
// } |
||||
|
// this.rename = this.formItem.name |
||||
|
// this.form.inputChildrens.push(this) |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
if (this.localdata && this.localdata.length !== 0) { |
||||
|
this.isLocal = true |
||||
|
this.range = this.localdata |
||||
|
this.dataList = this.getDataList(this.getSelectedValue(this.range)) |
||||
|
} else { |
||||
|
if (this.collection) { |
||||
|
this.isLocal = false |
||||
|
this.loadData() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
loadData() { |
||||
|
this.mixinDatacomGet().then(res => { |
||||
|
this.mixinDatacomResData = res.result.data |
||||
|
if (this.mixinDatacomResData.length === 0) { |
||||
|
this.isLocal = false |
||||
|
this.mixinDatacomErrorMessage = this.emptyText |
||||
|
} else { |
||||
|
this.isLocal = true |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
this.mixinDatacomErrorMessage = err.message |
||||
|
}) |
||||
|
}, |
||||
|
/** |
||||
|
* 获取父元素实例 |
||||
|
*/ |
||||
|
getForm(name = 'uniForms') { |
||||
|
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; |
||||
|
}, |
||||
|
change(e) { |
||||
|
const values = e.detail.value |
||||
|
|
||||
|
let detail = { |
||||
|
value: [], |
||||
|
data: [] |
||||
|
} |
||||
|
|
||||
|
if (this.multiple) { |
||||
|
this.range.forEach(item => { |
||||
|
|
||||
|
if (values.includes(item[this.map.value] + '')) { |
||||
|
detail.value.push(item[this.map.value]) |
||||
|
detail.data.push(item) |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
const range = this.range.find(item => (item[this.map.value] + '') === values) |
||||
|
if (range) { |
||||
|
detail = { |
||||
|
value: range[this.map.value], |
||||
|
data: range |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// this.formItem && this.formItem.setValue(detail.value) |
||||
|
// TODO 兼容 vue2 |
||||
|
this.$emit('input', detail.value); |
||||
|
// // TOTO 兼容 vue3 |
||||
|
this.$emit('update:modelValue', detail.value); |
||||
|
this.$emit('change', { |
||||
|
detail |
||||
|
}) |
||||
|
if (this.multiple) { |
||||
|
// 如果 v-model 没有绑定 ,则走内部逻辑 |
||||
|
// if (this.value.length === 0) { |
||||
|
this.dataList = this.getDataList(detail.value, true) |
||||
|
// } |
||||
|
} else { |
||||
|
this.dataList = this.getDataList(detail.value) |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 获取渲染的新数组 |
||||
|
* @param {Object} value 选中内容 |
||||
|
*/ |
||||
|
getDataList(value) { |
||||
|
// 解除引用关系,破坏原引用关系,避免污染源数据 |
||||
|
let dataList = JSON.parse(JSON.stringify(this.range)) |
||||
|
let list = [] |
||||
|
if (this.multiple) { |
||||
|
if (!Array.isArray(value)) { |
||||
|
value = [] |
||||
|
} |
||||
|
} |
||||
|
dataList.forEach((item, index) => { |
||||
|
item.disabled = item.disable || item.disabled || false |
||||
|
if (this.multiple) { |
||||
|
if (value.length > 0) { |
||||
|
let have = value.find(val => val === item[this.map.value]) |
||||
|
item.selected = have !== undefined |
||||
|
} else { |
||||
|
item.selected = false |
||||
|
} |
||||
|
} else { |
||||
|
item.selected = value === item[this.map.value] |
||||
|
} |
||||
|
|
||||
|
list.push(item) |
||||
|
}) |
||||
|
return this.setRange(list) |
||||
|
}, |
||||
|
/** |
||||
|
* 处理最大最小值 |
||||
|
* @param {Object} list |
||||
|
*/ |
||||
|
setRange(list) { |
||||
|
let selectList = list.filter(item => item.selected) |
||||
|
let min = Number(this.min) || 0 |
||||
|
let max = Number(this.max) || '' |
||||
|
list.forEach((item, index) => { |
||||
|
if (this.multiple) { |
||||
|
if (selectList.length <= min) { |
||||
|
let have = selectList.find(val => val[this.map.value] === item[this.map.value]) |
||||
|
if (have !== undefined) { |
||||
|
item.disabled = true |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (selectList.length >= max && max !== '') { |
||||
|
let have = selectList.find(val => val[this.map.value] === item[this.map.value]) |
||||
|
if (have === undefined) { |
||||
|
item.disabled = true |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
this.setStyles(item, index) |
||||
|
list[index] = item |
||||
|
}) |
||||
|
return list |
||||
|
}, |
||||
|
/** |
||||
|
* 设置 class |
||||
|
* @param {Object} item |
||||
|
* @param {Object} index |
||||
|
*/ |
||||
|
setStyles(item, index) { |
||||
|
// 设置自定义样式 |
||||
|
item.styleBackgroud = this.setStyleBackgroud(item) |
||||
|
item.styleIcon = this.setStyleIcon(item) |
||||
|
item.styleIconText = this.setStyleIconText(item) |
||||
|
item.styleRightIcon = this.setStyleRightIcon(item) |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 获取选中值 |
||||
|
* @param {Object} range |
||||
|
*/ |
||||
|
getSelectedValue(range) { |
||||
|
if (!this.multiple) return this.dataValue |
||||
|
let selectedArr = [] |
||||
|
range.forEach((item) => { |
||||
|
if (item.selected) { |
||||
|
selectedArr.push(item[this.map.value]) |
||||
|
} |
||||
|
}) |
||||
|
return this.dataValue.length > 0 ? this.dataValue : selectedArr |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置背景样式 |
||||
|
*/ |
||||
|
setStyleBackgroud(item) { |
||||
|
let styles = {} |
||||
|
let selectedColor = this.selectedColor ? this.selectedColor : '#2979ff' |
||||
|
if (this.selectedColor) { |
||||
|
if (this.mode !== 'list') { |
||||
|
styles['border-color'] = item.selected ? selectedColor : '#DCDFE6' |
||||
|
} |
||||
|
if (this.mode === 'tag') { |
||||
|
styles['background-color'] = item.selected ? selectedColor : '#f5f5f5' |
||||
|
} |
||||
|
} |
||||
|
let classles = '' |
||||
|
for (let i in styles) { |
||||
|
classles += `${i}:${styles[i]};` |
||||
|
} |
||||
|
return classles |
||||
|
}, |
||||
|
setStyleIcon(item) { |
||||
|
let styles = {} |
||||
|
let classles = '' |
||||
|
if (this.selectedColor) { |
||||
|
let selectedColor = this.selectedColor ? this.selectedColor : '#2979ff' |
||||
|
styles['background-color'] = item.selected ? selectedColor : '#fff' |
||||
|
styles['border-color'] = item.selected ? selectedColor : '#DCDFE6' |
||||
|
|
||||
|
if (!item.selected && item.disabled) { |
||||
|
styles['background-color'] = '#F2F6FC' |
||||
|
styles['border-color'] = item.selected ? selectedColor : '#DCDFE6' |
||||
|
} |
||||
|
} |
||||
|
for (let i in styles) { |
||||
|
classles += `${i}:${styles[i]};` |
||||
|
} |
||||
|
return classles |
||||
|
}, |
||||
|
setStyleIconText(item) { |
||||
|
let styles = {} |
||||
|
let classles = '' |
||||
|
if (this.selectedColor) { |
||||
|
let selectedColor = this.selectedColor ? this.selectedColor : '#2979ff' |
||||
|
if (this.mode === 'tag') { |
||||
|
styles.color = item.selected ? (this.selectedTextColor ? this.selectedTextColor : '#fff') : '#666' |
||||
|
} else { |
||||
|
styles.color = item.selected ? (this.selectedTextColor ? this.selectedTextColor : selectedColor) : '#666' |
||||
|
} |
||||
|
if (!item.selected && item.disabled) { |
||||
|
styles.color = '#999' |
||||
|
} |
||||
|
} |
||||
|
for (let i in styles) { |
||||
|
classles += `${i}:${styles[i]};` |
||||
|
} |
||||
|
return classles |
||||
|
}, |
||||
|
setStyleRightIcon(item) { |
||||
|
let styles = {} |
||||
|
let classles = '' |
||||
|
if (this.mode === 'list') { |
||||
|
styles['border-color'] = item.selected ? this.styles.selectedColor : '#DCDFE6' |
||||
|
} |
||||
|
for (let i in styles) { |
||||
|
classles += `${i}:${styles[i]};` |
||||
|
} |
||||
|
|
||||
|
return classles |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
$uni-primary: #2979ff !default; |
||||
|
$border-color: #DCDFE6; |
||||
|
$disable: 0.4; |
||||
|
|
||||
|
@mixin flex { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.uni-data-loading { |
||||
|
@include flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
height: 36px; |
||||
|
padding-left: 10px; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.uni-data-checklist { |
||||
|
position: relative; |
||||
|
z-index: 0; |
||||
|
flex: 1; |
||||
|
|
||||
|
// 多选样式 |
||||
|
.checklist-group { |
||||
|
@include flex; |
||||
|
flex-direction: row; |
||||
|
flex-wrap: wrap; |
||||
|
|
||||
|
&.is-list { |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.checklist-box { |
||||
|
@include flex; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
position: relative; |
||||
|
margin: 5px 0; |
||||
|
margin-right: 25px; |
||||
|
|
||||
|
.hidden { |
||||
|
position: absolute; |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
// 文字样式 |
||||
|
.checklist-content { |
||||
|
@include flex; |
||||
|
flex: 1; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
|
||||
|
.checklist-text { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
margin-left: 5px; |
||||
|
line-height: 14px; |
||||
|
} |
||||
|
|
||||
|
.checkobx__list { |
||||
|
border-right-width: 1px; |
||||
|
border-right-color: #007aff; |
||||
|
border-right-style: solid; |
||||
|
border-bottom-width: 1px; |
||||
|
border-bottom-color: #007aff; |
||||
|
border-bottom-style: solid; |
||||
|
height: 12px; |
||||
|
width: 6px; |
||||
|
left: -5px; |
||||
|
transform-origin: center; |
||||
|
transform: rotate(45deg); |
||||
|
opacity: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 多选样式 |
||||
|
.checkbox__inner { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
flex-shrink: 0; |
||||
|
box-sizing: border-box; |
||||
|
/* #endif */ |
||||
|
position: relative; |
||||
|
width: 16px; |
||||
|
height: 16px; |
||||
|
border: 1px solid $border-color; |
||||
|
border-radius: 4px; |
||||
|
background-color: #fff; |
||||
|
z-index: 1; |
||||
|
|
||||
|
.checkbox__inner-icon { |
||||
|
position: absolute; |
||||
|
/* #ifdef APP-NVUE */ |
||||
|
top: 2px; |
||||
|
/* #endif */ |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
top: 1px; |
||||
|
/* #endif */ |
||||
|
left: 5px; |
||||
|
height: 8px; |
||||
|
width: 4px; |
||||
|
border-right-width: 1px; |
||||
|
border-right-color: #fff; |
||||
|
border-right-style: solid; |
||||
|
border-bottom-width: 1px; |
||||
|
border-bottom-color: #fff; |
||||
|
border-bottom-style: solid; |
||||
|
opacity: 0; |
||||
|
transform-origin: center; |
||||
|
transform: rotate(40deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 单选样式 |
||||
|
.radio__inner { |
||||
|
@include flex; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
flex-shrink: 0; |
||||
|
box-sizing: border-box; |
||||
|
/* #endif */ |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
position: relative; |
||||
|
width: 16px; |
||||
|
height: 16px; |
||||
|
border: 1px solid $border-color; |
||||
|
border-radius: 16px; |
||||
|
background-color: #fff; |
||||
|
z-index: 1; |
||||
|
|
||||
|
.radio__inner-icon { |
||||
|
width: 8px; |
||||
|
height: 8px; |
||||
|
border-radius: 10px; |
||||
|
opacity: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 默认样式 |
||||
|
&.is--default { |
||||
|
|
||||
|
// 禁用 |
||||
|
&.is-disable { |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
|
||||
|
/* #endif */ |
||||
|
.checkbox__inner { |
||||
|
background-color: #F2F6FC; |
||||
|
border-color: $border-color; |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
background-color: #F2F6FC; |
||||
|
border-color: $border-color; |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 选中 |
||||
|
&.is-checked { |
||||
|
.checkbox__inner { |
||||
|
border-color: $uni-primary; |
||||
|
background-color: $uni-primary; |
||||
|
|
||||
|
.checkbox__inner-icon { |
||||
|
opacity: 1; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
border-color: $uni-primary; |
||||
|
|
||||
|
.radio__inner-icon { |
||||
|
opacity: 1; |
||||
|
background-color: $uni-primary; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: $uni-primary; |
||||
|
} |
||||
|
|
||||
|
// 选中禁用 |
||||
|
&.is-disable { |
||||
|
.checkbox__inner { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 按钮样式 |
||||
|
&.is--button { |
||||
|
margin-right: 10px; |
||||
|
padding: 5px 10px; |
||||
|
border: 1px $border-color solid; |
||||
|
border-radius: 3px; |
||||
|
transition: border-color 0.2s; |
||||
|
|
||||
|
// 禁用 |
||||
|
&.is-disable { |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
border: 1px #eee solid; |
||||
|
opacity: $disable; |
||||
|
|
||||
|
.checkbox__inner { |
||||
|
background-color: #F2F6FC; |
||||
|
border-color: $border-color; |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
background-color: #F2F6FC; |
||||
|
border-color: $border-color; |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&.is-checked { |
||||
|
border-color: $uni-primary; |
||||
|
|
||||
|
.checkbox__inner { |
||||
|
border-color: $uni-primary; |
||||
|
background-color: $uni-primary; |
||||
|
|
||||
|
.checkbox__inner-icon { |
||||
|
opacity: 1; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
border-color: $uni-primary; |
||||
|
|
||||
|
.radio__inner-icon { |
||||
|
opacity: 1; |
||||
|
background-color: $uni-primary; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: $uni-primary; |
||||
|
} |
||||
|
|
||||
|
// 选中禁用 |
||||
|
&.is-disable { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 标签样式 |
||||
|
&.is--tag { |
||||
|
margin-right: 10px; |
||||
|
padding: 5px 10px; |
||||
|
border: 1px $border-color solid; |
||||
|
border-radius: 3px; |
||||
|
background-color: #f5f5f5; |
||||
|
|
||||
|
.checklist-text { |
||||
|
margin: 0; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
// 禁用 |
||||
|
&.is-disable { |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
|
||||
|
&.is-checked { |
||||
|
background-color: $uni-primary; |
||||
|
border-color: $uni-primary; |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: #fff; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 列表样式 |
||||
|
&.is--list { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
padding: 10px 15px; |
||||
|
padding-left: 0; |
||||
|
margin: 0; |
||||
|
|
||||
|
&.is-list-border { |
||||
|
border-top: 1px #eee solid; |
||||
|
} |
||||
|
|
||||
|
// 禁用 |
||||
|
&.is-disable { |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
|
||||
|
/* #endif */ |
||||
|
.checkbox__inner { |
||||
|
background-color: #F2F6FC; |
||||
|
border-color: $border-color; |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: not-allowed; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&.is-checked { |
||||
|
.checkbox__inner { |
||||
|
border-color: $uni-primary; |
||||
|
background-color: $uni-primary; |
||||
|
|
||||
|
.checkbox__inner-icon { |
||||
|
opacity: 1; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.radio__inner { |
||||
|
border-color: $uni-primary; |
||||
|
.radio__inner-icon { |
||||
|
opacity: 1; |
||||
|
background-color: $uni-primary; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
color: $uni-primary; |
||||
|
} |
||||
|
|
||||
|
.checklist-content { |
||||
|
.checkobx__list { |
||||
|
opacity: 1; |
||||
|
border-color: $uni-primary; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 选中禁用 |
||||
|
&.is-disable { |
||||
|
.checkbox__inner { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
|
||||
|
.checklist-text { |
||||
|
opacity: $disable; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,84 @@ |
|||||
|
{ |
||||
|
"id": "uni-data-checkbox", |
||||
|
"displayName": "uni-data-checkbox 数据选择器", |
||||
|
"version": "1.0.5", |
||||
|
"description": "通过数据驱动的单选框和复选框", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"checkbox", |
||||
|
"单选", |
||||
|
"多选", |
||||
|
"单选多选" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "^3.1.1" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": ["uni-load-more","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,18 @@ |
|||||
|
|
||||
|
|
||||
|
## DataCheckbox 数据驱动的单选复选框 |
||||
|
> **组件名:uni-data-checkbox** |
||||
|
> 代码块: `uDataCheckbox` |
||||
|
|
||||
|
|
||||
|
本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括: |
||||
|
|
||||
|
1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能 |
||||
|
2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验 |
||||
|
3. 本组件合并了单选多选 |
||||
|
4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性 |
||||
|
|
||||
|
在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data |
||||
|
|
||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox) |
||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
||||
@ -0,0 +1,77 @@ |
|||||
|
## 2.0.0(2023-12-14) |
||||
|
- 新增 支持 uni-app-x |
||||
|
## 1.1.2(2023-04-11) |
||||
|
- 修复 更改 modelValue 报错的 bug |
||||
|
- 修复 v-for 未使用 key 值控制台 warning |
||||
|
## 1.1.1(2023-02-21) |
||||
|
- 修复代码合并时引发 value 属性为空时不渲染数据的问题 |
||||
|
## 1.1.0(2023-02-15) |
||||
|
- 修复 localdata 不支持动态更新的bug |
||||
|
## 1.0.9(2023-02-15) |
||||
|
- 修复 localdata 不支持动态更新的bug |
||||
|
## 1.0.8(2022-09-16) |
||||
|
- 可以使用 uni-scss 控制主题色 |
||||
|
## 1.0.7(2022-07-06) |
||||
|
- 优化 pc端图标位置不正确的问题 |
||||
|
## 1.0.6(2022-07-05) |
||||
|
- 优化 显示样式 |
||||
|
## 1.0.5(2022-07-04) |
||||
|
- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug |
||||
|
## 1.0.4(2022-04-19) |
||||
|
- 修复 字节小程序 本地数据无法选择下一级的Bug |
||||
|
## 1.0.3(2022-02-25) |
||||
|
- 修复 nvue 不支持的 v-show 的 bug |
||||
|
## 1.0.2(2022-02-25) |
||||
|
- 修复 条件编译 nvue 不支持的 css 样式 |
||||
|
## 1.0.1(2021-11-23) |
||||
|
- 修复 由上个版本引发的map、v-model等属性不生效的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-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker) |
||||
|
## 0.4.9(2021-10-28) |
||||
|
- 修复 VUE2 v-model 概率无效的 bug |
||||
|
## 0.4.8(2021-10-27) |
||||
|
- 修复 v-model 概率无效的 bug |
||||
|
## 0.4.7(2021-10-25) |
||||
|
- 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+ |
||||
|
- 修复 树型 uniCloud 数据类型为 int 时报错的 bug |
||||
|
## 0.4.6(2021-10-19) |
||||
|
- 修复 非 VUE3 v-model 为 0 时无法选中的 bug |
||||
|
## 0.4.5(2021-09-26) |
||||
|
- 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效 |
||||
|
- 修复 readonly 为 true 时报错的 bug |
||||
|
## 0.4.4(2021-09-26) |
||||
|
- 修复 上一版本造成的 map 属性失效的 bug |
||||
|
- 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略 |
||||
|
## 0.4.3(2021-09-24) |
||||
|
- 修复 某些情况下级联未触发的 bug |
||||
|
## 0.4.2(2021-09-23) |
||||
|
- 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用 |
||||
|
- 新增 选项内容过长自动添加省略号 |
||||
|
## 0.4.1(2021-09-15) |
||||
|
- 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段 |
||||
|
## 0.4.0(2021-07-13) |
||||
|
- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
||||
|
## 0.3.5(2021-06-04) |
||||
|
- 修复 无法加载云端数据的问题 |
||||
|
## 0.3.4(2021-05-28) |
||||
|
- 修复 v-model 无效问题 |
||||
|
- 修复 loaddata 为空数据组时加载时间过长问题 |
||||
|
- 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点 |
||||
|
## 0.3.3(2021-05-12) |
||||
|
- 新增 组件示例地址 |
||||
|
## 0.3.2(2021-04-22) |
||||
|
- 修复 非树形数据有 where 属性查询报错的问题 |
||||
|
## 0.3.1(2021-04-15) |
||||
|
- 修复 本地数据概率无法回显时问题 |
||||
|
## 0.3.0(2021-04-07) |
||||
|
- 新增 支持云端非树形表结构数据 |
||||
|
- 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题 |
||||
|
## 0.2.0(2021-03-15) |
||||
|
- 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题 |
||||
|
## 0.1.9(2021-03-09) |
||||
|
- 修复 微信小程序某些情况下无法选择的问题 |
||||
|
## 0.1.8(2021-02-05) |
||||
|
- 优化 部分样式在 nvue 上的兼容表现 |
||||
|
## 0.1.7(2021-02-05) |
||||
|
- 调整为 uni_modules 目录规范 |
||||
@ -0,0 +1,45 @@ |
|||||
|
// #ifdef H5
|
||||
|
export default { |
||||
|
name: 'Keypress', |
||||
|
props: { |
||||
|
disable: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
} |
||||
|
}, |
||||
|
mounted () { |
||||
|
const keyNames = { |
||||
|
esc: ['Esc', 'Escape'], |
||||
|
tab: 'Tab', |
||||
|
enter: 'Enter', |
||||
|
space: [' ', 'Spacebar'], |
||||
|
up: ['Up', 'ArrowUp'], |
||||
|
left: ['Left', 'ArrowLeft'], |
||||
|
right: ['Right', 'ArrowRight'], |
||||
|
down: ['Down', 'ArrowDown'], |
||||
|
delete: ['Backspace', 'Delete', 'Del'] |
||||
|
} |
||||
|
const listener = ($event) => { |
||||
|
if (this.disable) { |
||||
|
return |
||||
|
} |
||||
|
const keyName = Object.keys(keyNames).find(key => { |
||||
|
const keyName = $event.key |
||||
|
const value = keyNames[key] |
||||
|
return value === keyName || (Array.isArray(value) && value.includes(keyName)) |
||||
|
}) |
||||
|
if (keyName) { |
||||
|
// 避免和其他按键事件冲突
|
||||
|
setTimeout(() => { |
||||
|
this.$emit(keyName, {}) |
||||
|
}, 0) |
||||
|
} |
||||
|
} |
||||
|
document.addEventListener('keyup', listener) |
||||
|
this.$once('hook:beforeDestroy', () => { |
||||
|
document.removeEventListener('keyup', listener) |
||||
|
}) |
||||
|
}, |
||||
|
render: () => {} |
||||
|
} |
||||
|
// #endif
|
||||
@ -0,0 +1,380 @@ |
|||||
|
<template> |
||||
|
<view class="uni-data-tree"> |
||||
|
<view class="uni-data-tree-input" @click="handleInput"> |
||||
|
<slot :data="selectedPaths" :error="error"> |
||||
|
<view class="input-value" :class="{'input-value-border': border}"> |
||||
|
<text v-if="error!=null" class="error-text">{{error!.errMsg}}</text> |
||||
|
<scroll-view v-if="selectedPaths.length" class="selected-path" scroll-x="true"> |
||||
|
<view class="selected-list"> |
||||
|
<template v-for="(item, index) in selectedPaths"> |
||||
|
<text class="text-color">{{item[mappingTextName]}}</text> |
||||
|
<text v-if="index<selectedPaths.length-1" class="input-split-line">{{split}}</text> |
||||
|
</template> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<text v-else-if="error==null&&!loading" class="placeholder">{{placeholder}}</text> |
||||
|
<view v-if="!readonly" class="arrow-area"> |
||||
|
<view class="input-arrow"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</slot> |
||||
|
<view v-if="loading && !isOpened" class="selected-loading"> |
||||
|
<slot name="picker-loading" :loading="loading"></slot> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view> |
||||
|
<view class="uni-data-tree-dialog" v-if="isOpened"> |
||||
|
<view class="uni-popper__arrow"></view> |
||||
|
<view class="dialog-caption"> |
||||
|
<view class="dialog-title-view"> |
||||
|
<text class="dialog-title">{{popupTitle}}</text> |
||||
|
</view> |
||||
|
<view class="dialog-close" @click="handleClose"> |
||||
|
<view class="dialog-close-plus" data-id="close"></view> |
||||
|
<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view ref="pickerView" class="uni-data-pickerview"> |
||||
|
<view v-if="error!=null" class="error"> |
||||
|
<text class="error-text">{{error!.errMsg}}</text> |
||||
|
</view> |
||||
|
<scroll-view v-if="!isCloudDataList" :scroll-x="true"> |
||||
|
<view class="selected-node-list"> |
||||
|
<template v-for="(item, index) in selectedNodes"> |
||||
|
<text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}" |
||||
|
@click="onTabSelect(index)"> |
||||
|
{{item[mappingTextName]}} |
||||
|
</text> |
||||
|
</template> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<list-view class="list-view" :scroll-y="true"> |
||||
|
<list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)"> |
||||
|
<text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text> |
||||
|
<text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text> |
||||
|
</list-item> |
||||
|
</list-view> |
||||
|
<view class="loading-cover" v-if="loading"> |
||||
|
<slot name="pickerview-loading" :loading="loading"></slot> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { dataPicker } from "../uni-data-pickerview/uni-data-picker.uts" |
||||
|
|
||||
|
/** |
||||
|
* DataPicker 级联选择 |
||||
|
* @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
||||
|
* @property {String} popup-title 弹出窗口标题 |
||||
|
* @property {Array} localdata 本地数据,参考 |
||||
|
* @property {Boolean} border = [true|false] 是否有边框 |
||||
|
* @property {Boolean} readonly = [true|false] 是否仅读 |
||||
|
* @property {Boolean} preload = [true|false] 是否预加载数据 |
||||
|
* @value true 开启预加载数据,点击弹出窗口后显示已加载数据 |
||||
|
* @value false 关闭预加载数据,点击弹出窗口后开始加载数据 |
||||
|
* @property {Boolean} step-searh = [true|false] 是否分布查询 |
||||
|
* @value true 启用分布查询,仅查询当前选中节点 |
||||
|
* @value false 关闭分布查询,一次查询出所有数据 |
||||
|
* @property {String|DBFieldString} self-field 分布查询当前字段名称 |
||||
|
* @property {String|DBFieldString} parent-field 分布查询父字段名称 |
||||
|
* @property {String|DBCollectionString} collection 表名 |
||||
|
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
||||
|
* @property {String} orderby 排序字段及正序倒叙设置 |
||||
|
* @property {String|JQLString} where 查询条件 |
||||
|
* @event {Function} popupshow 弹出的选择窗口打开时触发此事件 |
||||
|
* @event {Function} popuphide 弹出的选择窗口关闭时触发此事件 |
||||
|
*/ |
||||
|
export default { |
||||
|
name: 'UniDataPicker', |
||||
|
emits: ['popupopened', 'popupclosed', 'nodeclick', 'change', 'input', 'update:modelValue', 'inputclick'], |
||||
|
mixins: [dataPicker], |
||||
|
props: { |
||||
|
popupTitle: { |
||||
|
type: String, |
||||
|
default: '请选择' |
||||
|
}, |
||||
|
placeholder: { |
||||
|
type: String, |
||||
|
default: '请选择' |
||||
|
}, |
||||
|
heightMobile: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
readonly: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
clearIcon: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
border: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
split: { |
||||
|
type: String, |
||||
|
default: '/' |
||||
|
}, |
||||
|
ellipsis: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
isOpened: false |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
isShowClearIcon() : boolean { |
||||
|
if (this.readonly) { |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
if (this.clearIcon && this.selectedPaths.length > 0) { |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
return false |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.load() |
||||
|
}, |
||||
|
methods: { |
||||
|
clear() { |
||||
|
}, |
||||
|
load() { |
||||
|
if (this.isLocalData) { |
||||
|
this.loadLocalData() |
||||
|
} else if (this.isCloudDataList || this.isCloudDataTree) { |
||||
|
this.loadCloudDataPath() |
||||
|
} |
||||
|
}, |
||||
|
show() { |
||||
|
this.isOpened = true |
||||
|
this.$emit('popupopened') |
||||
|
if (!this.hasCloudTreeData) { |
||||
|
this.loadData() |
||||
|
} |
||||
|
}, |
||||
|
hide() { |
||||
|
this.isOpened = false |
||||
|
this.$emit('popupclosed') |
||||
|
}, |
||||
|
handleInput() { |
||||
|
if (this.readonly) { |
||||
|
this.$emit('inputclick') |
||||
|
} else { |
||||
|
this.show() |
||||
|
} |
||||
|
}, |
||||
|
handleClose() { |
||||
|
this.hide() |
||||
|
}, |
||||
|
onFinish() { |
||||
|
this.selectedPaths = this.getChangeNodes() |
||||
|
this.$emit('change', this.selectedPaths) |
||||
|
this.hide() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
@import url("../uni-data-pickerview/uni-data-pickerview.css"); |
||||
|
|
||||
|
.uni-data-tree { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-input { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.selected-loading { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.error-text { |
||||
|
flex: 1; |
||||
|
font-size: 12px; |
||||
|
color: #DD524D; |
||||
|
} |
||||
|
|
||||
|
.input-value { |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
flex-wrap: nowrap; |
||||
|
padding: 5px 5px; |
||||
|
padding-right: 5px; |
||||
|
overflow: hidden; |
||||
|
min-height: 28px; |
||||
|
} |
||||
|
|
||||
|
.input-value-border { |
||||
|
border: 1px solid #e5e5e5; |
||||
|
border-radius: 5px; |
||||
|
} |
||||
|
|
||||
|
.selected-path { |
||||
|
flex: 1; |
||||
|
flex-direction: row; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.load-more { |
||||
|
width: 40px; |
||||
|
} |
||||
|
|
||||
|
.selected-list { |
||||
|
flex-direction: row; |
||||
|
flex-wrap: nowrap; |
||||
|
} |
||||
|
|
||||
|
.selected-item { |
||||
|
flex-direction: row; |
||||
|
flex-wrap: nowrap; |
||||
|
} |
||||
|
|
||||
|
.text-color { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.placeholder { |
||||
|
color: grey; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.input-split-line { |
||||
|
opacity: .5; |
||||
|
margin-left: 1px; |
||||
|
margin-right: 1px; |
||||
|
} |
||||
|
|
||||
|
.arrow-area { |
||||
|
position: relative; |
||||
|
padding: 0 12px; |
||||
|
margin-left: auto; |
||||
|
justify-content: center; |
||||
|
transform: rotate(-45deg); |
||||
|
transform-origin: center; |
||||
|
} |
||||
|
|
||||
|
.input-arrow { |
||||
|
width: 8px; |
||||
|
height: 8px; |
||||
|
border-left: 2px solid #999; |
||||
|
border-bottom: 2px solid #999; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-cover { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, .4); |
||||
|
flex-direction: column; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-dialog { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
top: 20%; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: #FFFFFF; |
||||
|
border-top-left-radius: 10px; |
||||
|
border-top-right-radius: 10px; |
||||
|
flex-direction: column; |
||||
|
z-index: 102; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.dialog-caption { |
||||
|
position: relative; |
||||
|
flex-direction: row; |
||||
|
} |
||||
|
|
||||
|
.dialog-title-view { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.dialog-title { |
||||
|
align-self: center; |
||||
|
padding: 0 10px; |
||||
|
line-height: 44px; |
||||
|
} |
||||
|
|
||||
|
.dialog-close { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
padding: 0 15px; |
||||
|
} |
||||
|
|
||||
|
.dialog-close-plus { |
||||
|
width: 16px; |
||||
|
height: 2px; |
||||
|
background-color: #666; |
||||
|
border-radius: 2px; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
|
||||
|
.dialog-close-rotate { |
||||
|
position: absolute; |
||||
|
transform: rotate(-45deg); |
||||
|
} |
||||
|
|
||||
|
.uni-data-pickerview { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.icon-clear { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
/* #ifdef H5 */ |
||||
|
@media all and (min-width: 768px) { |
||||
|
.uni-data-tree-cover { |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-dialog { |
||||
|
position: absolute; |
||||
|
top: 55px; |
||||
|
height: auto; |
||||
|
min-height: 400px; |
||||
|
max-height: 50vh; |
||||
|
background-color: #fff; |
||||
|
border: 1px solid #EBEEF5; |
||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
||||
|
border-radius: 4px; |
||||
|
overflow: unset; |
||||
|
} |
||||
|
|
||||
|
.dialog-caption { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
/* #endif */ |
||||
|
</style> |
||||
@ -0,0 +1,551 @@ |
|||||
|
<template> |
||||
|
<view class="uni-data-tree"> |
||||
|
<view class="uni-data-tree-input" @click="handleInput"> |
||||
|
<slot :options="options" :data="inputSelected" :error="errorMessage"> |
||||
|
<view class="input-value" :class="{'input-value-border': border}"> |
||||
|
<text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text> |
||||
|
<view v-else-if="loading && !isOpened" class="selected-area"> |
||||
|
<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more> |
||||
|
</view> |
||||
|
<scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true"> |
||||
|
<view class="selected-list"> |
||||
|
<view class="selected-item" v-for="(item,index) in inputSelected" :key="index"> |
||||
|
<text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1" |
||||
|
class="input-split-line">{{split}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<text v-else class="selected-area placeholder">{{placeholder}}</text> |
||||
|
<view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear"> |
||||
|
<uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons> |
||||
|
</view> |
||||
|
<view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly "> |
||||
|
<view class="input-arrow"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</slot> |
||||
|
</view> |
||||
|
<view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view> |
||||
|
<view class="uni-data-tree-dialog" v-if="isOpened"> |
||||
|
<view class="uni-popper__arrow"></view> |
||||
|
<view class="dialog-caption"> |
||||
|
<view class="title-area"> |
||||
|
<text class="dialog-title">{{popupTitle}}</text> |
||||
|
</view> |
||||
|
<view class="dialog-close" @click="handleClose"> |
||||
|
<view class="dialog-close-plus" data-id="close"></view> |
||||
|
<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata" |
||||
|
:preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where" |
||||
|
:step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true" :map="map" |
||||
|
:ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick"> |
||||
|
</data-picker-view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import dataPicker from "../uni-data-pickerview/uni-data-picker.js" |
||||
|
import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue" |
||||
|
|
||||
|
/** |
||||
|
* DataPicker 级联选择 |
||||
|
* @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
||||
|
* @property {String} popup-title 弹出窗口标题 |
||||
|
* @property {Array} localdata 本地数据,参考 |
||||
|
* @property {Boolean} border = [true|false] 是否有边框 |
||||
|
* @property {Boolean} readonly = [true|false] 是否仅读 |
||||
|
* @property {Boolean} preload = [true|false] 是否预加载数据 |
||||
|
* @value true 开启预加载数据,点击弹出窗口后显示已加载数据 |
||||
|
* @value false 关闭预加载数据,点击弹出窗口后开始加载数据 |
||||
|
* @property {Boolean} step-searh = [true|false] 是否分布查询 |
||||
|
* @value true 启用分布查询,仅查询当前选中节点 |
||||
|
* @value false 关闭分布查询,一次查询出所有数据 |
||||
|
* @property {String|DBFieldString} self-field 分布查询当前字段名称 |
||||
|
* @property {String|DBFieldString} parent-field 分布查询父字段名称 |
||||
|
* @property {String|DBCollectionString} collection 表名 |
||||
|
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
||||
|
* @property {String} orderby 排序字段及正序倒叙设置 |
||||
|
* @property {String|JQLString} where 查询条件 |
||||
|
* @event {Function} popupshow 弹出的选择窗口打开时触发此事件 |
||||
|
* @event {Function} popuphide 弹出的选择窗口关闭时触发此事件 |
||||
|
*/ |
||||
|
export default { |
||||
|
name: 'UniDataPicker', |
||||
|
emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue','inputclick'], |
||||
|
mixins: [dataPicker], |
||||
|
components: { |
||||
|
DataPickerView |
||||
|
}, |
||||
|
props: { |
||||
|
options: { |
||||
|
type: [Object, Array], |
||||
|
default () { |
||||
|
return {} |
||||
|
} |
||||
|
}, |
||||
|
popupTitle: { |
||||
|
type: String, |
||||
|
default: '请选择' |
||||
|
}, |
||||
|
placeholder: { |
||||
|
type: String, |
||||
|
default: '请选择' |
||||
|
}, |
||||
|
heightMobile: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
readonly: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
clearIcon: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
border: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
split: { |
||||
|
type: String, |
||||
|
default: '/' |
||||
|
}, |
||||
|
ellipsis: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
isOpened: false, |
||||
|
inputSelected: [] |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.$nextTick(() => { |
||||
|
this.load(); |
||||
|
}) |
||||
|
}, |
||||
|
watch: { |
||||
|
localdata: { |
||||
|
handler() { |
||||
|
this.load() |
||||
|
}, |
||||
|
deep: true |
||||
|
}, |
||||
|
}, |
||||
|
methods: { |
||||
|
clear() { |
||||
|
this._dispatchEvent([]); |
||||
|
}, |
||||
|
onPropsChange() { |
||||
|
this._treeData = []; |
||||
|
this.selectedIndex = 0; |
||||
|
|
||||
|
this.load(); |
||||
|
}, |
||||
|
load() { |
||||
|
if (this.readonly) { |
||||
|
this._processReadonly(this.localdata, this.dataValue); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 回显本地数据 |
||||
|
if (this.isLocalData) { |
||||
|
this.loadData(); |
||||
|
this.inputSelected = this.selected.slice(0); |
||||
|
} else if (this.isCloudDataList || this.isCloudDataTree) { // 回显 Cloud 数据 |
||||
|
this.loading = true; |
||||
|
this.getCloudDataValue().then((res) => { |
||||
|
this.loading = false; |
||||
|
this.inputSelected = res; |
||||
|
}).catch((err) => { |
||||
|
this.loading = false; |
||||
|
this.errorMessage = err; |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
show() { |
||||
|
this.isOpened = true |
||||
|
setTimeout(() => { |
||||
|
this.$refs.pickerView.updateData({ |
||||
|
treeData: this._treeData, |
||||
|
selected: this.selected, |
||||
|
selectedIndex: this.selectedIndex |
||||
|
}) |
||||
|
}, 200) |
||||
|
this.$emit('popupopened') |
||||
|
}, |
||||
|
hide() { |
||||
|
this.isOpened = false |
||||
|
this.$emit('popupclosed') |
||||
|
}, |
||||
|
handleInput() { |
||||
|
if (this.readonly) { |
||||
|
this.$emit('inputclick') |
||||
|
return |
||||
|
} |
||||
|
this.show() |
||||
|
}, |
||||
|
handleClose(e) { |
||||
|
this.hide() |
||||
|
}, |
||||
|
onnodeclick(e) { |
||||
|
this.$emit('nodeclick', e) |
||||
|
}, |
||||
|
ondatachange(e) { |
||||
|
this._treeData = this.$refs.pickerView._treeData |
||||
|
}, |
||||
|
onchange(e) { |
||||
|
this.hide() |
||||
|
this.$nextTick(() => { |
||||
|
this.inputSelected = e; |
||||
|
}) |
||||
|
this._dispatchEvent(e) |
||||
|
}, |
||||
|
_processReadonly(dataList, value) { |
||||
|
var isTree = dataList.findIndex((item) => { |
||||
|
return item.children |
||||
|
}) |
||||
|
if (isTree > -1) { |
||||
|
let inputValue |
||||
|
if (Array.isArray(value)) { |
||||
|
inputValue = value[value.length - 1] |
||||
|
if (typeof inputValue === 'object' && inputValue.value) { |
||||
|
inputValue = inputValue.value |
||||
|
} |
||||
|
} else { |
||||
|
inputValue = value |
||||
|
} |
||||
|
this.inputSelected = this._findNodePath(inputValue, this.localdata) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if (!this.hasValue) { |
||||
|
this.inputSelected = [] |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
let result = [] |
||||
|
for (let i = 0; i < value.length; i++) { |
||||
|
var val = value[i] |
||||
|
var item = dataList.find((v) => { |
||||
|
return v.value == val |
||||
|
}) |
||||
|
if (item) { |
||||
|
result.push(item) |
||||
|
} |
||||
|
} |
||||
|
if (result.length) { |
||||
|
this.inputSelected = result |
||||
|
} |
||||
|
}, |
||||
|
_filterForArray(data, valueArray) { |
||||
|
var result = [] |
||||
|
for (let i = 0; i < valueArray.length; i++) { |
||||
|
var value = valueArray[i] |
||||
|
var found = data.find((item) => { |
||||
|
return item.value == value |
||||
|
}) |
||||
|
if (found) { |
||||
|
result.push(found) |
||||
|
} |
||||
|
} |
||||
|
return result |
||||
|
}, |
||||
|
_dispatchEvent(selected) { |
||||
|
let item = {} |
||||
|
if (selected.length) { |
||||
|
var value = new Array(selected.length) |
||||
|
for (var i = 0; i < selected.length; i++) { |
||||
|
value[i] = selected[i].value |
||||
|
} |
||||
|
item = selected[selected.length - 1] |
||||
|
} else { |
||||
|
item.value = '' |
||||
|
} |
||||
|
if (this.formItem) { |
||||
|
this.formItem.setValue(item.value) |
||||
|
} |
||||
|
|
||||
|
this.$emit('input', item.value) |
||||
|
this.$emit('update:modelValue', item.value) |
||||
|
this.$emit('change', { |
||||
|
detail: { |
||||
|
value: selected |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.uni-data-tree { |
||||
|
flex: 1; |
||||
|
position: relative; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.error-text { |
||||
|
color: #DD524D; |
||||
|
} |
||||
|
|
||||
|
.input-value { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
flex-wrap: nowrap; |
||||
|
font-size: 14px; |
||||
|
/* line-height: 35px; */ |
||||
|
padding: 0 10px; |
||||
|
padding-right: 5px; |
||||
|
overflow: hidden; |
||||
|
height: 35px; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
box-sizing: border-box; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.input-value-border { |
||||
|
border: 1px solid #e5e5e5; |
||||
|
border-radius: 5px; |
||||
|
} |
||||
|
|
||||
|
.selected-area { |
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
} |
||||
|
|
||||
|
.load-more { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
margin-right: auto; |
||||
|
/* #endif */ |
||||
|
/* #ifdef APP-NVUE */ |
||||
|
width: 40px; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.selected-list { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
flex-wrap: nowrap; |
||||
|
/* padding: 0 5px; */ |
||||
|
} |
||||
|
|
||||
|
.selected-item { |
||||
|
flex-direction: row; |
||||
|
/* padding: 0 1px; */ |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
white-space: nowrap; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.text-color { |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.placeholder { |
||||
|
color: grey; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.input-split-line { |
||||
|
opacity: .5; |
||||
|
} |
||||
|
|
||||
|
.arrow-area { |
||||
|
position: relative; |
||||
|
width: 20px; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
margin-bottom: 5px; |
||||
|
margin-left: auto; |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
justify-content: center; |
||||
|
transform: rotate(-45deg); |
||||
|
transform-origin: center; |
||||
|
} |
||||
|
|
||||
|
.input-arrow { |
||||
|
width: 7px; |
||||
|
height: 7px; |
||||
|
border-left: 1px solid #999; |
||||
|
border-bottom: 1px solid #999; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-cover { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, .4); |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: column; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-dialog { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
top: 20%; |
||||
|
/* #endif */ |
||||
|
/* #ifdef APP-NVUE */ |
||||
|
top: 200px; |
||||
|
/* #endif */ |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: #FFFFFF; |
||||
|
border-top-left-radius: 10px; |
||||
|
border-top-right-radius: 10px; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: column; |
||||
|
z-index: 102; |
||||
|
overflow: hidden; |
||||
|
/* #ifdef APP-NVUE */ |
||||
|
width: 750rpx; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.dialog-caption { |
||||
|
position: relative; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
/* border-bottom: 1px solid #f0f0f0; */ |
||||
|
} |
||||
|
|
||||
|
.title-area { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
align-items: center; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
margin: auto; |
||||
|
/* #endif */ |
||||
|
padding: 0 10px; |
||||
|
} |
||||
|
|
||||
|
.dialog-title { |
||||
|
/* font-weight: bold; */ |
||||
|
line-height: 44px; |
||||
|
} |
||||
|
|
||||
|
.dialog-close { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
padding: 0 15px; |
||||
|
} |
||||
|
|
||||
|
.dialog-close-plus { |
||||
|
width: 16px; |
||||
|
height: 2px; |
||||
|
background-color: #666; |
||||
|
border-radius: 2px; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
|
||||
|
.dialog-close-rotate { |
||||
|
position: absolute; |
||||
|
transform: rotate(-45deg); |
||||
|
} |
||||
|
|
||||
|
.picker-view { |
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.icon-clear { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
/* #ifdef H5 */ |
||||
|
@media all and (min-width: 768px) { |
||||
|
.uni-data-tree-cover { |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
|
||||
|
.uni-data-tree-dialog { |
||||
|
position: absolute; |
||||
|
top: 55px; |
||||
|
height: auto; |
||||
|
min-height: 400px; |
||||
|
max-height: 50vh; |
||||
|
background-color: #fff; |
||||
|
border: 1px solid #EBEEF5; |
||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
||||
|
border-radius: 4px; |
||||
|
overflow: unset; |
||||
|
} |
||||
|
|
||||
|
.dialog-caption { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.icon-clear { |
||||
|
/* margin-right: 5px; */ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* #endif */ |
||||
|
|
||||
|
/* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */ |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
.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; |
||||
|
} |
||||
|
|
||||
|
/* #endif */ |
||||
|
</style> |
||||
1
uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
File diff suppressed because it is too large
View File
@ -0,0 +1,622 @@ |
|||||
|
export default { |
||||
|
props: { |
||||
|
localdata: { |
||||
|
type: [Array, Object], |
||||
|
default () { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
spaceInfo: { |
||||
|
type: Object, |
||||
|
default () { |
||||
|
return {} |
||||
|
} |
||||
|
}, |
||||
|
collection: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
action: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
field: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
orderby: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
where: { |
||||
|
type: [String, Object], |
||||
|
default: '' |
||||
|
}, |
||||
|
pageData: { |
||||
|
type: String, |
||||
|
default: 'add' |
||||
|
}, |
||||
|
pageCurrent: { |
||||
|
type: Number, |
||||
|
default: 1 |
||||
|
}, |
||||
|
pageSize: { |
||||
|
type: Number, |
||||
|
default: 500 |
||||
|
}, |
||||
|
getcount: { |
||||
|
type: [Boolean, String], |
||||
|
default: false |
||||
|
}, |
||||
|
getone: { |
||||
|
type: [Boolean, String], |
||||
|
default: false |
||||
|
}, |
||||
|
gettree: { |
||||
|
type: [Boolean, String], |
||||
|
default: false |
||||
|
}, |
||||
|
manual: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
value: { |
||||
|
type: [Array, String, Number], |
||||
|
default () { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
modelValue: { |
||||
|
type: [Array, String, Number], |
||||
|
default () { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
preload: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
stepSearh: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
selfField: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
parentField: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
multiple: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
map: { |
||||
|
type: Object, |
||||
|
default () { |
||||
|
return { |
||||
|
text: "text", |
||||
|
value: "value" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
loading: false, |
||||
|
errorMessage: '', |
||||
|
loadMore: { |
||||
|
contentdown: '', |
||||
|
contentrefresh: '', |
||||
|
contentnomore: '' |
||||
|
}, |
||||
|
dataList: [], |
||||
|
selected: [], |
||||
|
selectedIndex: 0, |
||||
|
page: { |
||||
|
current: this.pageCurrent, |
||||
|
size: this.pageSize, |
||||
|
count: 0 |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
isLocalData() { |
||||
|
return !this.collection.length; |
||||
|
}, |
||||
|
isCloudData() { |
||||
|
return this.collection.length > 0; |
||||
|
}, |
||||
|
isCloudDataList() { |
||||
|
return (this.isCloudData && (!this.parentField && !this.selfField)); |
||||
|
}, |
||||
|
isCloudDataTree() { |
||||
|
return (this.isCloudData && this.parentField && this.selfField); |
||||
|
}, |
||||
|
dataValue() { |
||||
|
let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || |
||||
|
this.modelValue !== undefined); |
||||
|
return isModelValue ? this.modelValue : this.value; |
||||
|
}, |
||||
|
hasValue() { |
||||
|
if (typeof this.dataValue === 'number') { |
||||
|
return true |
||||
|
} |
||||
|
return (this.dataValue != null) && (this.dataValue.length > 0) |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.$watch(() => { |
||||
|
var al = []; |
||||
|
['pageCurrent', |
||||
|
'pageSize', |
||||
|
'spaceInfo', |
||||
|
'value', |
||||
|
'modelValue', |
||||
|
'localdata', |
||||
|
'collection', |
||||
|
'action', |
||||
|
'field', |
||||
|
'orderby', |
||||
|
'where', |
||||
|
'getont', |
||||
|
'getcount', |
||||
|
'gettree' |
||||
|
].forEach(key => { |
||||
|
al.push(this[key]) |
||||
|
}); |
||||
|
return al |
||||
|
}, (newValue, oldValue) => { |
||||
|
let needReset = false |
||||
|
for (let i = 2; i < newValue.length; i++) { |
||||
|
if (newValue[i] != oldValue[i]) { |
||||
|
needReset = true |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
if (newValue[0] != oldValue[0]) { |
||||
|
this.page.current = this.pageCurrent |
||||
|
} |
||||
|
this.page.size = this.pageSize |
||||
|
|
||||
|
this.onPropsChange() |
||||
|
}) |
||||
|
this._treeData = [] |
||||
|
}, |
||||
|
methods: { |
||||
|
onPropsChange() { |
||||
|
this._treeData = []; |
||||
|
}, |
||||
|
|
||||
|
// 填充 pickview 数据
|
||||
|
async loadData() { |
||||
|
if (this.isLocalData) { |
||||
|
this.loadLocalData(); |
||||
|
} else if (this.isCloudDataList) { |
||||
|
this.loadCloudDataList(); |
||||
|
} else if (this.isCloudDataTree) { |
||||
|
this.loadCloudDataTree(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载本地数据
|
||||
|
async loadLocalData() { |
||||
|
this._treeData = []; |
||||
|
this._extractTree(this.localdata, this._treeData); |
||||
|
|
||||
|
let inputValue = this.dataValue; |
||||
|
if (inputValue === undefined) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Array.isArray(inputValue)) { |
||||
|
inputValue = inputValue[inputValue.length - 1]; |
||||
|
if (typeof inputValue === 'object' && inputValue[this.map.value]) { |
||||
|
inputValue = inputValue[this.map.value]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this.selected = this._findNodePath(inputValue, this.localdata); |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (单列)
|
||||
|
async loadCloudDataList() { |
||||
|
if (this.loading) { |
||||
|
return; |
||||
|
} |
||||
|
this.loading = true; |
||||
|
|
||||
|
try { |
||||
|
let response = await this.getCommand(); |
||||
|
let responseData = response.result.data; |
||||
|
|
||||
|
this._treeData = responseData; |
||||
|
|
||||
|
this._updateBindData(); |
||||
|
this._updateSelected(); |
||||
|
|
||||
|
this.onDataChange(); |
||||
|
} catch (e) { |
||||
|
this.errorMessage = e; |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (树形)
|
||||
|
async loadCloudDataTree() { |
||||
|
if (this.loading) { |
||||
|
return; |
||||
|
} |
||||
|
this.loading = true; |
||||
|
|
||||
|
try { |
||||
|
let commandOptions = { |
||||
|
field: this._cloudDataPostField(), |
||||
|
where: this._cloudDataTreeWhere() |
||||
|
}; |
||||
|
if (this.gettree) { |
||||
|
commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`; |
||||
|
} |
||||
|
|
||||
|
let response = await this.getCommand(commandOptions); |
||||
|
let responseData = response.result.data; |
||||
|
|
||||
|
this._treeData = responseData; |
||||
|
this._updateBindData(); |
||||
|
this._updateSelected(); |
||||
|
|
||||
|
this.onDataChange(); |
||||
|
} catch (e) { |
||||
|
this.errorMessage = e; |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (节点)
|
||||
|
async loadCloudDataNode(callback) { |
||||
|
if (this.loading) { |
||||
|
return; |
||||
|
} |
||||
|
this.loading = true; |
||||
|
|
||||
|
try { |
||||
|
let commandOptions = { |
||||
|
field: this._cloudDataPostField(), |
||||
|
where: this._cloudDataNodeWhere() |
||||
|
}; |
||||
|
|
||||
|
let response = await this.getCommand(commandOptions); |
||||
|
let responseData = response.result.data; |
||||
|
|
||||
|
callback(responseData); |
||||
|
} catch (e) { |
||||
|
this.errorMessage = e; |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 回显 Cloud 数据
|
||||
|
getCloudDataValue() { |
||||
|
if (this.isCloudDataList) { |
||||
|
return this.getCloudDataListValue(); |
||||
|
} |
||||
|
|
||||
|
if (this.isCloudDataTree) { |
||||
|
return this.getCloudDataTreeValue(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 回显 Cloud 数据 (单列)
|
||||
|
getCloudDataListValue() { |
||||
|
// 根据 field's as value标识匹配 where 条件
|
||||
|
let where = []; |
||||
|
let whereField = this._getForeignKeyByField(); |
||||
|
if (whereField) { |
||||
|
where.push(`${whereField} == '${this.dataValue}'`) |
||||
|
} |
||||
|
|
||||
|
where = where.join(' || '); |
||||
|
|
||||
|
if (this.where) { |
||||
|
where = `(${this.where}) && (${where})` |
||||
|
} |
||||
|
|
||||
|
return this.getCommand({ |
||||
|
field: this._cloudDataPostField(), |
||||
|
where |
||||
|
}).then((res) => { |
||||
|
this.selected = res.result.data; |
||||
|
return res.result.data; |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 回显 Cloud 数据 (树形)
|
||||
|
getCloudDataTreeValue() { |
||||
|
return this.getCommand({ |
||||
|
field: this._cloudDataPostField(), |
||||
|
getTreePath: { |
||||
|
startWith: `${this.selfField}=='${this.dataValue}'` |
||||
|
} |
||||
|
}).then((res) => { |
||||
|
let treePath = []; |
||||
|
this._extractTreePath(res.result.data, treePath); |
||||
|
this.selected = treePath; |
||||
|
return treePath; |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
getCommand(options = {}) { |
||||
|
/* eslint-disable no-undef */ |
||||
|
let db = uniCloud.database(this.spaceInfo) |
||||
|
|
||||
|
const action = options.action || this.action |
||||
|
if (action) { |
||||
|
db = db.action(action) |
||||
|
} |
||||
|
|
||||
|
const collection = options.collection || this.collection |
||||
|
db = db.collection(collection) |
||||
|
|
||||
|
const where = options.where || this.where |
||||
|
if (!(!where || !Object.keys(where).length)) { |
||||
|
db = db.where(where) |
||||
|
} |
||||
|
|
||||
|
const field = options.field || this.field |
||||
|
if (field) { |
||||
|
db = db.field(field) |
||||
|
} |
||||
|
|
||||
|
const orderby = options.orderby || this.orderby |
||||
|
if (orderby) { |
||||
|
db = db.orderBy(orderby) |
||||
|
} |
||||
|
|
||||
|
const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current |
||||
|
const size = options.pageSize !== undefined ? options.pageSize : this.page.size |
||||
|
const getCount = options.getcount !== undefined ? options.getcount : this.getcount |
||||
|
const getTree = options.gettree !== undefined ? options.gettree : this.gettree |
||||
|
|
||||
|
const getOptions = { |
||||
|
getCount, |
||||
|
getTree |
||||
|
} |
||||
|
if (options.getTreePath) { |
||||
|
getOptions.getTreePath = options.getTreePath |
||||
|
} |
||||
|
|
||||
|
db = db.skip(size * (current - 1)).limit(size).get(getOptions) |
||||
|
|
||||
|
return db |
||||
|
}, |
||||
|
|
||||
|
_cloudDataPostField() { |
||||
|
let fields = [this.field]; |
||||
|
if (this.parentField) { |
||||
|
fields.push(`${this.parentField} as parent_value`); |
||||
|
} |
||||
|
return fields.join(','); |
||||
|
}, |
||||
|
|
||||
|
_cloudDataTreeWhere() { |
||||
|
let result = [] |
||||
|
let selected = this.selected |
||||
|
let parentField = this.parentField |
||||
|
if (parentField) { |
||||
|
result.push(`${parentField} == null || ${parentField} == ""`) |
||||
|
} |
||||
|
if (selected.length) { |
||||
|
for (var i = 0; i < selected.length - 1; i++) { |
||||
|
result.push(`${parentField} == '${selected[i].value}'`) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let where = [] |
||||
|
if (this.where) { |
||||
|
where.push(`(${this.where})`) |
||||
|
} |
||||
|
|
||||
|
if (result.length) { |
||||
|
where.push(`(${result.join(' || ')})`) |
||||
|
} |
||||
|
|
||||
|
return where.join(' && ') |
||||
|
}, |
||||
|
|
||||
|
_cloudDataNodeWhere() { |
||||
|
let where = [] |
||||
|
let selected = this.selected; |
||||
|
if (selected.length) { |
||||
|
where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`); |
||||
|
} |
||||
|
|
||||
|
where = where.join(' || '); |
||||
|
|
||||
|
if (this.where) { |
||||
|
return `(${this.where}) && (${where})` |
||||
|
} |
||||
|
|
||||
|
return where |
||||
|
}, |
||||
|
|
||||
|
_getWhereByForeignKey() { |
||||
|
let result = [] |
||||
|
let whereField = this._getForeignKeyByField(); |
||||
|
if (whereField) { |
||||
|
result.push(`${whereField} == '${this.dataValue}'`) |
||||
|
} |
||||
|
|
||||
|
if (this.where) { |
||||
|
return `(${this.where}) && (${result.join(' || ')})` |
||||
|
} |
||||
|
|
||||
|
return result.join(' || ') |
||||
|
}, |
||||
|
|
||||
|
_getForeignKeyByField() { |
||||
|
let fields = this.field.split(','); |
||||
|
let whereField = null; |
||||
|
for (let i = 0; i < fields.length; i++) { |
||||
|
const items = fields[i].split('as'); |
||||
|
if (items.length < 2) { |
||||
|
continue; |
||||
|
} |
||||
|
if (items[1].trim() === 'value') { |
||||
|
whereField = items[0].trim(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return whereField; |
||||
|
}, |
||||
|
|
||||
|
_updateBindData(node) { |
||||
|
const { |
||||
|
dataList, |
||||
|
hasNodes |
||||
|
} = this._filterData(this._treeData, this.selected) |
||||
|
|
||||
|
let isleaf = this._stepSearh === false && !hasNodes |
||||
|
|
||||
|
if (node) { |
||||
|
node.isleaf = isleaf |
||||
|
} |
||||
|
|
||||
|
this.dataList = dataList |
||||
|
this.selectedIndex = dataList.length - 1 |
||||
|
|
||||
|
if (!isleaf && this.selected.length < dataList.length) { |
||||
|
this.selected.push({ |
||||
|
value: null, |
||||
|
text: "请选择" |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
isleaf, |
||||
|
hasNodes |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
_updateSelected() { |
||||
|
let dl = this.dataList |
||||
|
let sl = this.selected |
||||
|
let textField = this.map.text |
||||
|
let valueField = this.map.value |
||||
|
for (let i = 0; i < sl.length; i++) { |
||||
|
let value = sl[i].value |
||||
|
let dl2 = dl[i] |
||||
|
for (let j = 0; j < dl2.length; j++) { |
||||
|
let item2 = dl2[j] |
||||
|
if (item2[valueField] === value) { |
||||
|
sl[i].text = item2[textField] |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
_filterData(data, paths) { |
||||
|
let dataList = [] |
||||
|
let hasNodes = true |
||||
|
|
||||
|
dataList.push(data.filter((item) => { |
||||
|
return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '') |
||||
|
})) |
||||
|
for (let i = 0; i < paths.length; i++) { |
||||
|
let value = paths[i].value |
||||
|
let nodes = data.filter((item) => { |
||||
|
return item.parent_value === value |
||||
|
}) |
||||
|
|
||||
|
if (nodes.length) { |
||||
|
dataList.push(nodes) |
||||
|
} else { |
||||
|
hasNodes = false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
dataList, |
||||
|
hasNodes |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
_extractTree(nodes, result, parent_value) { |
||||
|
let list = result || [] |
||||
|
let valueField = this.map.value |
||||
|
for (let i = 0; i < nodes.length; i++) { |
||||
|
let node = nodes[i] |
||||
|
|
||||
|
let child = {} |
||||
|
for (let key in node) { |
||||
|
if (key !== 'children') { |
||||
|
child[key] = node[key] |
||||
|
} |
||||
|
} |
||||
|
if (parent_value !== null && parent_value !== undefined && parent_value !== '') { |
||||
|
child.parent_value = parent_value |
||||
|
} |
||||
|
result.push(child) |
||||
|
|
||||
|
let children = node.children |
||||
|
if (children) { |
||||
|
this._extractTree(children, result, node[valueField]) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
_extractTreePath(nodes, result) { |
||||
|
let list = result || [] |
||||
|
for (let i = 0; i < nodes.length; i++) { |
||||
|
let node = nodes[i] |
||||
|
|
||||
|
let child = {} |
||||
|
for (let key in node) { |
||||
|
if (key !== 'children') { |
||||
|
child[key] = node[key] |
||||
|
} |
||||
|
} |
||||
|
result.push(child) |
||||
|
|
||||
|
let children = node.children |
||||
|
if (children) { |
||||
|
this._extractTreePath(children, result) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
_findNodePath(key, nodes, path = []) { |
||||
|
let textField = this.map.text |
||||
|
let valueField = this.map.value |
||||
|
for (let i = 0; i < nodes.length; i++) { |
||||
|
let node = nodes[i] |
||||
|
let children = node.children |
||||
|
let text = node[textField] |
||||
|
let value = node[valueField] |
||||
|
|
||||
|
path.push({ |
||||
|
value, |
||||
|
text |
||||
|
}) |
||||
|
|
||||
|
if (value === key) { |
||||
|
return path |
||||
|
} |
||||
|
|
||||
|
if (children) { |
||||
|
const p = this._findNodePath(key, children, path) |
||||
|
if (p.length) { |
||||
|
return p |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
path.pop() |
||||
|
} |
||||
|
return [] |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,693 @@ |
|||||
|
export type PaginationType = { |
||||
|
current : number, |
||||
|
size : number, |
||||
|
count : number |
||||
|
} |
||||
|
|
||||
|
export type LoadMoreType = { |
||||
|
contentdown : string, |
||||
|
contentrefresh : string, |
||||
|
contentnomore : string |
||||
|
} |
||||
|
|
||||
|
export type SelectedItemType = { |
||||
|
name : string, |
||||
|
value : string, |
||||
|
} |
||||
|
|
||||
|
export type GetCommandOptions = { |
||||
|
collection ?: UTSJSONObject, |
||||
|
field ?: string, |
||||
|
orderby ?: string, |
||||
|
where ?: any, |
||||
|
pageData ?: string, |
||||
|
pageCurrent ?: number, |
||||
|
pageSize ?: number, |
||||
|
getCount ?: boolean, |
||||
|
getTree ?: any, |
||||
|
getTreePath ?: UTSJSONObject, |
||||
|
startwith ?: string, |
||||
|
limitlevel ?: number, |
||||
|
groupby ?: string, |
||||
|
groupField ?: string, |
||||
|
distinct ?: boolean, |
||||
|
pageIndistinct ?: boolean, |
||||
|
foreignKey ?: string, |
||||
|
loadtime ?: string, |
||||
|
manual ?: boolean |
||||
|
} |
||||
|
|
||||
|
const DefaultSelectedNode = { |
||||
|
text: '请选择', |
||||
|
value: '' |
||||
|
} |
||||
|
|
||||
|
export const dataPicker = defineMixin({ |
||||
|
props: { |
||||
|
localdata: { |
||||
|
type: Array as PropType<Array<UTSJSONObject>>, |
||||
|
default: [] as Array<UTSJSONObject> |
||||
|
}, |
||||
|
collection: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
field: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
orderby: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
where: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
pageData: { |
||||
|
type: String, |
||||
|
default: 'add' |
||||
|
}, |
||||
|
pageCurrent: { |
||||
|
type: Number, |
||||
|
default: 1 |
||||
|
}, |
||||
|
pageSize: { |
||||
|
type: Number, |
||||
|
default: 20 |
||||
|
}, |
||||
|
getcount: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
gettree: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
gettreepath: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
startwith: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
limitlevel: { |
||||
|
type: Number, |
||||
|
default: 10 |
||||
|
}, |
||||
|
groupby: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
groupField: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
distinct: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
pageIndistinct: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
foreignKey: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
loadtime: { |
||||
|
type: String, |
||||
|
default: 'auto' |
||||
|
}, |
||||
|
manual: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
preload: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
stepSearh: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
selfField: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
parentField: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
multiple: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
value: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
modelValue: { |
||||
|
type: Object, |
||||
|
default: '' |
||||
|
}, |
||||
|
defaultProps: { |
||||
|
type: Object as PropType<UTSJSONObject>, |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
loading: false, |
||||
|
error: null as UniCloudError | null, |
||||
|
treeData: [] as Array<UTSJSONObject>, |
||||
|
selectedIndex: 0, |
||||
|
selectedNodes: [] as Array<UTSJSONObject>, |
||||
|
selectedPages: [] as Array<UTSJSONObject>[], |
||||
|
selectedValue: '', |
||||
|
selectedPaths: [] as Array<UTSJSONObject>, |
||||
|
pagination: { |
||||
|
current: 1, |
||||
|
size: 20, |
||||
|
count: 0 |
||||
|
} as PaginationType |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
mappingTextName() : string { |
||||
|
// TODO |
||||
|
return (this.defaultProps != null) ? this.defaultProps!.getString('text', 'text') : 'text' |
||||
|
}, |
||||
|
mappingValueName() : string { |
||||
|
// TODO |
||||
|
return (this.defaultProps != null) ? this.defaultProps!.getString('value', 'value') : 'value' |
||||
|
}, |
||||
|
currentDataList() : Array<UTSJSONObject> { |
||||
|
if (this.selectedIndex > this.selectedPages.length - 1) { |
||||
|
return [] as Array<UTSJSONObject> |
||||
|
} |
||||
|
return this.selectedPages[this.selectedIndex] |
||||
|
}, |
||||
|
isLocalData() : boolean { |
||||
|
return this.localdata.length > 0 |
||||
|
}, |
||||
|
isCloudData() : boolean { |
||||
|
return this._checkIsNotNull(this.collection) |
||||
|
}, |
||||
|
isCloudDataList() : boolean { |
||||
|
return (this.isCloudData && (this.parentField.length == 0 && this.selfField.length == 0)) |
||||
|
}, |
||||
|
isCloudDataTree() : boolean { |
||||
|
return (this.isCloudData && this.parentField.length > 0 && this.selfField.length > 0) |
||||
|
}, |
||||
|
dataValue() : any { |
||||
|
return this.hasModelValue ? this.modelValue : this.value |
||||
|
}, |
||||
|
hasCloudTreeData() : boolean { |
||||
|
return this.treeData.length > 0 |
||||
|
}, |
||||
|
hasModelValue() : boolean { |
||||
|
if (typeof this.modelValue == 'string') { |
||||
|
const valueString = this.modelValue as string |
||||
|
return (valueString.length > 0) |
||||
|
} else if (Array.isArray(this.modelValue)) { |
||||
|
const valueArray = this.modelValue as Array<string> |
||||
|
return (valueArray.length > 0) |
||||
|
} |
||||
|
return false |
||||
|
}, |
||||
|
hasCloudDataValue() : boolean { |
||||
|
if (typeof this.dataValue == 'string') { |
||||
|
const valueString = this.dataValue as string |
||||
|
return (valueString.length > 0) |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.pagination.current = this.pageCurrent |
||||
|
this.pagination.size = this.pageSize |
||||
|
|
||||
|
this.$watch( |
||||
|
() : any => [ |
||||
|
this.pageCurrent, |
||||
|
this.pageSize, |
||||
|
this.localdata, |
||||
|
this.value, |
||||
|
this.collection, |
||||
|
this.field, |
||||
|
this.getcount, |
||||
|
this.orderby, |
||||
|
this.where, |
||||
|
this.groupby, |
||||
|
this.groupField, |
||||
|
this.distinct |
||||
|
], |
||||
|
(newValue : Array<any>, oldValue : Array<any>) => { |
||||
|
this.pagination.size = this.pageSize |
||||
|
if (newValue[0] !== oldValue[0]) { |
||||
|
this.pagination.current = this.pageCurrent |
||||
|
} |
||||
|
|
||||
|
this.onPropsChange() |
||||
|
} |
||||
|
) |
||||
|
}, |
||||
|
methods: { |
||||
|
onPropsChange() { |
||||
|
this.selectedIndex = 0 |
||||
|
this.treeData.length = 0 |
||||
|
this.selectedNodes.length = 0 |
||||
|
this.selectedPages.length = 0 |
||||
|
this.selectedPaths.length = 0 |
||||
|
|
||||
|
// 加载数据 |
||||
|
this.$nextTick(() => { |
||||
|
this.loadData() |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
onTabSelect(index : number) { |
||||
|
this.selectedIndex = index |
||||
|
}, |
||||
|
|
||||
|
onNodeClick(nodeData : UTSJSONObject) { |
||||
|
if (nodeData.getBoolean('disable', false)) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const isLeaf = this._checkIsLeafNode(nodeData) |
||||
|
|
||||
|
this._trimSelectedNodes(nodeData) |
||||
|
|
||||
|
this.$emit('nodeclick', nodeData) |
||||
|
|
||||
|
if (this.isLocalData) { |
||||
|
if (isLeaf || !this._checkHasChildren(nodeData)) { |
||||
|
this.onFinish() |
||||
|
} |
||||
|
} else if (this.isCloudDataList) { |
||||
|
this.onFinish() |
||||
|
} else if (this.isCloudDataTree) { |
||||
|
if (isLeaf) { |
||||
|
this.onFinish() |
||||
|
} else if (!this._checkHasChildren(nodeData)) { |
||||
|
// 尝试请求一次,如果没有返回数据标记为叶子节点 |
||||
|
this.loadCloudDataNode(nodeData) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
getChangeNodes(): Array<UTSJSONObject> { |
||||
|
const nodes: Array<UTSJSONObject> = [] |
||||
|
this.selectedNodes.forEach((node : UTSJSONObject) => { |
||||
|
const newNode: UTSJSONObject = {} |
||||
|
newNode[this.mappingTextName] = node.getString(this.mappingTextName) |
||||
|
newNode[this.mappingValueName] = node.getString(this.mappingValueName) |
||||
|
nodes.push(newNode) |
||||
|
}) |
||||
|
return nodes |
||||
|
}, |
||||
|
|
||||
|
onFinish() { }, |
||||
|
|
||||
|
// 加载数据(自动判定环境) |
||||
|
loadData() { |
||||
|
if (this.isLocalData) { |
||||
|
this.loadLocalData() |
||||
|
} else if (this.isCloudDataList) { |
||||
|
this.loadCloudDataList() |
||||
|
} else if (this.isCloudDataTree) { |
||||
|
this.loadCloudDataTree() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载本地数据 |
||||
|
loadLocalData() { |
||||
|
this.treeData = this.localdata |
||||
|
if (Array.isArray(this.dataValue)) { |
||||
|
const value = this.dataValue as Array<UTSJSONObject> |
||||
|
this.selectedPaths = value.slice(0) |
||||
|
this._pushSelectedTreeNodes(value, this.localdata) |
||||
|
} else { |
||||
|
this._pushSelectedNodes(this.localdata) |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (单列) |
||||
|
loadCloudDataList() { |
||||
|
this._loadCloudData(null, (data : Array<UTSJSONObject>) => { |
||||
|
this.treeData = data |
||||
|
this._pushSelectedNodes(data) |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (树形) |
||||
|
loadCloudDataTree() { |
||||
|
let commandOptions = { |
||||
|
field: this._cloudDataPostField(), |
||||
|
where: this._cloudDataTreeWhere(), |
||||
|
getTree: true |
||||
|
} as GetCommandOptions |
||||
|
if (this._checkIsNotNull(this.gettree)) { |
||||
|
commandOptions.startwith = `${this.selfField}=='${this.dataValue as string}'` |
||||
|
} |
||||
|
this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => { |
||||
|
this.treeData = data |
||||
|
if (this.selectedPaths.length > 0) { |
||||
|
this._pushSelectedTreeNodes(this.selectedPaths, data) |
||||
|
} else { |
||||
|
this._pushSelectedNodes(data) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 加载 Cloud 数据 (节点) |
||||
|
loadCloudDataNode(nodeData : UTSJSONObject) { |
||||
|
const commandOptions = { |
||||
|
field: this._cloudDataPostField(), |
||||
|
where: this._cloudDataNodeWhere() |
||||
|
} as GetCommandOptions |
||||
|
this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => { |
||||
|
nodeData['children'] = data |
||||
|
if (data.length == 0) { |
||||
|
nodeData['isleaf'] = true |
||||
|
this.onFinish() |
||||
|
} else { |
||||
|
this._pushSelectedNodes(data) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 回显 Cloud Tree Path |
||||
|
loadCloudDataPath() { |
||||
|
if (!this.hasCloudDataValue) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const command : GetCommandOptions = {} |
||||
|
|
||||
|
// 单列 |
||||
|
if (this.isCloudDataList) { |
||||
|
// 根据 field's as value标识匹配 where 条件 |
||||
|
let where : Array<string> = []; |
||||
|
let whereField = this._getForeignKeyByField(); |
||||
|
if (whereField.length > 0) { |
||||
|
where.push(`${whereField} == '${this.dataValue as string}'`) |
||||
|
} |
||||
|
|
||||
|
let whereString = where.join(' || ') |
||||
|
if (this._checkIsNotNull(this.where)) { |
||||
|
whereString = `(${this.where}) && (${whereString})` |
||||
|
} |
||||
|
|
||||
|
command.field = this._cloudDataPostField() |
||||
|
command.where = whereString |
||||
|
} |
||||
|
|
||||
|
// 树形 |
||||
|
if (this.isCloudDataTree) { |
||||
|
command.field = this._cloudDataPostField() |
||||
|
command.getTreePath = { |
||||
|
startWith: `${this.selfField}=='${this.dataValue as string}'` |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this._loadCloudData(command, (data : Array<UTSJSONObject>) => { |
||||
|
this._extractTreePath(data, this.selectedPaths) |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
_loadCloudData(options ?: GetCommandOptions, callback ?: ((data : Array<UTSJSONObject>) => void)) { |
||||
|
if (this.loading) { |
||||
|
return |
||||
|
} |
||||
|
this.loading = true |
||||
|
|
||||
|
this.error = null |
||||
|
|
||||
|
this._getCommand(options).then((response : UniCloudDBGetResult) => { |
||||
|
callback?.(response.data) |
||||
|
}).catch((err : any | null) => { |
||||
|
this.error = err as UniCloudError |
||||
|
}).finally(() => { |
||||
|
this.loading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
_cloudDataPostField() : string { |
||||
|
let fields = [this.field]; |
||||
|
if (this.parentField.length > 0) { |
||||
|
fields.push(`${this.parentField} as parent_value`) |
||||
|
} |
||||
|
return fields.join(',') |
||||
|
}, |
||||
|
|
||||
|
_cloudDataTreeWhere() : string { |
||||
|
let result : Array<string> = [] |
||||
|
let selectedNodes = this.selectedNodes.length > 0 ? this.selectedNodes : this.selectedPaths |
||||
|
let parentField = this.parentField |
||||
|
if (parentField.length > 0) { |
||||
|
result.push(`${parentField} == null || ${parentField} == ""`) |
||||
|
} |
||||
|
if (selectedNodes.length > 0) { |
||||
|
for (var i = 0; i < selectedNodes.length - 1; i++) { |
||||
|
const parentFieldValue = selectedNodes[i].getString('value', '') |
||||
|
result.push(`${parentField} == '${parentFieldValue}'`) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let where : Array<string> = [] |
||||
|
if (this._checkIsNotNull(this.where)) { |
||||
|
where.push(`(${this.where as string})`) |
||||
|
} |
||||
|
|
||||
|
if (result.length > 0) { |
||||
|
where.push(`(${result.join(' || ')})`) |
||||
|
} |
||||
|
|
||||
|
return where.join(' && ') |
||||
|
}, |
||||
|
|
||||
|
_cloudDataNodeWhere() : string { |
||||
|
const where : Array<string> = [] |
||||
|
if (this.selectedNodes.length > 0) { |
||||
|
const value = this.selectedNodes[this.selectedNodes.length - 1].getString('value', '') |
||||
|
where.push(`${this.parentField} == '${value}'`) |
||||
|
} |
||||
|
|
||||
|
let whereString = where.join(' || ') |
||||
|
if (this._checkIsNotNull(this.where)) { |
||||
|
return `(${this.where as string}) && (${whereString})` |
||||
|
} |
||||
|
|
||||
|
return whereString |
||||
|
}, |
||||
|
|
||||
|
_getWhereByForeignKey() : string { |
||||
|
let result : Array<string> = [] |
||||
|
let whereField = this._getForeignKeyByField(); |
||||
|
if (whereField.length > 0) { |
||||
|
result.push(`${whereField} == '${this.dataValue as string}'`) |
||||
|
} |
||||
|
|
||||
|
if (this._checkIsNotNull(this.where)) { |
||||
|
return `(${this.where}) && (${result.join(' || ')})` |
||||
|
} |
||||
|
|
||||
|
return result.join(' || ') |
||||
|
}, |
||||
|
|
||||
|
_getForeignKeyByField() : string { |
||||
|
const fields = this.field.split(',') |
||||
|
let whereField = '' |
||||
|
for (let i = 0; i < fields.length; i++) { |
||||
|
const items = fields[i].split('as') |
||||
|
if (items.length < 2) { |
||||
|
continue |
||||
|
} |
||||
|
if (items[1].trim() === 'value') { |
||||
|
whereField = items[0].trim() |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
return whereField |
||||
|
}, |
||||
|
|
||||
|
_getCommand(options ?: GetCommandOptions) : Promise<UniCloudDBGetResult> { |
||||
|
let db = uniCloud.databaseForJQL() |
||||
|
|
||||
|
let collection = Array.isArray(this.collection) ? db.collection(...(this.collection as Array<any>)) : db.collection(this.collection) |
||||
|
|
||||
|
let filter : UniCloudDBFilter | null = null |
||||
|
if (this.foreignKey.length > 0) { |
||||
|
filter = collection.foreignKey(this.foreignKey) |
||||
|
} |
||||
|
|
||||
|
const where : any = options?.where ?? this.where |
||||
|
if (typeof where == 'string') { |
||||
|
const whereString = where as string |
||||
|
if (whereString.length > 0) { |
||||
|
filter = (filter != null) ? filter.where(where) : collection.where(where) |
||||
|
} |
||||
|
} else { |
||||
|
filter = (filter != null) ? filter.where(where) : collection.where(where) |
||||
|
} |
||||
|
|
||||
|
let query : UniCloudDBQuery | null = null |
||||
|
if (this.field.length > 0) { |
||||
|
query = (filter != null) ? filter.field(this.field) : collection.field(this.field) |
||||
|
} |
||||
|
if (this.groupby.length > 0) { |
||||
|
if (query != null) { |
||||
|
query = query.groupBy(this.groupby) |
||||
|
} else if (filter != null) { |
||||
|
query = filter.groupBy(this.groupby) |
||||
|
} |
||||
|
} |
||||
|
if (this.groupField.length > 0) { |
||||
|
if (query != null) { |
||||
|
query = query.groupField(this.groupField) |
||||
|
} else if (filter != null) { |
||||
|
query = filter.groupField(this.groupField) |
||||
|
} |
||||
|
} |
||||
|
if (this.distinct == true) { |
||||
|
if (query != null) { |
||||
|
query = query.distinct(this.field) |
||||
|
} else if (filter != null) { |
||||
|
query = filter.distinct(this.field) |
||||
|
} |
||||
|
} |
||||
|
if (this.orderby.length > 0) { |
||||
|
if (query != null) { |
||||
|
query = query.orderBy(this.orderby) |
||||
|
} else if (filter != null) { |
||||
|
query = filter.orderBy(this.orderby) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const size = this.pagination.size |
||||
|
const current = this.pagination.current |
||||
|
if (query != null) { |
||||
|
query = query.skip(size * (current - 1)).limit(size) |
||||
|
} else if (filter != null) { |
||||
|
query = filter.skip(size * (current - 1)).limit(size) |
||||
|
} else { |
||||
|
query = collection.skip(size * (current - 1)).limit(size) |
||||
|
} |
||||
|
|
||||
|
const getOptions = {} |
||||
|
const treeOptions = { |
||||
|
limitLevel: this.limitlevel, |
||||
|
startWith: this.startwith |
||||
|
} |
||||
|
if (this.getcount == true) { |
||||
|
getOptions['getCount'] = this.getcount |
||||
|
} |
||||
|
|
||||
|
const getTree : any = options?.getTree ?? this.gettree |
||||
|
if (typeof getTree == 'string') { |
||||
|
const getTreeString = getTree as string |
||||
|
if (getTreeString.length > 0) { |
||||
|
getOptions['getTree'] = treeOptions |
||||
|
} |
||||
|
} else if (typeof getTree == 'object') { |
||||
|
getOptions['getTree'] = treeOptions |
||||
|
} else { |
||||
|
getOptions['getTree'] = getTree |
||||
|
} |
||||
|
|
||||
|
const getTreePath = options?.getTreePath ?? this.gettreepath |
||||
|
if (typeof getTreePath == 'string') { |
||||
|
const getTreePathString = getTreePath as string |
||||
|
if (getTreePathString.length > 0) { |
||||
|
getOptions['getTreePath'] = getTreePath |
||||
|
} |
||||
|
} else { |
||||
|
getOptions['getTreePath'] = getTreePath |
||||
|
} |
||||
|
|
||||
|
return query.get(getOptions) |
||||
|
}, |
||||
|
|
||||
|
_checkIsNotNull(value : any) : boolean { |
||||
|
if (typeof value == 'string') { |
||||
|
const valueString = value as string |
||||
|
return (valueString.length > 0) |
||||
|
} else if (value instanceof UTSJSONObject) { |
||||
|
return true |
||||
|
} |
||||
|
return false |
||||
|
}, |
||||
|
|
||||
|
_checkIsLeafNode(nodeData : UTSJSONObject) : boolean { |
||||
|
if (this.selectedIndex >= this.limitlevel) { |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
if (nodeData.getBoolean('isleaf', false)) { |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
return false |
||||
|
}, |
||||
|
|
||||
|
_checkHasChildren(nodeData : UTSJSONObject) : boolean { |
||||
|
const children = nodeData.getArray('children') ?? ([] as Array<any>) |
||||
|
return children.length > 0 |
||||
|
}, |
||||
|
|
||||
|
_pushSelectedNodes(nodes : Array<UTSJSONObject>) { |
||||
|
this.selectedNodes.push(DefaultSelectedNode) |
||||
|
this.selectedPages.push(nodes) |
||||
|
this.selectedIndex = this.selectedPages.length - 1 |
||||
|
}, |
||||
|
|
||||
|
_trimSelectedNodes(nodeData : UTSJSONObject) { |
||||
|
this.selectedNodes.splice(this.selectedIndex) |
||||
|
this.selectedNodes.push(nodeData) |
||||
|
|
||||
|
if (this.selectedPages.length > 0) { |
||||
|
this.selectedPages.splice(this.selectedIndex + 1) |
||||
|
} |
||||
|
|
||||
|
const children = nodeData.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>) |
||||
|
if (children.length > 0) { |
||||
|
this.selectedNodes.push(DefaultSelectedNode) |
||||
|
this.selectedPages.push(children) |
||||
|
} |
||||
|
|
||||
|
this.selectedIndex = this.selectedPages.length - 1 |
||||
|
}, |
||||
|
|
||||
|
_pushSelectedTreeNodes(paths : Array<UTSJSONObject>, nodes : Array<UTSJSONObject>) { |
||||
|
let children : Array<UTSJSONObject> = nodes |
||||
|
paths.forEach((node : UTSJSONObject) => { |
||||
|
const findNode = children.find((item : UTSJSONObject) : boolean => { |
||||
|
return (item.getString(this.mappingValueName) == node.getString(this.mappingValueName)) |
||||
|
}) |
||||
|
if (findNode != null) { |
||||
|
this.selectedPages.push(children) |
||||
|
this.selectedNodes.push(node) |
||||
|
children = findNode.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>) |
||||
|
} |
||||
|
}) |
||||
|
this.selectedIndex = this.selectedPages.length - 1 |
||||
|
}, |
||||
|
|
||||
|
_extractTreePath(nodes : Array<UTSJSONObject>, result : Array<UTSJSONObject>) { |
||||
|
if (nodes.length == 0) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const node = nodes[0] |
||||
|
result.push(node) |
||||
|
|
||||
|
const children = node.getArray<UTSJSONObject>('children') |
||||
|
if (Array.isArray(children) && children!.length > 0) { |
||||
|
this._extractTreePath(children, result) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
@ -0,0 +1,76 @@ |
|||||
|
.uni-data-pickerview { |
||||
|
position: relative; |
||||
|
flex-direction: column; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.loading-cover { |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background-color: rgba(150, 150, 150, .1); |
||||
|
} |
||||
|
|
||||
|
.error { |
||||
|
background-color: #fff; |
||||
|
padding: 15px; |
||||
|
} |
||||
|
|
||||
|
.error-text { |
||||
|
color: #DD524D; |
||||
|
} |
||||
|
|
||||
|
.selected-node-list { |
||||
|
flex-direction: row; |
||||
|
flex-wrap: nowrap; |
||||
|
} |
||||
|
|
||||
|
.selected-node-item { |
||||
|
margin-left: 10px; |
||||
|
margin-right: 10px; |
||||
|
padding: 8px 10px 8px 10px; |
||||
|
border-bottom: 2px solid transparent; |
||||
|
} |
||||
|
|
||||
|
.selected-node-item-active { |
||||
|
color: #007aff; |
||||
|
border-bottom-color: #007aff; |
||||
|
} |
||||
|
|
||||
|
.list-view { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.list-item { |
||||
|
flex-direction: row; |
||||
|
justify-content: space-between; |
||||
|
padding: 12px 15px; |
||||
|
border-bottom: 1px solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.item-text { |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.item-text-disabled { |
||||
|
opacity: .5; |
||||
|
} |
||||
|
|
||||
|
.item-text-overflow { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.check { |
||||
|
margin-right: 5px; |
||||
|
border: 2px solid #007aff; |
||||
|
border-left: 0; |
||||
|
border-top: 0; |
||||
|
height: 12px; |
||||
|
width: 6px; |
||||
|
transform-origin: center; |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
<template> |
||||
|
<view class="uni-data-pickerview"> |
||||
|
<view v-if="error!=null" class="error"> |
||||
|
<text class="error-text">{{error!.errMsg}}</text> |
||||
|
</view> |
||||
|
<scroll-view v-if="!isCloudDataList" :scroll-x="true"> |
||||
|
<view class="selected-node-list"> |
||||
|
<template v-for="(item, index) in selectedNodes"> |
||||
|
<text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}" |
||||
|
@click="onTabSelect(index)"> |
||||
|
{{item[mappingTextName]}} |
||||
|
</text> |
||||
|
</template> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<list-view class="list-view" :scroll-y="true"> |
||||
|
<list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)"> |
||||
|
<text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text> |
||||
|
<text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text> |
||||
|
</list-item> |
||||
|
</list-view> |
||||
|
<view class="loading-cover" v-if="loading"> |
||||
|
<slot name="pickerview-loading" :loading="loading"></slot> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { dataPicker } from "./uni-data-picker.uts" |
||||
|
|
||||
|
/** |
||||
|
* DataPickerview |
||||
|
* @description uni-data-pickerview |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
||||
|
* @property {Array} localdata 本地数据,参考 |
||||
|
* @property {Boolean} step-searh = [true|false] 是否分布查询 |
||||
|
* @value true 启用分布查询,仅查询当前选中节点 |
||||
|
* @value false 关闭分布查询,一次查询出所有数据 |
||||
|
* @property {String|DBFieldString} self-field 分布查询当前字段名称 |
||||
|
* @property {String|DBFieldString} parent-field 分布查询父字段名称 |
||||
|
* @property {String|DBCollectionString} collection 表名 |
||||
|
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
||||
|
* @property {String} orderby 排序字段及正序倒叙设置 |
||||
|
* @property {String|JQLString} where 查询条件 |
||||
|
*/ |
||||
|
export default { |
||||
|
name: 'UniDataPickerView', |
||||
|
emits: ['nodeclick', 'change', 'update:modelValue'], |
||||
|
mixins: [dataPicker], |
||||
|
props: { |
||||
|
ellipsis: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.loadData() |
||||
|
}, |
||||
|
methods: { |
||||
|
onFinish() { |
||||
|
this.$emit('change', this.getChangeNodes()) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
@import url("uni-data-pickerview.css"); |
||||
|
</style> |
||||
@ -0,0 +1,323 @@ |
|||||
|
<template> |
||||
|
<view class="uni-data-pickerview"> |
||||
|
<scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true"> |
||||
|
<view class="selected-list"> |
||||
|
<view |
||||
|
class="selected-item" |
||||
|
v-for="(item,index) in selected" |
||||
|
:key="index" |
||||
|
:class="{ |
||||
|
'selected-item-active':index == selectedIndex |
||||
|
}" |
||||
|
@click="handleSelect(index)" |
||||
|
> |
||||
|
<text>{{item.text || ''}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<view class="tab-c"> |
||||
|
<scroll-view class="list" :scroll-y="true"> |
||||
|
<view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in dataList[selectedIndex]" :key="j" |
||||
|
@click="handleNodeClick(item, selectedIndex, j)"> |
||||
|
<text class="item-text">{{item[map.text]}}</text> |
||||
|
<view class="check" v-if="selected.length > selectedIndex && item[map.value] == selected[selectedIndex].value"></view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
|
||||
|
<view class="loading-cover" v-if="loading"> |
||||
|
<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more> |
||||
|
</view> |
||||
|
<view class="error-message" v-if="errorMessage"> |
||||
|
<text class="error-text">{{errorMessage}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import dataPicker from "./uni-data-picker.js" |
||||
|
|
||||
|
/** |
||||
|
* DataPickerview |
||||
|
* @description uni-data-pickerview |
||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=3796 |
||||
|
* @property {Array} localdata 本地数据,参考 |
||||
|
* @property {Boolean} step-searh = [true|false] 是否分布查询 |
||||
|
* @value true 启用分布查询,仅查询当前选中节点 |
||||
|
* @value false 关闭分布查询,一次查询出所有数据 |
||||
|
* @property {String|DBFieldString} self-field 分布查询当前字段名称 |
||||
|
* @property {String|DBFieldString} parent-field 分布查询父字段名称 |
||||
|
* @property {String|DBCollectionString} collection 表名 |
||||
|
* @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割 |
||||
|
* @property {String} orderby 排序字段及正序倒叙设置 |
||||
|
* @property {String|JQLString} where 查询条件 |
||||
|
*/ |
||||
|
export default { |
||||
|
name: 'UniDataPickerView', |
||||
|
emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'], |
||||
|
mixins: [dataPicker], |
||||
|
props: { |
||||
|
managedMode: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
ellipsis: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
if (!this.managedMode) { |
||||
|
this.$nextTick(() => { |
||||
|
this.loadData(); |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
onPropsChange() { |
||||
|
this._treeData = []; |
||||
|
this.selectedIndex = 0; |
||||
|
this.$nextTick(() => { |
||||
|
this.loadData(); |
||||
|
}) |
||||
|
}, |
||||
|
handleSelect(index) { |
||||
|
this.selectedIndex = index; |
||||
|
}, |
||||
|
handleNodeClick(item, i, j) { |
||||
|
if (item.disable) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const node = this.dataList[i][j]; |
||||
|
const text = node[this.map.text]; |
||||
|
const value = node[this.map.value]; |
||||
|
|
||||
|
if (i < this.selected.length - 1) { |
||||
|
this.selected.splice(i, this.selected.length - i) |
||||
|
this.selected.push({ |
||||
|
text, |
||||
|
value |
||||
|
}) |
||||
|
} else if (i === this.selected.length - 1) { |
||||
|
this.selected.splice(i, 1, { |
||||
|
text, |
||||
|
value |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
if (node.isleaf) { |
||||
|
this.onSelectedChange(node, node.isleaf) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const { |
||||
|
isleaf, |
||||
|
hasNodes |
||||
|
} = this._updateBindData() |
||||
|
|
||||
|
// 本地数据 |
||||
|
if (this.isLocalData) { |
||||
|
this.onSelectedChange(node, (!hasNodes || isleaf)) |
||||
|
} else if (this.isCloudDataList) { // Cloud 数据 (单列) |
||||
|
this.onSelectedChange(node, true) |
||||
|
} else if (this.isCloudDataTree) { // Cloud 数据 (树形) |
||||
|
if (isleaf) { |
||||
|
this.onSelectedChange(node, node.isleaf) |
||||
|
} else if (!hasNodes) { // 请求一次服务器以确定是否为叶子节点 |
||||
|
this.loadCloudDataNode((data) => { |
||||
|
if (!data.length) { |
||||
|
node.isleaf = true |
||||
|
} else { |
||||
|
this._treeData.push(...data) |
||||
|
this._updateBindData(node) |
||||
|
} |
||||
|
this.onSelectedChange(node, node.isleaf) |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
updateData(data) { |
||||
|
this._treeData = data.treeData |
||||
|
this.selected = data.selected |
||||
|
if (!this._treeData.length) { |
||||
|
this.loadData() |
||||
|
} else { |
||||
|
//this.selected = data.selected |
||||
|
this._updateBindData() |
||||
|
} |
||||
|
}, |
||||
|
onDataChange() { |
||||
|
this.$emit('datachange'); |
||||
|
}, |
||||
|
onSelectedChange(node, isleaf) { |
||||
|
if (isleaf) { |
||||
|
this._dispatchEvent() |
||||
|
} |
||||
|
|
||||
|
if (node) { |
||||
|
this.$emit('nodeclick', node) |
||||
|
} |
||||
|
}, |
||||
|
_dispatchEvent() { |
||||
|
this.$emit('change', this.selected.slice(0)) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
$uni-primary: #007aff !default; |
||||
|
|
||||
|
.uni-data-pickerview { |
||||
|
flex: 1; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: column; |
||||
|
overflow: hidden; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.error-text { |
||||
|
color: #DD524D; |
||||
|
} |
||||
|
|
||||
|
.loading-cover { |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(255, 255, 255, .5); |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
z-index: 1001; |
||||
|
} |
||||
|
|
||||
|
.load-more { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
margin: auto; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.error-message { |
||||
|
background-color: #fff; |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
padding: 15px; |
||||
|
opacity: .9; |
||||
|
z-index: 102; |
||||
|
} |
||||
|
|
||||
|
/* #ifdef APP-NVUE */ |
||||
|
.selected-area { |
||||
|
width: 750rpx; |
||||
|
} |
||||
|
/* #endif */ |
||||
|
|
||||
|
.selected-list { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
flex-wrap: nowrap; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
padding: 0 5px; |
||||
|
border-bottom: 1px solid #f8f8f8; |
||||
|
} |
||||
|
|
||||
|
.selected-item { |
||||
|
margin-left: 10px; |
||||
|
margin-right: 10px; |
||||
|
padding: 12px 0; |
||||
|
text-align: center; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
white-space: nowrap; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.selected-item-text-overflow { |
||||
|
width: 168px; |
||||
|
/* fix nvue */ |
||||
|
overflow: hidden; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
width: 6em; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
-o-text-overflow: ellipsis; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.selected-item-active { |
||||
|
border-bottom: 2px solid $uni-primary; |
||||
|
} |
||||
|
|
||||
|
.selected-item-text { |
||||
|
color: $uni-primary; |
||||
|
} |
||||
|
|
||||
|
.tab-c { |
||||
|
position: relative; |
||||
|
flex: 1; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.list { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.item { |
||||
|
padding: 12px 15px; |
||||
|
/* border-bottom: 1px solid #f0f0f0; */ |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.is-disabled { |
||||
|
opacity: .5; |
||||
|
} |
||||
|
|
||||
|
.item-text { |
||||
|
/* flex: 1; */ |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.item-text-overflow { |
||||
|
width: 280px; |
||||
|
/* fix nvue */ |
||||
|
overflow: hidden; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
width: 20em; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
-o-text-overflow: ellipsis; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.check { |
||||
|
margin-right: 5px; |
||||
|
border: 2px solid $uni-primary; |
||||
|
border-left: 0; |
||||
|
border-top: 0; |
||||
|
height: 12px; |
||||
|
width: 6px; |
||||
|
transform-origin: center; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
transition: all 0.3s; |
||||
|
/* #endif */ |
||||
|
transform: rotate(45deg); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,91 @@ |
|||||
|
{ |
||||
|
"id": "uni-data-picker", |
||||
|
"displayName": "uni-data-picker 数据驱动的picker选择器", |
||||
|
"version": "2.0.0", |
||||
|
"description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"uniui", |
||||
|
"picker", |
||||
|
"级联", |
||||
|
"省市区", |
||||
|
"" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": [ |
||||
|
"uni-load-more", |
||||
|
"uni-icons", |
||||
|
"uni-scss" |
||||
|
], |
||||
|
"encrypt": [], |
||||
|
"platforms": { |
||||
|
"cloud": { |
||||
|
"tcb": "y", |
||||
|
"aliyun": "y" |
||||
|
}, |
||||
|
"client": { |
||||
|
"App": { |
||||
|
"app-vue": "y", |
||||
|
"app-nvue": "y", |
||||
|
"app-uvue": "y" |
||||
|
}, |
||||
|
"H5-mobile": { |
||||
|
"Safari": "y", |
||||
|
"Android Browser": "y", |
||||
|
"微信浏览器(Android)": "y", |
||||
|
"QQ浏览器(Android)": "y" |
||||
|
}, |
||||
|
"H5-pc": { |
||||
|
"Chrome": "y", |
||||
|
"IE": "y", |
||||
|
"Edge": "y", |
||||
|
"Firefox": "y", |
||||
|
"Safari": "y" |
||||
|
}, |
||||
|
"小程序": { |
||||
|
"微信": "y", |
||||
|
"阿里": "y", |
||||
|
"百度": "y", |
||||
|
"字节跳动": "y", |
||||
|
"QQ": "y", |
||||
|
"京东": "u" |
||||
|
}, |
||||
|
"快应用": { |
||||
|
"华为": "u", |
||||
|
"联盟": "u" |
||||
|
}, |
||||
|
"Vue": { |
||||
|
"vue2": "y", |
||||
|
"vue3": "y" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
## DataPicker 级联选择 |
||||
|
> **组件名:uni-data-picker** |
||||
|
> 代码块: `uDataPicker` |
||||
|
> 关联组件:`uni-data-pickerview`、`uni-load-more`。 |
||||
|
|
||||
|
|
||||
|
`<uni-data-picker>` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。 |
||||
|
|
||||
|
支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。 |
||||
|
|
||||
|
候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。 |
||||
|
|
||||
|
`<uni-data-picker>` 组件尤其适用于地址选择、分类选择等选择类。 |
||||
|
|
||||
|
`<uni-data-picker>` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。 |
||||
|
|
||||
|
`<uni-data-picker>` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。 |
||||
|
|
||||
|
在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。 |
||||
|
|
||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker) |
||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
||||
@ -0,0 +1,39 @@ |
|||||
|
## 1.0.8(2024-03-28) |
||||
|
- 修复 在vue2下:style动态绑定导致编译失败的bug |
||||
|
## 1.0.7(2024-01-20) |
||||
|
- 修复 长文本回显超过容器的bug,超过容器部分显示省略号 |
||||
|
## 1.0.6(2023-04-12) |
||||
|
- 修复 微信小程序点击时会改变背景颜色的 bug |
||||
|
## 1.0.5(2023-02-03) |
||||
|
- 修复 禁用时会显示清空按钮 |
||||
|
## 1.0.4(2023-02-02) |
||||
|
- 优化 查询条件短期内多次变更只查询最后一次变更后的结果 |
||||
|
- 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue |
||||
|
## 1.0.3(2023-01-16) |
||||
|
- 修复 不关联服务空间报错的问题 |
||||
|
## 1.0.2(2023-01-14) |
||||
|
- 新增 属性 `format` 可用于格式化显示选项内容 |
||||
|
## 1.0.1(2022-12-06) |
||||
|
- 修复 当where变化时,数据不会自动更新的问题 |
||||
|
## 0.1.9(2022-09-05) |
||||
|
- 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框 |
||||
|
## 0.1.8(2022-08-29) |
||||
|
- 修复 点击的位置不准确 |
||||
|
## 0.1.7(2022-08-12) |
||||
|
- 新增 支持 disabled 属性 |
||||
|
## 0.1.6(2022-07-06) |
||||
|
- 修复 pc端宽度异常的bug |
||||
|
## 0.1.5 |
||||
|
- 修复 pc端宽度异常的bug |
||||
|
## 0.1.4(2022-07-05) |
||||
|
- 优化 显示样式 |
||||
|
## 0.1.3(2022-06-02) |
||||
|
- 修复 localdata 赋值不生效的 bug |
||||
|
- 新增 支持 uni.scss 修改颜色 |
||||
|
- 新增 支持选项禁用(数据选项设置 disabled: true 即禁用) |
||||
|
## 0.1.2(2022-05-08) |
||||
|
- 修复 当 value 为 0 时选择不生效的 bug |
||||
|
## 0.1.1(2022-05-07) |
||||
|
- 新增 记住上次的选项(仅 collection 存在时有效) |
||||
|
## 0.1.0(2022-04-22) |
||||
|
- 初始化 |
||||
@ -0,0 +1,562 @@ |
|||||
|
<template> |
||||
|
<view class="uni-stat__select"> |
||||
|
<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span> |
||||
|
<view class="uni-stat-box" :class="{'uni-stat__actived': current}"> |
||||
|
<view class="uni-select" :class="{'uni-select--disabled':disabled}"> |
||||
|
<view class="uni-select__input-box" @click="toggleSelector"> |
||||
|
<view v-if="current" class="uni-select__input-text">{{textShow}}</view> |
||||
|
<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view> |
||||
|
<view v-if="current && clear && !disabled" @click.stop="clearVal"> |
||||
|
<uni-icons type="clear" color="#c0c4cc" size="24" /> |
||||
|
</view> |
||||
|
<view v-else> |
||||
|
<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" /> |
||||
|
<view class="uni-select__selector" :style="getOffsetByPlacement" v-if="showSelector"> |
||||
|
<view :class="placement=='bottom'?'uni-popper__arrow_bottom':'uni-popper__arrow_top'"></view> |
||||
|
<scroll-view scroll-y="true" class="uni-select__selector-scroll"> |
||||
|
<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0"> |
||||
|
<text>{{emptyTips}}</text> |
||||
|
</view> |
||||
|
<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index" |
||||
|
@click="change(item)"> |
||||
|
<text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
/** |
||||
|
* DataChecklist 数据选择器 |
||||
|
* @description 通过数据渲染的下拉框组件 |
||||
|
* @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select |
||||
|
* @property {String} value 默认值 |
||||
|
* @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}] |
||||
|
* @property {Boolean} clear 是否可以清空已选项 |
||||
|
* @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效 |
||||
|
* @property {String} label 左侧标题 |
||||
|
* @property {String} placeholder 输入框的提示文字 |
||||
|
* @property {Boolean} disabled 是否禁用 |
||||
|
* @property {String} placement 弹出位置 |
||||
|
* @value top 顶部弹出 |
||||
|
* @value bottom 底部弹出(default) |
||||
|
* @event {Function} change 选中发生变化触发 |
||||
|
*/ |
||||
|
|
||||
|
export default { |
||||
|
name: "uni-data-select", |
||||
|
mixins: [uniCloud.mixinDatacom || {}], |
||||
|
props: { |
||||
|
localdata: { |
||||
|
type: Array, |
||||
|
default () { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
value: { |
||||
|
type: [String, Number], |
||||
|
default: '' |
||||
|
}, |
||||
|
modelValue: { |
||||
|
type: [String, Number], |
||||
|
default: '' |
||||
|
}, |
||||
|
label: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
placeholder: { |
||||
|
type: String, |
||||
|
default: '请选择' |
||||
|
}, |
||||
|
emptyTips: { |
||||
|
type: String, |
||||
|
default: '无选项' |
||||
|
}, |
||||
|
clear: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
}, |
||||
|
defItem: { |
||||
|
type: Number, |
||||
|
default: 0 |
||||
|
}, |
||||
|
disabled: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
// 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}" |
||||
|
format: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
placement: { |
||||
|
type: String, |
||||
|
default: 'bottom' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
showSelector: false, |
||||
|
current: '', |
||||
|
mixinDatacomResData: [], |
||||
|
apps: [], |
||||
|
channels: [], |
||||
|
cacheKey: "uni-data-select-lastSelectedValue", |
||||
|
}; |
||||
|
}, |
||||
|
created() { |
||||
|
this.debounceGet = this.debounce(() => { |
||||
|
this.query(); |
||||
|
}, 300); |
||||
|
if (this.collection && !this.localdata.length) { |
||||
|
this.debounceGet(); |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
typePlaceholder() { |
||||
|
const text = { |
||||
|
'opendb-stat-app-versions': '版本', |
||||
|
'opendb-app-channels': '渠道', |
||||
|
'opendb-app-list': '应用' |
||||
|
} |
||||
|
const common = this.placeholder |
||||
|
const placeholder = text[this.collection] |
||||
|
return placeholder ? |
||||
|
common + placeholder : |
||||
|
common |
||||
|
}, |
||||
|
valueCom() { |
||||
|
// #ifdef VUE3 |
||||
|
return this.modelValue; |
||||
|
// #endif |
||||
|
// #ifndef VUE3 |
||||
|
return this.value; |
||||
|
// #endif |
||||
|
}, |
||||
|
textShow() { |
||||
|
// 长文本显示 |
||||
|
let text = this.current; |
||||
|
if (text.length > 10) { |
||||
|
return text.slice(0, 25) + '...'; |
||||
|
} |
||||
|
return text; |
||||
|
}, |
||||
|
getOffsetByPlacement() { |
||||
|
switch (this.placement) { |
||||
|
case 'top': |
||||
|
return "bottom:calc(100% + 12px);"; |
||||
|
case 'bottom': |
||||
|
return "top:calc(100% + 12px);"; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
localdata: { |
||||
|
immediate: true, |
||||
|
handler(val, old) { |
||||
|
if (Array.isArray(val) && old !== val) { |
||||
|
this.mixinDatacomResData = val |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
valueCom(val, old) { |
||||
|
this.initDefVal() |
||||
|
}, |
||||
|
mixinDatacomResData: { |
||||
|
immediate: true, |
||||
|
handler(val) { |
||||
|
if (val.length) { |
||||
|
this.initDefVal() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
}, |
||||
|
methods: { |
||||
|
debounce(fn, time = 100) { |
||||
|
let timer = null |
||||
|
return function(...args) { |
||||
|
if (timer) clearTimeout(timer) |
||||
|
timer = setTimeout(() => { |
||||
|
fn.apply(this, args) |
||||
|
}, time) |
||||
|
} |
||||
|
}, |
||||
|
// 执行数据库查询 |
||||
|
query() { |
||||
|
this.mixinDatacomEasyGet(); |
||||
|
}, |
||||
|
// 监听查询条件变更事件 |
||||
|
onMixinDatacomPropsChange() { |
||||
|
if (this.collection) { |
||||
|
this.debounceGet(); |
||||
|
} |
||||
|
}, |
||||
|
initDefVal() { |
||||
|
let defValue = '' |
||||
|
if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) { |
||||
|
defValue = this.valueCom |
||||
|
} else { |
||||
|
let strogeValue |
||||
|
if (this.collection) { |
||||
|
strogeValue = this.getCache() |
||||
|
} |
||||
|
if (strogeValue || strogeValue === 0) { |
||||
|
defValue = strogeValue |
||||
|
} else { |
||||
|
let defItem = '' |
||||
|
if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) { |
||||
|
defItem = this.mixinDatacomResData[this.defItem - 1].value |
||||
|
} |
||||
|
defValue = defItem |
||||
|
} |
||||
|
if (defValue || defValue === 0) { |
||||
|
this.emit(defValue) |
||||
|
} |
||||
|
} |
||||
|
const def = this.mixinDatacomResData.find(item => item.value === defValue) |
||||
|
this.current = def ? this.formatItemName(def) : '' |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* @param {[String, Number]} value |
||||
|
* 判断用户给的 value 是否同时为禁用状态 |
||||
|
*/ |
||||
|
isDisabled(value) { |
||||
|
let isDisabled = false; |
||||
|
|
||||
|
this.mixinDatacomResData.forEach(item => { |
||||
|
if (item.value === value) { |
||||
|
isDisabled = item.disable |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
return isDisabled; |
||||
|
}, |
||||
|
|
||||
|
clearVal() { |
||||
|
this.emit('') |
||||
|
if (this.collection) { |
||||
|
this.removeCache() |
||||
|
} |
||||
|
}, |
||||
|
change(item) { |
||||
|
if (!item.disable) { |
||||
|
this.showSelector = false |
||||
|
this.current = this.formatItemName(item) |
||||
|
this.emit(item.value) |
||||
|
} |
||||
|
}, |
||||
|
emit(val) { |
||||
|
this.$emit('input', val) |
||||
|
this.$emit('update:modelValue', val) |
||||
|
this.$emit('change', val) |
||||
|
if (this.collection) { |
||||
|
this.setCache(val); |
||||
|
} |
||||
|
}, |
||||
|
toggleSelector() { |
||||
|
if (this.disabled) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.showSelector = !this.showSelector |
||||
|
}, |
||||
|
formatItemName(item) { |
||||
|
let { |
||||
|
text, |
||||
|
value, |
||||
|
channel_code |
||||
|
} = item |
||||
|
channel_code = channel_code ? `(${channel_code})` : '' |
||||
|
|
||||
|
if (this.format) { |
||||
|
// 格式化输出 |
||||
|
let str = ""; |
||||
|
str = this.format; |
||||
|
for (let key in item) { |
||||
|
str = str.replace(new RegExp(`{${key}}`, "g"), item[key]); |
||||
|
} |
||||
|
return str; |
||||
|
} else { |
||||
|
return this.collection.indexOf('app-list') > 0 ? |
||||
|
`${text}(${value})` : |
||||
|
( |
||||
|
text ? |
||||
|
text : |
||||
|
`未命名${channel_code}` |
||||
|
) |
||||
|
} |
||||
|
}, |
||||
|
// 获取当前加载的数据 |
||||
|
getLoadData() { |
||||
|
return this.mixinDatacomResData; |
||||
|
}, |
||||
|
// 获取当前缓存key |
||||
|
getCurrentCacheKey() { |
||||
|
return this.collection; |
||||
|
}, |
||||
|
// 获取缓存 |
||||
|
getCache(name = this.getCurrentCacheKey()) { |
||||
|
let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
||||
|
return cacheData[name]; |
||||
|
}, |
||||
|
// 设置缓存 |
||||
|
setCache(value, name = this.getCurrentCacheKey()) { |
||||
|
let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
||||
|
cacheData[name] = value; |
||||
|
uni.setStorageSync(this.cacheKey, cacheData); |
||||
|
}, |
||||
|
// 删除缓存 |
||||
|
removeCache(name = this.getCurrentCacheKey()) { |
||||
|
let cacheData = uni.getStorageSync(this.cacheKey) || {}; |
||||
|
delete cacheData[name]; |
||||
|
uni.setStorageSync(this.cacheKey, cacheData); |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
$uni-base-color: #6a6a6a !default; |
||||
|
$uni-main-color: #333 !default; |
||||
|
$uni-secondary-color: #909399 !default; |
||||
|
$uni-border-3: #e5e5e5; |
||||
|
|
||||
|
/* #ifndef APP-NVUE */ |
||||
|
@media screen and (max-width: 500px) { |
||||
|
.hide-on-phone { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* #endif */ |
||||
|
.uni-stat__select { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
// padding: 15px; |
||||
|
/* #ifdef H5 */ |
||||
|
cursor: pointer; |
||||
|
/* #endif */ |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.uni-stat-box { |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.uni-stat__actived { |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
// outline: 1px solid #2979ff; |
||||
|
} |
||||
|
|
||||
|
.uni-label-text { |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
color: $uni-base-color; |
||||
|
margin: auto 0; |
||||
|
margin-right: 5px; |
||||
|
} |
||||
|
|
||||
|
.uni-select { |
||||
|
font-size: 14px; |
||||
|
border: 1px solid $uni-border-3; |
||||
|
box-sizing: border-box; |
||||
|
border-radius: 4px; |
||||
|
padding: 0 5px; |
||||
|
padding-left: 10px; |
||||
|
position: relative; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
user-select: none; |
||||
|
/* #endif */ |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
border-bottom: solid 1px $uni-border-3; |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
height: 35px; |
||||
|
|
||||
|
&--disabled { |
||||
|
background-color: #f5f7fa; |
||||
|
cursor: not-allowed; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.uni-select__label { |
||||
|
font-size: 16px; |
||||
|
// line-height: 22px; |
||||
|
height: 35px; |
||||
|
padding-right: 10px; |
||||
|
color: $uni-secondary-color; |
||||
|
} |
||||
|
|
||||
|
.uni-select__input-box { |
||||
|
height: 35px; |
||||
|
position: relative; |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
/* #endif */ |
||||
|
flex: 1; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.uni-select__input { |
||||
|
flex: 1; |
||||
|
font-size: 14px; |
||||
|
height: 22px; |
||||
|
line-height: 22px; |
||||
|
} |
||||
|
|
||||
|
.uni-select__input-plac { |
||||
|
font-size: 14px; |
||||
|
color: $uni-secondary-color; |
||||
|
} |
||||
|
|
||||
|
.uni-select__selector { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
box-sizing: border-box; |
||||
|
/* #endif */ |
||||
|
position: absolute; |
||||
|
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: 3; |
||||
|
padding: 4px 0; |
||||
|
} |
||||
|
|
||||
|
.uni-select__selector-scroll { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
max-height: 200px; |
||||
|
box-sizing: border-box; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
/* #ifdef H5 */ |
||||
|
@media (min-width: 768px) { |
||||
|
.uni-select__selector-scroll { |
||||
|
max-height: 600px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* #endif */ |
||||
|
|
||||
|
.uni-select__selector-empty, |
||||
|
.uni-select__selector-item { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
display: flex; |
||||
|
cursor: pointer; |
||||
|
/* #endif */ |
||||
|
line-height: 35px; |
||||
|
font-size: 14px; |
||||
|
text-align: center; |
||||
|
/* border-bottom: solid 1px $uni-border-3; */ |
||||
|
padding: 0px 10px; |
||||
|
} |
||||
|
|
||||
|
.uni-select__selector-item:hover { |
||||
|
background-color: #f9f9f9; |
||||
|
} |
||||
|
|
||||
|
.uni-select__selector-empty:last-child, |
||||
|
.uni-select__selector-item:last-child { |
||||
|
/* #ifndef APP-NVUE */ |
||||
|
border-bottom: none; |
||||
|
/* #endif */ |
||||
|
} |
||||
|
|
||||
|
.uni-select__selector__disabled { |
||||
|
opacity: 0.4; |
||||
|
cursor: default; |
||||
|
} |
||||
|
|
||||
|
/* picker 弹出层通用的指示小三角 */ |
||||
|
.uni-popper__arrow_bottom, |
||||
|
.uni-popper__arrow_bottom::after, |
||||
|
.uni-popper__arrow_top, |
||||
|
.uni-popper__arrow_top::after, |
||||
|
{ |
||||
|
position: absolute; |
||||
|
display: block; |
||||
|
width: 0; |
||||
|
height: 0; |
||||
|
border-color: transparent; |
||||
|
border-style: solid; |
||||
|
border-width: 6px; |
||||
|
} |
||||
|
|
||||
|
.uni-popper__arrow_bottom { |
||||
|
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_bottom::after { |
||||
|
content: " "; |
||||
|
top: 1px; |
||||
|
margin-left: -6px; |
||||
|
border-top-width: 0; |
||||
|
border-bottom-color: #fff; |
||||
|
} |
||||
|
|
||||
|
.uni-popper__arrow_top { |
||||
|
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)); |
||||
|
bottom: -6px; |
||||
|
left: 10%; |
||||
|
margin-right: 3px; |
||||
|
border-bottom-width: 0; |
||||
|
border-top-color: #EBEEF5; |
||||
|
} |
||||
|
|
||||
|
.uni-popper__arrow_top::after { |
||||
|
content: " "; |
||||
|
bottom: 1px; |
||||
|
margin-left: -6px; |
||||
|
border-bottom-width: 0; |
||||
|
border-top-color: #fff; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.uni-select__input-text { |
||||
|
// width: 280px; |
||||
|
width: 100%; |
||||
|
color: $uni-main-color; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
-o-text-overflow: ellipsis; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.uni-select__input-placeholder { |
||||
|
color: $uni-base-color; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.uni-select--mask { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
bottom: 0; |
||||
|
right: 0; |
||||
|
left: 0; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,86 @@ |
|||||
|
{ |
||||
|
"id": "uni-data-select", |
||||
|
"displayName": "uni-data-select 下拉框选择器", |
||||
|
"version": "1.0.8", |
||||
|
"description": "通过数据驱动的下拉框选择器", |
||||
|
"keywords": [ |
||||
|
"uni-ui", |
||||
|
"select", |
||||
|
"uni-data-select", |
||||
|
"下拉框", |
||||
|
"下拉选" |
||||
|
], |
||||
|
"repository": "https://github.com/dcloudio/uni-ui", |
||||
|
"engines": { |
||||
|
"HBuilderX": "^3.1.1" |
||||
|
}, |
||||
|
"directories": { |
||||
|
"example": "../../temps/example_temps" |
||||
|
}, |
||||
|
"dcloudext": { |
||||
|
"sale": { |
||||
|
"regular": { |
||||
|
"price": "0.00" |
||||
|
}, |
||||
|
"sourcecode": { |
||||
|
"price": "0.00" |
||||
|
} |
||||
|
}, |
||||
|
"contact": { |
||||
|
"qq": "" |
||||
|
}, |
||||
|
"declaration": { |
||||
|
"ads": "无", |
||||
|
"data": "无", |
||||
|
"permissions": "无" |
||||
|
}, |
||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", |
||||
|
"type": "component-vue" |
||||
|
}, |
||||
|
"uni_modules": { |
||||
|
"dependencies": ["uni-load-more"], |
||||
|
"encrypt": [], |
||||
|
"platforms": { |
||||
|
"cloud": { |
||||
|
"tcb": "y", |
||||
|
"aliyun": "y", |
||||
|
"alipay": "n" |
||||
|
}, |
||||
|
"client": { |
||||
|
"App": { |
||||
|
"app-vue": "u", |
||||
|
"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" |
||||
|
}, |
||||
|
"Vue": { |
||||
|
"vue2": "y", |
||||
|
"vue3": "y" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
## DataSelect 下拉框选择器 |
||||
|
> **组件名:uni-data-select** |
||||
|
> 代码块: `uDataSelect` |
||||
|
|
||||
|
当选项过多时,使用下拉菜单展示并选择内容 |
||||
|
|
||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select) |
||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
||||
@ -0,0 +1,10 @@ |
|||||
|
## 1.0.0(2021-11-19) |
||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat) |
||||
|
## 0.0.5(2021-07-08) |
||||
|
- 调整 默认时间不再是当前时间,而是显示'-'字符 |
||||
|
## 0.0.4(2021-05-12) |
||||
|
- 新增 组件示例地址 |
||||
|
## 0.0.3(2021-02-04) |
||||
|
- 调整为uni_modules目录规范 |
||||
|
- 修复 iOS 平台日期格式化出错的问题 |
||||