Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
飞
飞鹤小程序
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
FH
飞鹤小程序
Commits
970699b8
Commit
970699b8
authored
Jun 19, 2025
by
jtwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ai取名功能
parent
e9685618
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
5140 additions
and
224 deletions
+5140
-224
.DS_Store
.DS_Store
+0
-0
launch.json
.hbuilderx/launch.json
+16
-0
naming.js
api/naming.js
+9
-0
request.js
api/request.js
+5
-1
manifest.json
manifest.json
+13
-3
my.js
mock/my.js
+10
-0
pages.json
pages.json
+18
-0
naming.vue
pages/naming/naming.vue
+625
-0
namingResult.vue
pages/naming/namingResult.vue
+312
-0
changelog.md
uni_modules/uni-datetime-picker/changelog.md
+169
-0
calendar-item.vue
...e-picker/components/uni-datetime-picker/calendar-item.vue
+177
-0
calendar.vue
...tetime-picker/components/uni-datetime-picker/calendar.vue
+947
-0
en.json
...tetime-picker/components/uni-datetime-picker/i18n/en.json
+22
-0
index.js
...etime-picker/components/uni-datetime-picker/i18n/index.js
+8
-0
zh-Hans.json
...e-picker/components/uni-datetime-picker/i18n/zh-Hans.json
+22
-0
zh-Hant.json
...e-picker/components/uni-datetime-picker/i18n/zh-Hant.json
+22
-0
time-picker.vue
...ime-picker/components/uni-datetime-picker/time-picker.vue
+940
-0
uni-datetime-picker.vue
...er/components/uni-datetime-picker/uni-datetime-picker.vue
+1073
-0
util.js
...ni-datetime-picker/components/uni-datetime-picker/util.js
+421
-0
package.json
uni_modules/uni-datetime-picker/package.json
+90
-0
readme.md
uni_modules/uni-datetime-picker/readme.md
+21
-0
uni-icons.uvue
uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
+90
-90
uni-icons.vue
uni_modules/uni-icons/components/uni-icons/uni-icons.vue
+109
-109
uniicons_file.ts
uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
+18
-18
uniicons_file_vue.js
...dules/uni-icons/components/uni-icons/uniicons_file_vue.js
+3
-3
No files found.
.DS_Store
View file @
970699b8
No preview for this file type
.hbuilderx/launch.json
0 → 100644
View file @
970699b8
{
//
launch.json
配置了启动调试时相关设置,configurations下节点名称可为
app-plus/h
5
/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp
-360
/
//
launchtype项可配置值为local或remote
,
local代表前端连本地云函数,remote代表前端连云端云函数
"version"
:
"0.0"
,
"configurations"
:
[{
"default"
:
{
"launchtype"
:
"local"
},
"mp-weixin"
:
{
"launchtype"
:
"local"
},
"type"
:
"uniCloud"
}
]
}
api/naming.js
0 → 100644
View file @
970699b8
import
requestModule
from
'./request.js'
;
const
{
api
}
=
requestModule
;
/**
* ai取名
* @returns
*/
export
const
aiNaming
=
(
data
)
=>
api
.
post
(
'/c/ai/chat/query'
,
data
);
\ No newline at end of file
api/request.js
View file @
970699b8
...
...
@@ -16,13 +16,17 @@ const {
// request.js
// 通常可以吧 baseUrl 单独放在一个 js 文件了
// const baseUrl = "http://172.16.224.178:7777/pmall";
const
baseUrl
=
"https://momclub-uat.feihe.com/pmall"
;
// const baseUrl = "https://docs.dui88.com/mock/1956";
let
baseUrl
=
"https://momclub-uat.feihe.com/pmall"
;
const
request
=
(
options
=
{})
=>
{
// 在这里可以对请求头进行一些设置
// 例如:
// options.header = {
// "Content-Type": "application/x-www-form-urlencoded"
// }
// if(options.url == '/c/ai/chat/query'){
// baseUrl = "https://docs.dui88.com/mock/1956";
// }
return
new
Promise
((
resolve
,
reject
)
=>
{
uni
...
...
manifest.json
View file @
970699b8
...
...
@@ -43,7 +43,9 @@
/*
ios打包配置
*/
"ios"
:
{},
/*
SDK配置
*/
"sdkConfigs"
:
{}
"sdkConfigs"
:
{
"share"
:
{}
}
}
},
/*
快应用特有相关
*/
...
...
@@ -53,9 +55,17 @@
"appid"
:
"wx88ab296d52e9835d"
,
"setting"
:
{
"urlCheck"
:
false
,
"minified"
:
true
"minified"
:
true
,
"postcss"
:
true
,
"es6"
:
true
},
"usingComponents"
:
true
"usingComponents"
:
true
,
"permission"
:
{
"scope.userLocation"
:
{
"desc"
:
"请允许获取位置信息,用于提供附近服务"
}
},
"requiredBackgroundModes"
:
[
"share"
]
},
"mp-alipay"
:
{
"usingComponents"
:
true
...
...
mock/my.js
View file @
970699b8
...
...
@@ -40,6 +40,16 @@ export const myObj = {
"url"
:
"/pages/partner/redirect"
,
"extra"
:
{}
}
},
{
"bgUrl"
:
"my/naming.png"
,
"title"
:
"AI互娱"
,
"desc"
:
"AI互娱"
,
"link"
:
{
"type"
:
1
,
"url"
:
"/pages/naming/naming"
,
"extra"
:
{}
}
},
{
"bgUrl"
:
"my/babytest.png"
,
...
...
pages.json
View file @
970699b8
...
...
@@ -46,6 +46,24 @@
"style"
:
{
"navigationStyle"
:
"custom"
}
},
{
"path"
:
"pages/naming/naming"
,
"style"
:
{
"navigationBarTitleText"
:
"宝宝取名"
,
"enablePullDownRefresh"
:
false
,
"navigationStyle"
:
"custom"
}
},
{
"path"
:
"pages/naming/namingResult"
,
"style"
:
{
"navigationBarTitleText"
:
"AI-宝宝取名"
,
"enablePullDownRefresh"
:
false
,
"navigationStyle"
:
"custom"
}
}
],
"globalStyle"
:
{
...
...
pages/naming/naming.vue
0 → 100644
View file @
970699b8
<
template
>
<view>
<view
class=
"naming_bg"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/bg.jpg)`}">
<view
class=
"page-top"
>
<image
@
tap=
"backHandler"
class=
"btnback"
:src=
"$baseUrl+'aiNaming/back_btn.png'"
></image>
<view
class=
"page_title"
>
AI-宝宝取名
</view>
</view>
<view
class=
"top_con"
>
<!--出生状态-->
<view
class=
"cs_status"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
><span
:style=
"
{color: '#b27c1e'}">*
</span>
出生状态
</span>
<view
class=
"val_view"
>
<view
class=
"radio-group"
:style=
"
{display: 'flex'}">
<label
class=
"radio-item"
:class=
"
{ active: birthStatus === '已出生' }"
@click="birthStatus = '已出生'">
<radio
:style=
"
{opacity: 0}" :checked="birthStatus === '已出生'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"birthStatus === '已出生' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">已出生
</text>
</view>
</label>
<label
class=
"radio-item"
:class=
"
{ active: birthStatus === '未出生' }"
@click="birthStatus = '未出生'">
<radio
:style=
"
{opacity: 0}" :checked="birthStatus === '未出生'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"birthStatus === '未出生' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">未出生
</text>
</view>
</label>
</view>
</view>
</view>
<view
class=
"item_line"
></view>
</view>
<!--出生时间-->
<view
class=
"cs_time"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
><span
:style=
"
{color: '#b27c1e'}">*
</span>
出生时间
</span>
<view
class=
"val_view"
>
<view
class=
"time-picker-container"
@
click=
"openPicker"
>
<!-- 隐藏的时间选择器 -->
<view
class=
"datetime-picker"
:style=
"
{'margin-left': '0rpx', 'width':'480rpx'}">
<uni-datetime-picker
ref=
"pickerRef"
v-model=
"birthTime"
>
<!-- 时间显示部分 -->
<view
class=
"time-display"
>
<text
class=
"date_txt"
>
{{
formattedDate
}}
</text>
<view
class=
"time-separator"
>
<image
:src=
"`$
{$baseUrl}aiNaming/line.png`" mode="aspectFit"
class="time-icon" />时
</view>
<view
class=
"time-separator"
>
<image
:src=
"`$
{$baseUrl}aiNaming/line.png`" mode="aspectFit"
class="time-icon" />分
</view>
<!-- 右侧箭头图标 -->
<view
class=
"time-separator"
>
<image
:src=
"`$
{$baseUrl}aiNaming/jt.png`" mode="aspectFit"
class="arrow-icon" />
</view>
<text
class=
"hh"
>
{{
formattedTime
.
hour
}}
</text>
<text
class=
"ss"
>
{{
formattedTime
.
minute
}}
</text>
</view>
</uni-datetime-picker>
</view>
</view>
</view>
</view>
<view
class=
"item_line"
></view>
</view>
<!--姓氏-->
<view
class=
"surname_box"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
><span
:style=
"
{color: '#b27c1e'}">*
</span>
姓氏
</span>
<input
class=
"name_input"
placeholder=
"仅限2个汉字"
v-model=
"surname"
@
input=
"setNameInput"
@
blur=
"forceCorrection"
/>
</view>
<view
class=
"item_line"
></view>
</view>
<!--性别-->
<view
class=
"cs_sex"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
><span
:style=
"
{color: '#b27c1e'}">*
</span>
性别
</span>
<view
class=
"val_view"
>
<view
class=
"radio-group"
:style=
"
{display: 'flex'}">
<label
class=
"radio-item"
:class=
"
{ active: gender === '男' }" @click="gender = '男'">
<radio
:style=
"
{opacity: 0}" :checked="gender === '男'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"gender === '男' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">男
</text>
</view>
</label>
<label
class=
"radio-item"
:class=
"
{ active: gender === '女' }" @click="gender = '女'">
<radio
:style=
"
{opacity: 0}" :checked="gender === '女'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"gender === '女' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">女
</text>
</view>
</label>
</view>
</view>
</view>
<view
class=
"item_line"
></view>
</view>
<!--数字要求-->
<view
class=
"name_len"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
><span
:style=
"
{color: '#b27c1e'}">*
</span>
数字要求
</span>
<view
class=
"val_view"
>
<view
class=
"radio-group"
:style=
"
{display: 'flex'}">
<!--
<label
class=
"radio-item"
:class=
"
{ active: wordCount === '单字' }"
@click="wordCount = '单字'">
<radio
:style=
"
{opacity: 0}" :checked="wordCount === '单字'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"wordCount === '单字' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">单字
</text>
</view>
</label>
-->
<label
class=
"radio-item"
:class=
"
{ active: wordCount === '双字' }"
@click="wordCount = '双字'">
<radio
:style=
"
{opacity: 0}" :checked="wordCount === '双字'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"wordCount === '双字' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">双字
</text>
</view>
</label>
<label
class=
"radio-item"
:class=
"
{ active: wordCount === '三字' }"
@click="wordCount = '三字'">
<radio
:style=
"
{opacity: 0}" :checked="wordCount === '三字'" color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"wordCount === '三字' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">三字
</text>
</view>
</label>
</view>
</view>
</view>
<view
class=
"item_line"
></view>
</view>
<!--必有字-->
<view
class=
"shall_be_word"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
>
必有字
</span>
<input
class=
"shall_be_input"
placeholder=
"多、浩、雨"
v-model=
"requiredChars"
@
blur=
"e => enforceSeparator(e, 1)"
/>
</view>
<view
class=
"item_line"
></view>
</view>
<!--避讳字-->
<view
class=
"taboo_word"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
>
避讳字
</span>
<input
class=
"taboo_input"
placeholder=
"然、萌"
v-model=
"avoidChars"
@
blur=
"e => enforceSeparator(e, 2)"
/>
</view>
<view
class=
"item_line"
></view>
</view>
<!--期望风格-->
<view
class=
"hope_style"
>
<view
class=
"item_top"
>
<span
class=
"title_txt"
>
期望风格
</span>
<view
class=
"val_view"
>
<view
class=
"radio-group"
>
<view
:style=
"
{display: 'flex'}">
<label
class=
"radio-item"
:class=
"
{ active: expectedStyle === '古风诗词' }"
@click="expectedStyle = '古风诗词'">
<radio
:style=
"
{opacity: 0}" :checked="expectedStyle === '古风诗词'"
color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"expectedStyle === '古风诗词' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">古风诗词
</text>
</view>
</label>
<label
class=
"radio-item"
:class=
"
{ active: expectedStyle === '蛇年生肖' }"
@click="expectedStyle = '蛇年生肖'">
<radio
:style=
"
{opacity: 0}" :checked="expectedStyle === '蛇年生肖'"
color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"expectedStyle === '蛇年生肖' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">蛇年生肖
</text>
</view>
</label>
</view>
<view
:style=
"
{display: 'flex'}">
<label
class=
"radio-item"
:class=
"
{ active: expectedStyle === '龙年生肖' }"
@click="expectedStyle = '龙年生肖'">
<radio
:style=
"
{opacity: 0}" :checked="expectedStyle === '龙年生肖'"
color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"expectedStyle === '龙年生肖' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">龙年生肖
</text>
</view>
</label>
<label
class=
"radio-item"
:class=
"
{ active: expectedStyle === '马年生肖' }"
@click="expectedStyle = '马年生肖'">
<radio
:style=
"
{opacity: 0}" :checked="expectedStyle === '马年生肖'"
color="#4a90e2" />
<view
class=
"custom-radio"
:style=
"
{display: 'flex','margin-top': '-41rpx'}">
<image
class=
"radio-icon"
:src=
"expectedStyle === '马年生肖' ? `$
{$baseUrl}aiNaming/sel.png` : `${$baseUrl}aiNaming/no_sel.png`"
mode="aspectFit" />
<text
class=
"radio-label"
:style=
"
{'margin': '-6rpx 0 0 10rpx'}">马年生肖
</text>
</view>
</label>
</view>
</view>
</view>
</view>
<view
class=
"item_line"
></view>
</view>
</view>
<view
class=
"naming_btn"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/btn.png)`}" @click="onNaming">
</view>
</view>
</view>
</
template
>
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
,
computed
,
nextTick
}
from
'vue'
import
{
onLoad
,
onShow
}
from
'@dcloudio/uni-app'
import
{
jump
,
JumpType
,
throttleTap
}
from
'@/utils/index.js'
;
import
{
aiNaming
}
from
'../../api/naming.js'
;
// 出生状态
const
birthStatus
=
ref
(
''
);
//姓氏
const
surname
=
ref
(
''
);
// 性别选择
const
gender
=
ref
(
''
);
// 字数要求
const
wordCount
=
ref
(
''
);
//必有字
const
requiredChars
=
ref
(
''
);
//避讳字
const
avoidChars
=
ref
(
''
);
//期望风格
const
expectedStyle
=
ref
(
''
);
const
back_btn
=
ref
(
''
);
onLoad
((
options
)
=>
{
back_btn
.
value
=
options
.
back_btn
console
.
log
(
'接收到的参数:'
,
back_btn
.
value
)
});
onShow
(()
=>
{
console
.
log
(
'onShow'
)
});
// 页面加载
onMounted
(()
=>
{
});
// 转换为目标格式
const
getDefaultTime
=
()
=>
{
const
date
=
new
Date
(
Date
.
now
())
const
year
=
date
.
getFullYear
()
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
'0'
)
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
'0'
)
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
return
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
`
}
//出生时间
const
birthTime
=
ref
(
getDefaultTime
())
// 默认时间
const
pickerRef
=
ref
(
null
)
// 格式化日期显示
const
formattedDate
=
computed
(()
=>
{
return
birthTime
.
value
.
split
(
' '
)[
0
]
})
// 格式化时间显示
const
formattedTime
=
computed
(()
=>
{
const
timePart
=
birthTime
.
value
.
split
(
' '
)[
1
]
||
'00:00'
const
[
hour
,
minute
]
=
timePart
.
split
(
':'
)
return
{
hour
,
minute
}
})
// 打开时间选择器
const
openPicker
=
()
=>
{
uni
.
nextTick
(()
=>
{
if
(
pickerRef
.
value
?.
show
)
{
pickerRef
.
value
.
show
()
}
else
{
console
.
error
(
'时间选择器初始化失败'
)
}
})
}
// 计算中文字符数
// const chineseCount = computed(() => {
// // 方法1:正则匹配中文
// const chineseChars = surname.value.match(/[\u4e00-\u9fa5]/g) || []
// return chineseChars.length
// })
// const setNameInput = (e) => {
// const text = e.detail.value
// // 如果超过2个中文,截取前2个
// if (chineseCount.value > 2) {
// // 找到第二个中文字符的位置
// const chineseMatches = [...text.matchAll(/[\u4e00-\u9fa5]/g)]
// if (chineseMatches.length >= 2) {
// const secondCharEndPos = chineseMatches[chineseMatches.length - 1].index + 1
// surname.value = text.slice(0, 2);
// }
// }
// }
const
realText
=
ref
(
''
)
// 实际存储的中文
// 核心输入处理
const
setNameInput
=
(
e
)
=>
{
const
inputVal
=
e
.
detail
.
value
// 1. 移除非中文字符(包括标点、英文、数字等)
const
chineseOnly
=
inputVal
.
replace
(
/
[^\u
4e00-
\u
9fa5
]
/g
,
''
).
slice
(
0
,
2
);
// 3. 更新实际值
realText
.
value
=
chineseOnly
// 4. 延迟同步显示(避免打断输入法组合)
if
(
shouldSyncDisplay
(
inputVal
,
chineseOnly
))
{
surname
.
value
=
chineseOnly
}
}
// 失焦时强制修正
const
forceCorrection
=
()
=>
{
surname
.
value
=
realText
.
value
}
// 判断是否需要立即同步显示
const
shouldSyncDisplay
=
(
input
,
filtered
)
=>
{
// 如果内容变短或完全匹配,立即同步
return
input
.
length
<=
filtered
.
length
||
input
===
filtered
}
//设置必有字和避讳字,用、隔开每一个字
const
enforceSeparator
=
(
e
,
idx
)
=>
{
let
text
=
e
.
detail
.
value
// 1. 移除所有现有分隔符(避免干扰)
text
=
text
.
replace
(
/、/g
,
''
)
// 2. 在每个字符后插入分隔符(最后一个字符除外)
const
formatted
=
[...
text
].
join
(
'、'
)
if
(
idx
==
1
)
{
requiredChars
.
value
=
formatted
.
slice
(
0
,
5
)
}
else
if
(
idx
==
2
)
{
avoidChars
.
value
=
formatted
.
slice
(
0
,
5
)
}
}
//ai取名
const
onNaming
=
(
data
)
=>
{
let
param
=
{
birthStatus
:
birthStatus
.
value
,
birthTime
:
birthTime
.
value
,
surname
:
surname
.
value
,
gender
:
gender
.
value
,
wordCount
:
wordCount
.
value
,
requiredChars
:
requiredChars
.
value
,
avoidChars
:
avoidChars
.
value
,
expectedStyle
:
expectedStyle
.
value
}
// console.log('开始取名::', param)
if
(
!
param
.
birthStatus
||
!
param
.
birthTime
||
!
param
.
surname
||
!
param
.
gender
||
!
param
.
wordCount
)
{
uni
.
showToast
({
title
:
'还有信息没填写哦'
,
icon
:
'none'
})
return
;
}
//验证通过,调接口
onAiNaming
(
param
);
};
//生成or重新生成名字
const
onAiNaming
=
throttleTap
(
async
(
param
)
=>
{
// 显示加载中
uni
.
showLoading
({
title
:
'生成中...'
,
mask
:
true
// 是否显示透明蒙层(防止触摸穿透)
})
let
d
=
await
aiNaming
(
param
);
if
(
d
)
{
let
nameList
=
d
?.
data
;
console
.
log
(
'取名回调:'
,
nameList
)
// 隐藏
uni
.
hideLoading
()
jump
({
type
:
JumpType
.
INNER
,
url
:
`/pages/naming/namingResult?param=
${
encodeURIComponent
(
JSON
.
stringify
(
param
))}
&nameList=
${
encodeURIComponent
(
JSON
.
stringify
(
nameList
))}
`
})
}
},
5000
)
// 首页组件逻辑
const
backHandler
=
()
=>
{
if
(
!
back_btn
){
uni
.
navigateBack
();
}
else
{
jump
({
type
:
JumpType
.
INNER
,
url
:
`/pages/index/index`
})
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.naming_bg {
// position: absolute;
width: 100%;
height: 1624rpx;
background-size: 100% 100%;
}
.top_con {
position: absolute;
width: 686rpx;
height: 1044rpx;
top: 243rpx;
left: 32rpx;
background: #fff;
border-radius: 28rpx;
}
.cs_status,
.cs_time,
.surname_box,
.cs_sex,
.name_len,
.shall_be_word,
.taboo_word,
.hope_style {
margin-top: 40rpx;
margin-left: 30rpx;
font-size: 28rpx;
}
.item_top {
display: flex;
}
.title_txt {
width: 150rpx;
}
.val_view {
display: flex;
flex-direction: column;
align-items: flex-end;
color: #6f6d67;
font-size: 28rpx;
font-weight: 400;
width: 480rpx;
text-align: right;
}
.example-body {
background-color: #fff;
padding: 10px;
}
.radio-item {
margin-left: 40rpx;
}
.radio-icon {
width: 26rpx;
height: 26rpx !important;
}
.name_input,
.shall_be_input,
.taboo_input {
width: 480rpx;
text-align: right;
}
.item_line {
width: 620rpx;
height: 2rpx;
margin-top: 30rpx;
background: #999;
opacity: 0.15;
}
.time-picker-container {
display: flex;
width: 470rpx;
margin-top: 0rpx;
color: #999;
}
.time-display {
flex: 1;
display: flex;
align-items: center;
// font-size: 20rpx;
color: #999;
}
.date_txt {
width: 200rpx;
}
.time-separator {
display: flex;
align-items: center;
margin-left: 10rpx;
color: #666;
}
.time-icon {
width: 76rpx;
height: 15rpx;
margin-right: 8rpx;
margin-top: 30rpx;
}
.hh {
margin-left: -232rpx;
}
.ss {
margin-left: 88rpx;
}
.arrow-icon {
width: 11rpx;
height: 19rpx;
margin-left: 5rpx;
}
.naming_btn {
position: absolute;
width: 686rpx;
height: 94rpx;
top: 1430rpx;
left: 32rpx;
background-size: 100% 100%;
}
.page-top {
width: 100%;
}
.btnback {
width: 20rpx;
height: 32rpx;
margin-top: 110rpx;
margin-left: 48rpx;
}
.page_title {
width: 100%;
font-size: 34rpx;
font-weight: 500;
text-align: center;
color: #1d1e25;
margin-top: -46rpx;
margin-left: 0rpx;
}
</
style
>
\ No newline at end of file
pages/naming/namingResult.vue
0 → 100644
View file @
970699b8
<
template
>
<view
class=
"bg"
>
<view
class=
"naming_result_bg"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/bg.jpg)`}">
<view
class=
"page-top"
>
<image
@
tap=
"backHandler"
class=
"btnback"
:src=
"$baseUrl+'aiNaming/back_btn.png'"
></image>
<view
class=
"page_title"
>
AI-宝宝取名
</view>
</view>
<view
class=
"box"
>
<view
class=
"name_box"
v-for=
"(item, index) in nameList"
:key=
"index"
>
<view
class=
"name_con"
>
<view
class=
"name_py"
>
{{
item
.
pinyin
}}
</view>
<view
class=
"name_txt"
>
{{
item
.
name
}}
</view>
</view>
<view
class=
"jt_box"
@
click=
"onJtClick(index)"
>
<image
class=
"jt"
:src=
"jt_type[index] === 0 ? `$
{$baseUrl}aiNaming/jx_icon_1.png` : `${$baseUrl}aiNaming/jx_icon_2.png`"
mode="aspectFit" />
<view
class=
"jt_txt"
>
解析
</view>
</view>
<view
class=
"name_desc"
v-if=
"jt_type[index] == 1"
>
<view
class=
"meaning"
>
{{
item
.
meaning
}}
</view>
<view
class=
"line"
></view>
<view
class=
"words_0"
>
{{
item
.
words
?.[
0
]
}}
</view>
<view
class=
"words_1"
>
{{
item
.
words
?.[
1
]
}}
</view>
<view
class=
"btn_box"
>
<button
open-type=
"share"
class=
"share_btn"
>
<image
:src=
"`$
{$baseUrl}aiNaming/share_btn.png`" mode="aspectFit" class="share_icon" />
</button>
<!--
<view
class=
"share_btn"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/share_btn.png)`}"
@click="shareAppMessage">
</view>
-->
<view
class=
"regenerate_btn1"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/cxsc_btn.png)`}" @click="onAiNaming">
</view>
</view>
</view>
</view>
<view
class=
"regenerate_btn"
:style=
"
{backgroundImage: `url(${$baseUrl}aiNaming/cxsc_btn.png)`}"
@click="onAiNaming">
</view>
</view>
</view>
</view>
</
template
>
<
script
setup
>
import
{
ref
,
reactive
,
computed
,
onMounted
,
getCurrentInstance
}
from
'vue'
;
import
{
jump
,
JumpType
,
throttleTap
}
from
"@/utils/index.js"
;
import
{
aiNaming
}
from
'../../api/naming.js'
;
import
{
onLoad
}
from
'@dcloudio/uni-app'
const
{
proxy
}
=
getCurrentInstance
();
const
$baseUrl
=
proxy
.
$baseUrl
;
const
jt_type
=
ref
([
0
,
0
,
0
]);
const
param
=
ref
();
const
nameList
=
ref
(
null
);
onLoad
((
options
)
=>
{
param
.
value
=
JSON
.
parse
(
decodeURIComponent
(
options
.
param
))
nameList
.
value
=
JSON
.
parse
(
decodeURIComponent
(
options
.
nameList
))
console
.
log
(
'接收到的参数:'
,
param
.
value
)
});
onMounted
(()
=>
{
uni
.
hideLoading
();
});
//生成or重新生成名字
const
onAiNaming
=
throttleTap
(
async
()
=>
{
uni
.
showLoading
({
title
:
'生成中...'
,
mask
:
true
// 是否显示透明蒙层(防止触摸穿透)
})
let
d
=
await
aiNaming
(
param
.
value
);
uni
.
hideLoading
();
if
(
d
)
{
nameList
.
value
=
d
?.
data
;
console
.
log
(
'重新生成:'
,
nameList
.
value
)
jt_type
.
value
=
[
0
,
0
,
0
]
}
},
1000
)
//点击箭头
const
onJtClick
=
(
index
)
=>
{
if
(
jt_type
.
value
[
index
])
{
jt_type
.
value
[
index
]
=
0
;
}
else
{
jt_type
.
value
[
index
]
=
1
;
}
}
// 首页组件逻辑
const
backHandler
=
()
=>
{
uni
.
navigateBack
();
}
</
script
>
<
script
>
export
default
{
setup
()
{
const
{
proxy
}
=
getCurrentInstance
()
const
$baseUrl
=
proxy
.
$baseUrl
// 返回供模板使用的数据/方法
return
{
$baseUrl
// 可以在 export default 的其他选项中通过 this.$baseUrl 访问
}
},
onShareAppMessage
()
{
// 通过 this 访问 setup() 返回的变量
return
{
title
:
'好名字是给宝宝独一无二的礼物'
,
path
:
`/pages/naming/naming?back_btn='hide'`
,
imageUrl
:
this
.
$baseUrl
+
'aiNaming/single.png'
}
}
}
</
script
>
<
style
lang=
"scss"
>
.bg
{
width
:
100vw
;
min-height
:
100vh
;
height
:
auto
;
background-color
:
#f6f8fa
;
}
.naming_result_bg
{
width
:
100vw
;
min-height
:
100vh
;
background-size
:
100%
100%
;
}
.box
{
height
:
auto
;
margin-top
:
80rpx
;
padding-left
:
32rpx
;
padding-right
:
32rpx
;
padding-bottom
:
100rpx
;
.name_box
{
padding
:
100rpx
32rpx
100rpx
32rpx
;
height
:
auto
;
margin-bottom
:
50rpx
;
background
:
#fff
;
border-radius
:
28rpx
;
.name_con
{
width
:
380rpx
;
margin-left
:
0rpx
;
font-size
:
30rpx
;
letter-spacing
:
10rpx
;
.name_py
{
width
:
100%
;
text-align
:
center
;
}
.name_txt
{
margin-top
:
5rpx
;
width
:
100%
;
font-size
:
54rpx
;
text-align
:
center
;
}
}
.jt_box
{
width
:
94rpx
;
margin-left
:
480rpx
;
margin-top
:
-80rpx
;
color
:
#6f6d67
;
font-size
:
28rpx
;
text-align
:
center
;
.jt
{
width
:
34rpx
;
height
:
34rpx
;
}
.jt_txt
{
width
:
100%
;
}
}
.name_desc
{
width
:
100%
;
margin-top
:
100rpx
;
color
:
#1d1e25
;
.meaning
{
font-size
:
26rpx
;
text-align
:
left
;
letter-spacing
:
1rpx
;
line-height
:
1
.5
;
opacity
:
0
.8
;
}
.line
{
width
:
620rpx
;
height
:
2rpx
;
background-color
:
#999
;
opacity
:
0
.1
;
margin-top
:
30rpx
;
margin-bottom
:
50rpx
;
}
.words_0
{
font-size
:
28rpx
;
text-align
:
left
;
opacity
:
0
.9
;
}
.words_1
{
font-size
:
28rpx
;
text-align
:
left
;
margin-top
:
30rpx
;
opacity
:
0
.9
;
}
.btn_box
{
width
:
100%
;
display
:
flex
;
margin-top
:
120rpx
;
margin-bottom
:
-60rpx
;
.share_btn
{
// width: 142rpx;
// height: 55rpx;
// background-size: 100% 100%;
// margin-left: 260rpx;
padding
:
0
;
margin
:
0
;
border
:
none
;
background
:
none
;
line-height
:
1
;
}
/* 去除微信按钮默认边框 */
.
share_btn
:
:
after
{
border
:
none
!
important
;
}
/* 图片样式 */
.share_icon
{
width
:
142rpx
;
height
:
55rpx
;
display
:
block
;
margin-left
:
230rpx
;
}
.regenerate_btn1
{
width
:
199rpx
;
height
:
55rpx
;
background-size
:
100%
100%
;
margin-left
:
40rpx
;
}
}
}
}
.regenerate_btn
{
width
:
199rpx
;
height
:
55rpx
;
background-size
:
100%
100%
;
margin-left
:
490rpx
;
}
}
.page-top
{
width
:
100%
;
}
.btnback
{
width
:
20rpx
;
height
:
32rpx
;
margin-top
:
110rpx
;
margin-left
:
48rpx
;
}
.page_title
{
width
:
100%
;
font-size
:
34rpx
;
font-weight
:
500
;
text-align
:
center
;
color
:
#1d1e25
;
margin-top
:
-46rpx
;
margin-left
:
0rpx
;
}
</
style
>
\ No newline at end of file
uni_modules/uni-datetime-picker/changelog.md
0 → 100644
View file @
970699b8
## 2.2.40(2025-04-14)
-
修复 绑定字符串值的时,日历面板选中状态未重置到默认值的问题
## 2.2.39(2025-04-14)
-
修复 在 iOS 微信小程序上type='daterange'时,传入'YYYY-MM-DD'格式不生效的问题
## 2.2.38(2024-10-15)
-
修复 微信小程序中的getSystemInfo警告
## 2.2.35(2024-09-21)
-
修复 没有选中日期时点击确定直接报错的Bug
[
详情
](
https://ask.dcloud.net.cn/question/198168
)
## 2.2.34(2024-04-24)
-
新增 日期点击事件,在点击日期时会触发该事件。
## 2.2.33(2024-04-15)
-
修复 抖音小程序事件传递失效bug
## 2.2.32(2024-02-20)
-
修复 日历的close事件触发异常的bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/844
)
## 2.2.31(2024-02-20)
-
修复 h5平台 右边日历的月份默认+1的bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/841
)
## 2.2.30(2024-01-31)
-
修复 隐藏“秒”时,在IOS15及以下版本时出现 结束时间在开始时间之前 的bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/788
)
## 2.2.29(2024-01-20)
-
新增 show事件,弹窗弹出时触发该事件
[
详情
](
https://github.com/dcloudio/uni-app/issues/4694
)
## 2.2.28(2024-01-18)
-
去除 noChange事件,当进行日期范围选择时,若只选了一天,则开始结束日期都为同一天
[
详情
](
https://github.com/dcloudio/uni-ui/issues/815
)
## 2.2.27(2024-01-10)
-
优化 增加noChange事件,当进行日期范围选择时,若有空值,则触发该事件
[
详情
](
https://github.com/dcloudio/uni-ui/issues/815
)
## 2.2.26(2024-01-08)
-
修复 字节小程序时间选择范围器失效问题
[
详情
](
https://github.com/dcloudio/uni-ui/issues/834
)
## 2.2.25(2023-10-18)
-
修复 PC端初次修改时间,开始时间未更新的Bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/737
)
## 2.2.24(2023-06-02)
-
修复 部分情况修改时间,开始、结束时间显示异常的Bug
[
详情
](
https://ask.dcloud.net.cn/question/171146
)
-
优化 当前月可以选择上月、下月的日期的Bug
## 2.2.23(2023-05-02)
-
修复 部分情况修改时间,开始时间未更新的Bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/737
)
-
修复 部分平台及设备第一次点击无法显示弹框的Bug
-
修复 ios 日期格式未补零显示及使用异常的Bug
[
详情
](
https://ask.dcloud.net.cn/question/162979
)
## 2.2.22(2023-03-30)
-
修复 日历 picker 修改年月后,自动选中当月1日的Bug
[
详情
](
https://ask.dcloud.net.cn/question/165937
)
-
修复 小程序端 低版本 ios NaN的Bug
[
详情
](
https://ask.dcloud.net.cn/question/162979
)
## 2.2.21(2023-02-20)
-
修复 firefox 浏览器显示区域点击无法拉起日历弹框的Bug
[
详情
](
https://ask.dcloud.net.cn/question/163362
)
## 2.2.20(2023-02-17)
-
优化 值为空依然选中当天问题
-
优化 提供 default-value 属性支持配置选择器打开时默认显示的时间
-
优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间
-
优化 字节小程序日期时间范围选择,底部日期换行的Bug
## 2.2.19(2023-02-09)
-
修复 2.2.18 引起范围选择配置 end 选择无效的Bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/686
)
## 2.2.18(2023-02-08)
-
修复 移动端范围选择change事件触发异常的Bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/684
)
-
优化 PC端输入日期格式错误时返回当前日期时间
-
优化 PC端输入日期时间超出 start、end 限制的Bug
-
优化 移动端日期时间范围用法时间展示不完整问题
## 2.2.17(2023-02-04)
-
修复 小程序端绑定 Date 类型报错的Bug
[
详情
](
https://github.com/dcloudio/uni-ui/issues/679
)
-
修复 vue3 time-picker 无法显示绑定时分秒的Bug
## 2.2.16(2023-02-02)
-
修复 字节小程序报错的Bug
## 2.2.15(2023-02-02)
-
修复 某些情况切换月份错误的Bug
## 2.2.14(2023-01-30)
-
修复 某些情况切换月份错误的Bug
[
详情
](
https://ask.dcloud.net.cn/question/162033
)
## 2.2.13(2023-01-10)
-
修复 多次加载组件造成内存占用的Bug
## 2.2.12(2022-12-01)
-
修复 vue3 下 i18n 国际化初始值不正确的Bug
## 2.2.11(2022-09-19)
-
修复 支付宝小程序样式错乱的Bug
[
详情
](
https://github.com/dcloudio/uni-app/issues/3861
)
## 2.2.10(2022-09-19)
-
修复 反向选择日期范围,日期显示异常的Bug
[
详情
](
https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false
)
## 2.2.9(2022-09-16)
-
可以使用 uni-scss 控制主题色
## 2.2.8(2022-09-08)
-
修复 close事件无效的Bug
## 2.2.7(2022-09-05)
-
修复 移动端 maskClick 无效的Bug
[
详情
](
https://ask.dcloud.net.cn/question/140824
)
## 2.2.6(2022-06-30)
-
优化 组件样式,调整了组件图标大小、高度、颜色等,与uni-ui风格保持一致
## 2.2.5(2022-06-24)
-
修复 日历顶部年月及底部确认未国际化的Bug
## 2.2.4(2022-03-31)
-
修复 Vue3 下动态赋值,单选类型未响应的Bug
## 2.2.3(2022-03-28)
-
修复 Vue3 下动态赋值未响应的Bug
## 2.2.2(2021-12-10)
-
修复 clear-icon 属性在小程序平台不生效的Bug
## 2.2.1(2021-12-10)
-
修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的Bug
## 2.2.0(2021-11-19)
-
优化 组件UI,并提供设计资源
[
详情
](
https://uniapp.dcloud.io/component/uniui/resource
)
-
文档迁移
[
https://uniapp.dcloud.io/component/uniui/uni-datetime-picker
](
https://uniapp.dcloud.io/component/uniui/uni-datetime-picker
)
## 2.1.5(2021-11-09)
-
新增 提供组件设计资源,组件样式调整
## 2.1.4(2021-09-10)
-
修复 hide-second 在移动端的Bug
-
修复 单选赋默认值时,赋值日期未高亮的Bug
-
修复 赋默认值时,移动端未正确显示时间的Bug
## 2.1.3(2021-09-09)
-
新增 hide-second 属性,支持只使用时分,隐藏秒
## 2.1.2(2021-09-03)
-
优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
-
优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
-
优化 调整字号大小,美化日历界面
-
修复 因国际化导致的 placeholder 失效的Bug
## 2.1.1(2021-08-24)
-
新增 支持国际化
-
优化 范围选择器在 pc 端过宽的问题
## 2.1.0(2021-08-09)
-
新增 适配 vue3
## 2.0.19(2021-08-09)
-
新增 支持作为 uni-forms 子组件相关功能
-
修复 在 uni-forms 中使用时,选择时间报 NAN 错误的Bug
## 2.0.18(2021-08-05)
-
修复 type 属性动态赋值无效的Bug
-
修复 ‘确认’按钮被 tabbar 遮盖 bug
-
修复 组件未赋值时范围选左、右日历相同的Bug
## 2.0.17(2021-08-04)
-
修复 范围选未正确显示当前值的Bug
-
修复 h5 平台(移动端)报错 'cale' of undefined 的Bug
## 2.0.16(2021-07-21)
-
新增 return-type 属性支持返回 date 日期对象
## 2.0.15(2021-07-14)
-
修复 单选日期类型,初始赋值后不在当前日历的Bug
-
新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
-
优化 移动端移除显示框的清空按钮,无实际用途
## 2.0.14(2021-07-14)
-
修复 组件赋值为空,界面未更新的Bug
-
修复 start 和 end 不能动态赋值的Bug
-
修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的Bug
## 2.0.13(2021-07-08)
-
修复 范围选择不能动态赋值的Bug
## 2.0.12(2021-07-08)
-
修复 范围选择的初始时间在一个月内时,造成无法选择的bug
## 2.0.11(2021-07-08)
-
优化 弹出层在超出视窗边缘定位不准确的问题
## 2.0.10(2021-07-08)
-
修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的Bug
-
优化 弹出层在超出视窗边缘被遮盖的问题
## 2.0.9(2021-07-07)
-
新增 maskClick 事件
-
修复 特殊情况日历 rpx 布局错误的Bug,rpx -> px
-
修复 范围选择时清空返回值不合理的bug,
[
'', ''
]
->
[]
## 2.0.8(2021-07-07)
-
新增 日期时间显示框支持插槽
## 2.0.7(2021-07-01)
-
优化 添加 uni-icons 依赖
## 2.0.6(2021-05-22)
-
修复 图标在小程序上不显示的Bug
-
优化 重命名引用组件,避免潜在组件命名冲突
## 2.0.5(2021-05-20)
-
优化 代码目录扁平化
## 2.0.4(2021-05-12)
-
新增 组件示例地址
## 2.0.3(2021-05-10)
-
修复 ios 下不识别 '-' 日期格式的Bug
-
优化 pc 下弹出层添加边框和阴影
## 2.0.2(2021-05-08)
-
修复 在 admin 中获取弹出层定位错误的bug
## 2.0.1(2021-05-08)
-
修复 type 属性向下兼容,默认值从 date 变更为 datetime
## 2.0.0(2021-04-30)
-
支持日历形式的日期+时间的范围选择
> 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)
## 1.0.6(2021-03-18)
-
新增 hide-second 属性,时间支持仅选择时、分
-
修复 选择跟显示的日期不一样的Bug
-
修复 chang事件触发2次的Bug
-
修复 分、秒 end 范围错误的Bug
-
优化 更好的 nvue 适配
uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
0 → 100644
View file @
970699b8
<
template
>
<view
class=
"uni-calendar-item__weeks-box"
:class=
"
{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked-x':weeks.afterMultiple,
}" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
<view
class=
"uni-calendar-item__weeks-box-item"
:class=
"
{
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate
&&
(calendar.userChecked || !checkHover),
'uni-calendar-item--checked-range-text': checkHover,
'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,
}">
<text
v-if=
"selected && weeks.extraInfo"
class=
"uni-calendar-item__weeks-box-circle"
></text>
<text
class=
"uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text"
>
{{
weeks
.
date
}}
</text>
</view>
<view
:class=
"
{'uni-calendar-item--today': weeks.isToday}">
</view>
</view>
</
template
>
<
script
>
export
default
{
props
:
{
weeks
:
{
type
:
Object
,
default
()
{
return
{}
}
},
calendar
:
{
type
:
Object
,
default
:
()
=>
{
return
{}
}
},
selected
:
{
type
:
Array
,
default
:
()
=>
{
return
[]
}
},
checkHover
:
{
type
:
Boolean
,
default
:
false
}
},
methods
:
{
choiceDate
(
weeks
)
{
this
.
$emit
(
'change'
,
weeks
)
},
handleMousemove
(
weeks
)
{
this
.
$emit
(
'handleMouse'
,
weeks
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
$uni-primary
:
#007aff
!
default
;
.uni-calendar-item__weeks-box
{
flex
:
1
;
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
margin
:
1px
0
;
position
:
relative
;
}
.uni-calendar-item__weeks-box-text
{
font-size
:
14px
;
// font-family: Lato-Bold, Lato;
font-weight
:
bold
;
color
:
darken
(
$color
:
$uni-primary
,
$amount
:
40%
);
}
.uni-calendar-item__weeks-box-item
{
position
:
relative
;
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
width
:
40px
;
height
:
40px
;
/* #ifdef H5 */
cursor
:
pointer
;
/* #endif */
}
.uni-calendar-item__weeks-box-circle
{
position
:
absolute
;
top
:
5px
;
right
:
5px
;
width
:
8px
;
height
:
8px
;
border-radius
:
8px
;
background-color
:
#dd524d
;
}
.uni-calendar-item__weeks-box
.uni-calendar-item--disable
{
cursor
:
default
;
}
.uni-calendar-item--disable
.uni-calendar-item__weeks-box-text-disable
{
color
:
#D1D1D1
;
}
.uni-calendar-item--today
{
position
:
absolute
;
top
:
10px
;
right
:
17%
;
background-color
:
#dd524d
;
width
:
6px
;
height
:
6px
;
border-radius
:
50%
;
}
.uni-calendar-item--extra
{
color
:
#dd524d
;
opacity
:
0
.8
;
}
.uni-calendar-item__weeks-box
.uni-calendar-item--checked
{
background-color
:
$uni-primary
;
border-radius
:
50%
;
box-sizing
:
border-box
;
border
:
3px
solid
#fff
;
}
.uni-calendar-item--checked
.uni-calendar-item--checked-text
{
color
:
#fff
;
}
.uni-calendar-item--multiple
.uni-calendar-item--checked-range-text
{
color
:
#333
;
}
.uni-calendar-item--multiple
{
background-color
:
#F6F7FC
;
// color: #fff;
}
.uni-calendar-item--multiple
.uni-calendar-item--before-checked
,
.uni-calendar-item--multiple
.uni-calendar-item--after-checked
{
background-color
:
$uni-primary
;
border-radius
:
50%
;
box-sizing
:
border-box
;
border
:
3px
solid
#F6F7FC
;
}
.uni-calendar-item--before-checked
.uni-calendar-item--checked-text
,
.uni-calendar-item--after-checked
.uni-calendar-item--checked-text
{
color
:
#fff
;
}
.uni-calendar-item--before-checked-x
{
border-top-left-radius
:
50px
;
border-bottom-left-radius
:
50px
;
box-sizing
:
border-box
;
background-color
:
#F6F7FC
;
}
.uni-calendar-item--after-checked-x
{
border-top-right-radius
:
50px
;
border-bottom-right-radius
:
50px
;
background-color
:
#F6F7FC
;
}
</
style
>
uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
0 → 100644
View file @
970699b8
<
template
>
<view
class=
"uni-calendar"
@
mouseleave=
"leaveCale"
>
<view
v-if=
"!insert && show"
class=
"uni-calendar__mask"
:class=
"
{'uni-calendar--mask-show':aniMaskShow}"
@click="maskClick">
</view>
<view
v-if=
"insert || show"
class=
"uni-calendar__content"
:class=
"
{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
<view
class=
"uni-calendar__header"
:class=
"
{'uni-calendar__header-mobile' :!insert}">
<view
class=
"uni-calendar__header-btn-box"
@
click
.
stop=
"changeMonth('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
||
''
)
+
yearText
+
(
nowDate
.
month
||
''
)
+
monthText
}}
</text>
</picker>
<view
class=
"uni-calendar__header-btn-box"
@
click
.
stop=
"changeMonth('next')"
>
<view
class=
"uni-calendar__header-btn uni-calendar--right"
></view>
</view>
<view
v-if=
"!insert"
class=
"dialog-close"
@
click=
"maskClick"
>
<view
class=
"dialog-close-plus"
data-id=
"close"
></view>
<view
class=
"dialog-close-plus dialog-close-rotate"
data-id=
"close"
></view>
</view>
</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"
style=
"padding-bottom: 7px;"
>
<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"
:checkHover=
"range"
@
change=
"choiceDate"
@
handleMouse=
"handleMouse"
>
</calendar-item>
</view>
</view>
</view>
<view
v-if=
"!insert && !range && hasTime"
class=
"uni-date-changed uni-calendar--fixed-top"
style=
"padding: 0 80px;"
>
<view
class=
"uni-date-changed--time-date"
>
{{
tempSingleDate
?
tempSingleDate
:
selectDateText
}}
</view>
<time-picker
type=
"time"
:start=
"timepickerStartTime"
:end=
"timepickerEndTime"
v-model=
"time"
:disabled=
"!tempSingleDate"
:border=
"false"
:hide-second=
"hideSecond"
class=
"time-picker-style"
>
</time-picker>
</view>
<view
v-if=
"!insert && range && hasTime"
class=
"uni-date-changed uni-calendar--fixed-top"
>
<view
class=
"uni-date-changed--time-start"
>
<view
class=
"uni-date-changed--time-date"
>
{{
tempRange
.
before
?
tempRange
.
before
:
startDateText
}}
</view>
<time-picker
type=
"time"
:start=
"timepickerStartTime"
v-model=
"timeRange.startTime"
:border=
"false"
:hide-second=
"hideSecond"
:disabled=
"!tempRange.before"
class=
"time-picker-style"
>
</time-picker>
</view>
<view
style=
"line-height: 50px;"
>
<uni-icons
type=
"arrowthinright"
color=
"#999"
></uni-icons>
</view>
<view
class=
"uni-date-changed--time-end"
>
<view
class=
"uni-date-changed--time-date"
>
{{
tempRange
.
after
?
tempRange
.
after
:
endDateText
}}
</view>
<time-picker
type=
"time"
:end=
"timepickerEndTime"
v-model=
"timeRange.endTime"
:border=
"false"
:hide-second=
"hideSecond"
:disabled=
"!tempRange.after"
class=
"time-picker-style"
>
</time-picker>
</view>
</view>
<view
v-if=
"!insert"
class=
"uni-date-changed uni-date-btn--ok"
>
<view
class=
"uni-datetime-picker--btn"
@
click=
"confirm"
>
{{
confirmText
}}
</view>
</view>
</view>
</view>
</
template
>
<
script
>
import
{
Calendar
,
getDate
,
getTime
}
from
'./util.js'
;
import
calendarItem
from
'./calendar-item.vue'
import
timePicker
from
'./time-picker.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 {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 是否选择月份为背景
* @property {[String} defaultValue 选择器打开时默认显示的时间
* @event {Function} change 日期改变,`insert :ture` 时生效
* @event {Function} confirm 确认选择`insert :false` 时生效
* @event {Function} monthSwitch 切换月份时触发
* @example <uni-calendar :insert="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
*/
export
default
{
components
:
{
calendarItem
,
timePicker
},
options
:
{
// #ifdef MP-TOUTIAO
virtualHost
:
false
,
// #endif
// #ifndef MP-TOUTIAO
virtualHost
:
true
// #endif
},
props
:
{
date
:
{
type
:
String
,
default
:
''
},
defTime
:
{
type
:
[
String
,
Object
],
default
:
''
},
selectableTimes
:
{
type
:
[
Object
],
default
()
{
return
{}
}
},
selected
:
{
type
:
Array
,
default
()
{
return
[]
}
},
startDate
:
{
type
:
String
,
default
:
''
},
endDate
:
{
type
:
String
,
default
:
''
},
startPlaceholder
:
{
type
:
String
,
default
:
''
},
endPlaceholder
:
{
type
:
String
,
default
:
''
},
range
:
{
type
:
Boolean
,
default
:
false
},
hasTime
:
{
type
:
Boolean
,
default
:
false
},
insert
:
{
type
:
Boolean
,
default
:
true
},
showMonth
:
{
type
:
Boolean
,
default
:
true
},
clearDate
:
{
type
:
Boolean
,
default
:
true
},
checkHover
:
{
type
:
Boolean
,
default
:
true
},
hideSecond
:
{
type
:
[
Boolean
],
default
:
false
},
pleStatus
:
{
type
:
Object
,
default
()
{
return
{
before
:
''
,
after
:
''
,
data
:
[],
fulldate
:
''
}
}
},
defaultValue
:
{
type
:
[
String
,
Object
,
Array
],
default
:
''
}
},
data
()
{
return
{
show
:
false
,
weeks
:
[],
calendar
:
{},
nowDate
:
{},
aniMaskShow
:
false
,
firstEnter
:
true
,
time
:
''
,
timeRange
:
{
startTime
:
''
,
endTime
:
''
},
tempSingleDate
:
''
,
tempRange
:
{
before
:
''
,
after
:
''
}
}
},
watch
:
{
date
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
!
this
.
range
)
{
this
.
tempSingleDate
=
newVal
setTimeout
(()
=>
{
this
.
init
(
newVal
)
},
100
)
}
}
},
defTime
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
!
this
.
range
)
{
this
.
time
=
newVal
}
else
{
this
.
timeRange
.
startTime
=
newVal
.
start
this
.
timeRange
.
endTime
=
newVal
.
end
}
}
},
startDate
(
val
)
{
// 字节小程序 watch 早于 created
if
(
!
this
.
cale
)
{
return
}
this
.
cale
.
setStartDate
(
val
)
this
.
cale
.
setDate
(
this
.
nowDate
.
fullDate
)
this
.
weeks
=
this
.
cale
.
weeks
},
endDate
(
val
)
{
// 字节小程序 watch 早于 created
if
(
!
this
.
cale
)
{
return
}
this
.
cale
.
setEndDate
(
val
)
this
.
cale
.
setDate
(
this
.
nowDate
.
fullDate
)
this
.
weeks
=
this
.
cale
.
weeks
},
selected
(
newVal
)
{
// 字节小程序 watch 早于 created
if
(
!
this
.
cale
)
{
return
}
this
.
cale
.
setSelectInfo
(
this
.
nowDate
.
fullDate
,
newVal
)
this
.
weeks
=
this
.
cale
.
weeks
},
pleStatus
:
{
immediate
:
true
,
handler
(
newVal
)
{
const
{
before
,
after
,
fulldate
,
which
}
=
newVal
this
.
tempRange
.
before
=
before
this
.
tempRange
.
after
=
after
setTimeout
(()
=>
{
if
(
fulldate
)
{
this
.
cale
.
setHoverMultiple
(
fulldate
)
if
(
before
&&
after
)
{
this
.
cale
.
lastHover
=
true
if
(
this
.
rangeWithinMonth
(
after
,
before
))
return
this
.
setDate
(
before
)
}
else
{
this
.
cale
.
setMultiple
(
fulldate
)
this
.
setDate
(
this
.
nowDate
.
fullDate
)
this
.
calendar
.
fullDate
=
''
this
.
cale
.
lastHover
=
false
}
}
else
{
// 字节小程序 watch 早于 created
if
(
!
this
.
cale
)
{
return
}
this
.
cale
.
setDefaultMultiple
(
before
,
after
)
if
(
which
===
'left'
&&
before
)
{
this
.
setDate
(
before
)
this
.
weeks
=
this
.
cale
.
weeks
}
else
if
(
after
)
{
this
.
setDate
(
after
)
this
.
weeks
=
this
.
cale
.
weeks
}
this
.
cale
.
lastHover
=
true
}
},
16
)
}
}
},
computed
:
{
timepickerStartTime
()
{
const
activeDate
=
this
.
range
?
this
.
tempRange
.
before
:
this
.
calendar
.
fullDate
return
activeDate
===
this
.
startDate
?
this
.
selectableTimes
.
start
:
''
},
timepickerEndTime
()
{
const
activeDate
=
this
.
range
?
this
.
tempRange
.
after
:
this
.
calendar
.
fullDate
return
activeDate
===
this
.
endDate
?
this
.
selectableTimes
.
end
:
''
},
/**
* for i18n
*/
selectDateText
()
{
return
t
(
"uni-datetime-picker.selectDate"
)
},
startDateText
()
{
return
this
.
startPlaceholder
||
t
(
"uni-datetime-picker.startDate"
)
},
endDateText
()
{
return
this
.
endPlaceholder
||
t
(
"uni-datetime-picker.endDate"
)
},
okText
()
{
return
t
(
"uni-datetime-picker.ok"
)
},
yearText
()
{
return
t
(
"uni-datetime-picker.year"
)
},
monthText
()
{
return
t
(
"uni-datetime-picker.month"
)
},
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"
)
},
confirmText
()
{
return
t
(
"uni-calender.confirm"
)
},
},
created
()
{
// 获取日历方法实例
this
.
cale
=
new
Calendar
({
selected
:
this
.
selected
,
startDate
:
this
.
startDate
,
endDate
:
this
.
endDate
,
range
:
this
.
range
,
})
// 选中某一天
this
.
init
(
this
.
date
)
},
methods
:
{
leaveCale
()
{
this
.
firstEnter
=
true
},
handleMouse
(
weeks
)
{
if
(
weeks
.
disable
)
return
if
(
this
.
cale
.
lastHover
)
return
let
{
before
,
after
}
=
this
.
cale
.
multipleStatus
if
(
!
before
)
return
this
.
calendar
=
weeks
// 设置范围选
this
.
cale
.
setHoverMultiple
(
this
.
calendar
.
fullDate
)
this
.
weeks
=
this
.
cale
.
weeks
// hover时,进入一个日历,更新另一个
if
(
this
.
firstEnter
)
{
this
.
$emit
(
'firstEnterCale'
,
this
.
cale
.
multipleStatus
)
this
.
firstEnter
=
false
}
},
rangeWithinMonth
(
A
,
B
)
{
const
[
yearA
,
monthA
]
=
A
.
split
(
'-'
)
const
[
yearB
,
monthB
]
=
B
.
split
(
'-'
)
return
yearA
===
yearB
&&
monthA
===
monthB
},
// 蒙版点击事件
maskClick
()
{
this
.
close
()
this
.
$emit
(
'maskClose'
)
},
clearCalender
()
{
if
(
this
.
range
)
{
this
.
timeRange
.
startTime
=
''
this
.
timeRange
.
endTime
=
''
this
.
tempRange
.
before
=
''
this
.
tempRange
.
after
=
''
this
.
cale
.
multipleStatus
.
before
=
''
this
.
cale
.
multipleStatus
.
after
=
''
this
.
cale
.
multipleStatus
.
data
=
[]
this
.
cale
.
lastHover
=
false
}
else
{
this
.
time
=
''
this
.
tempSingleDate
=
''
}
this
.
calendar
.
fullDate
=
''
this
.
setDate
(
new
Date
())
},
bindDateChange
(
e
)
{
const
value
=
e
.
detail
.
value
+
'-1'
this
.
setDate
(
value
)
},
/**
* 初始化日期显示
* @param {Object} date
*/
init
(
date
)
{
// 字节小程序 watch 早于 created
if
(
!
this
.
cale
)
{
return
}
this
.
cale
.
setDate
(
date
||
new
Date
())
this
.
weeks
=
this
.
cale
.
weeks
this
.
nowDate
=
this
.
cale
.
getInfo
(
date
)
this
.
calendar
=
{
...
this
.
nowDate
}
if
(
!
date
)
{
// 优化date为空默认不选中今天
this
.
calendar
.
fullDate
=
''
if
(
this
.
defaultValue
&&
!
this
.
range
)
{
// 暂时只支持移动端非范围选择
const
defaultDate
=
new
Date
(
this
.
defaultValue
)
const
fullDate
=
getDate
(
defaultDate
)
const
year
=
defaultDate
.
getFullYear
()
const
month
=
defaultDate
.
getMonth
()
+
1
const
date
=
defaultDate
.
getDate
()
const
day
=
defaultDate
.
getDay
()
this
.
calendar
=
{
fullDate
,
year
,
month
,
date
,
day
},
this
.
tempSingleDate
=
fullDate
this
.
time
=
getTime
(
defaultDate
,
this
.
hideSecond
)
}
}
},
/**
* 打开日历弹窗
*/
open
()
{
// 弹窗模式并且清理数据
if
(
this
.
clearDate
&&
!
this
.
insert
)
{
this
.
cale
.
cleanMultipleStatus
()
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
(
isSingleChange
)
{
if
(
!
this
.
insert
&&
!
isSingleChange
)
return
this
.
setEmit
(
'change'
)
},
/**
* 选择月份触发
*/
monthSwitch
()
{
let
{
year
,
month
}
=
this
.
nowDate
this
.
$emit
(
'monthSwitch'
,
{
year
,
month
:
Number
(
month
)
})
},
/**
* 派发事件
* @param {Object} name
*/
setEmit
(
name
)
{
if
(
!
this
.
range
)
{
if
(
!
this
.
calendar
.
fullDate
)
{
this
.
calendar
=
this
.
cale
.
getInfo
(
new
Date
())
this
.
tempSingleDate
=
this
.
calendar
.
fullDate
}
if
(
this
.
hasTime
&&
!
this
.
time
)
{
this
.
time
=
getTime
(
new
Date
(),
this
.
hideSecond
)
}
}
let
{
year
,
month
,
date
,
fullDate
,
extraInfo
}
=
this
.
calendar
this
.
$emit
(
name
,
{
range
:
this
.
cale
.
multipleStatus
,
year
,
month
,
date
,
time
:
this
.
time
,
timeRange
:
this
.
timeRange
,
fulldate
:
fullDate
,
extraInfo
:
extraInfo
||
{}
})
},
/**
* 选择天触发
* @param {Object} weeks
*/
choiceDate
(
weeks
)
{
if
(
weeks
.
disable
)
return
this
.
calendar
=
weeks
this
.
calendar
.
userChecked
=
true
// 设置多选
this
.
cale
.
setMultiple
(
this
.
calendar
.
fullDate
,
true
)
this
.
weeks
=
this
.
cale
.
weeks
this
.
tempSingleDate
=
this
.
calendar
.
fullDate
const
beforeDate
=
new
Date
(
this
.
cale
.
multipleStatus
.
before
).
getTime
()
const
afterDate
=
new
Date
(
this
.
cale
.
multipleStatus
.
after
).
getTime
()
if
(
beforeDate
>
afterDate
&&
afterDate
)
{
this
.
tempRange
.
before
=
this
.
cale
.
multipleStatus
.
after
this
.
tempRange
.
after
=
this
.
cale
.
multipleStatus
.
before
}
else
{
this
.
tempRange
.
before
=
this
.
cale
.
multipleStatus
.
before
this
.
tempRange
.
after
=
this
.
cale
.
multipleStatus
.
after
}
this
.
change
(
true
)
},
changeMonth
(
type
)
{
let
newDate
if
(
type
===
'pre'
)
{
newDate
=
this
.
cale
.
getPreMonthObj
(
this
.
nowDate
.
fullDate
).
fullDate
}
else
if
(
type
===
'next'
)
{
newDate
=
this
.
cale
.
getNextMonthObj
(
this
.
nowDate
.
fullDate
).
fullDate
}
this
.
setDate
(
newDate
)
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"
>
$uni-primary
:
#007aff
!
default
;
.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
:
rgba
(
0
,
0
,
0
,
0
.4
);
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
;
bottom
:
calc
(
var
(
--
window-bottom
));
left
:
0
;
right
:
0
;
transition-property
:
transform
;
transition-duration
:
0
.3s
;
transform
:
translateY
(
460px
);
/* #ifndef APP-NVUE */
z-index
:
99
;
/* #endif */
}
.uni-calendar--ani-show
{
transform
:
translateY
(
0
);
}
.uni-calendar__content
{
background-color
:
#fff
;
}
.uni-calendar__content-mobile
{
border-top-left-radius
:
10px
;
border-top-right-radius
:
10px
;
box-shadow
:
0px
0px
5px
3px
rgba
(
0
,
0
,
0
,
0
.1
);
}
.uni-calendar__header
{
position
:
relative
;
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
justify-content
:
center
;
align-items
:
center
;
height
:
50px
;
}
.uni-calendar__header-mobile
{
padding
:
10px
;
padding-bottom
:
0
;
}
.uni-calendar--fixed-top
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
justify-content
:
space-between
;
border-top-color
:
rgba
(
0
,
0
,
0
,
0
.4
);
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
:
#fff
;
background-color
:
#f1f1f1
;
}
.uni-calendar__header-text
{
text-align
:
center
;
width
:
100px
;
font-size
:
15px
;
color
:
#666
;
}
.uni-calendar__button-text
{
text-align
:
center
;
width
:
100px
;
font-size
:
14px
;
color
:
$uni-primary
;
/* #ifndef APP-NVUE */
letter-spacing
:
3px
;
/* #endif */
}
.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
:
9px
;
height
:
9px
;
border-left-color
:
#808080
;
border-left-style
:
solid
;
border-left-width
:
1px
;
border-top-color
:
#555555
;
border-top-style
:
solid
;
border-top-width
:
1px
;
}
.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
:
40px
;
border-bottom-color
:
#F5F5F5
;
border-bottom-style
:
solid
;
border-bottom-width
:
1px
;
}
.uni-calendar__weeks-day-text
{
font-size
:
12px
;
color
:
#B2B2B2
;
}
.uni-calendar__box
{
position
:
relative
;
// padding: 0 10px;
padding-bottom
:
7px
;
}
.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
:
#999
;
opacity
:
0
.1
;
text-align
:
center
;
/* #ifndef APP-NVUE */
line-height
:
1
;
/* #endif */
}
.uni-date-changed
{
padding
:
0
10px
;
// line-height: 50px;
text-align
:
center
;
color
:
#333
;
border-top-color
:
#DCDCDC
;
;
border-top-style
:
solid
;
border-top-width
:
1px
;
flex
:
1
;
}
.uni-date-btn--ok
{
padding
:
20px
15px
;
}
.uni-date-changed--time-start
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
align-items
:
center
;
}
.uni-date-changed--time-end
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
align-items
:
center
;
}
.uni-date-changed--time-date
{
color
:
#999
;
line-height
:
50px
;
/* #ifdef MP-TOUTIAO */
font-size
:
16px
;
/* #endif */
margin-right
:
5px
;
// opacity: 0.6;
}
.time-picker-style
{
// width: 62px;
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
justify-content
:
center
;
align-items
:
center
}
.mr-10
{
margin-right
:
10px
;
}
.dialog-close
{
position
:
absolute
;
top
:
0
;
right
:
0
;
bottom
:
0
;
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
align-items
:
center
;
padding
:
0
25px
;
margin-top
:
10px
;
}
.dialog-close-plus
{
width
:
16px
;
height
:
2px
;
background-color
:
#737987
;
border-radius
:
2px
;
transform
:
rotate
(
45deg
);
}
.dialog-close-rotate
{
position
:
absolute
;
transform
:
rotate
(
-45deg
);
}
.uni-datetime-picker--btn
{
border-radius
:
100px
;
height
:
40px
;
line-height
:
40px
;
background-color
:
$uni-primary
;
color
:
#fff
;
font-size
:
16px
;
letter-spacing
:
2px
;
}
/* #ifndef APP-NVUE */
.uni-datetime-picker--btn
:active
{
opacity
:
0
.7
;
}
/* #endif */
</
style
>
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
0 → 100644
View file @
970699b8
{
"uni-datetime-picker.selectDate"
:
"select date"
,
"uni-datetime-picker.selectTime"
:
"select time"
,
"uni-datetime-picker.selectDateTime"
:
"select date and time"
,
"uni-datetime-picker.startDate"
:
"start date"
,
"uni-datetime-picker.endDate"
:
"end date"
,
"uni-datetime-picker.startTime"
:
"start time"
,
"uni-datetime-picker.endTime"
:
"end time"
,
"uni-datetime-picker.ok"
:
"ok"
,
"uni-datetime-picker.clear"
:
"clear"
,
"uni-datetime-picker.cancel"
:
"cancel"
,
"uni-datetime-picker.year"
:
"-"
,
"uni-datetime-picker.month"
:
""
,
"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"
,
"uni-calender.confirm"
:
"confirm"
}
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
0 → 100644
View file @
970699b8
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
}
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
0 → 100644
View file @
970699b8
{
"uni-datetime-picker.selectDate"
:
"选择日期"
,
"uni-datetime-picker.selectTime"
:
"选择时间"
,
"uni-datetime-picker.selectDateTime"
:
"选择日期时间"
,
"uni-datetime-picker.startDate"
:
"开始日期"
,
"uni-datetime-picker.endDate"
:
"结束日期"
,
"uni-datetime-picker.startTime"
:
"开始时间"
,
"uni-datetime-picker.endTime"
:
"结束时间"
,
"uni-datetime-picker.ok"
:
"确定"
,
"uni-datetime-picker.clear"
:
"清除"
,
"uni-datetime-picker.cancel"
:
"取消"
,
"uni-datetime-picker.year"
:
"年"
,
"uni-datetime-picker.month"
:
"月"
,
"uni-calender.SUN"
:
"日"
,
"uni-calender.MON"
:
"一"
,
"uni-calender.TUE"
:
"二"
,
"uni-calender.WED"
:
"三"
,
"uni-calender.THU"
:
"四"
,
"uni-calender.FRI"
:
"五"
,
"uni-calender.SAT"
:
"六"
,
"uni-calender.confirm"
:
"确认"
}
\ No newline at end of file
uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
0 → 100644
View file @
970699b8
{
"uni-datetime-picker.selectDate"
:
"選擇日期"
,
"uni-datetime-picker.selectTime"
:
"選擇時間"
,
"uni-datetime-picker.selectDateTime"
:
"選擇日期時間"
,
"uni-datetime-picker.startDate"
:
"開始日期"
,
"uni-datetime-picker.endDate"
:
"結束日期"
,
"uni-datetime-picker.startTime"
:
"開始时间"
,
"uni-datetime-picker.endTime"
:
"結束时间"
,
"uni-datetime-picker.ok"
:
"確定"
,
"uni-datetime-picker.clear"
:
"清除"
,
"uni-datetime-picker.cancel"
:
"取消"
,
"uni-datetime-picker.year"
:
"年"
,
"uni-datetime-picker.month"
:
"月"
,
"uni-calender.SUN"
:
"日"
,
"uni-calender.MON"
:
"一"
,
"uni-calender.TUE"
:
"二"
,
"uni-calender.WED"
:
"三"
,
"uni-calender.THU"
:
"四"
,
"uni-calender.FRI"
:
"五"
,
"uni-calender.SAT"
:
"六"
,
"uni-calender.confirm"
:
"確認"
}
\ No newline at end of file
uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
0 → 100644
View file @
970699b8
<
template
>
<view
class=
"uni-datetime-picker"
>
<view
@
click=
"initTimePicker"
>
<slot>
<view
class=
"uni-datetime-picker-timebox-pointer"
:class=
"
{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
<text
class=
"uni-datetime-picker-text"
>
{{
time
}}
</text>
<view
v-if=
"!time"
class=
"uni-datetime-picker-time"
>
<text
class=
"uni-datetime-picker-text"
>
{{
selectTimeText
}}
</text>
</view>
</view>
</slot>
</view>
<view
v-if=
"visible"
id=
"mask"
class=
"uni-datetime-picker-mask"
@
click=
"tiggerTimePicker"
></view>
<view
v-if=
"visible"
class=
"uni-datetime-picker-popup"
:class=
"[dateShow && timeShow ? '' : 'fix-nvue-height']"
:style=
"fixNvueBug"
>
<view
class=
"uni-title"
>
<text
class=
"uni-datetime-picker-text"
>
{{
selectTimeText
}}
</text>
</view>
<view
v-if=
"dateShow"
class=
"uni-datetime-picker__container-box"
>
<picker-view
class=
"uni-datetime-picker-view"
:indicator-style=
"indicatorStyle"
:value=
"ymd"
@
change=
"bindDateChange"
>
<picker-view-column>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in years"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
<picker-view-column>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in months"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
<picker-view-column>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in days"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text
class=
"uni-datetime-picker-sign sign-left"
>
-
</text>
<text
class=
"uni-datetime-picker-sign sign-right"
>
-
</text>
</view>
<view
v-if=
"timeShow"
class=
"uni-datetime-picker__container-box"
>
<picker-view
class=
"uni-datetime-picker-view"
:class=
"[hideSecond ? 'time-hide-second' : '']"
:indicator-style=
"indicatorStyle"
:value=
"hms"
@
change=
"bindTimeChange"
>
<picker-view-column>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in hours"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
<picker-view-column>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in minutes"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
<picker-view-column
v-if=
"!hideSecond"
>
<view
class=
"uni-datetime-picker-item"
v-for=
"(item,index) in seconds"
:key=
"index"
>
<text
class=
"uni-datetime-picker-item"
>
{{
lessThanTen
(
item
)
}}
</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text
class=
"uni-datetime-picker-sign"
:class=
"[hideSecond ? 'sign-center' : 'sign-left']"
>
:
</text>
<text
v-if=
"!hideSecond"
class=
"uni-datetime-picker-sign sign-right"
>
:
</text>
</view>
<view
class=
"uni-datetime-picker-btn"
>
<view
@
click=
"clearTime"
>
<text
class=
"uni-datetime-picker-btn-text"
>
{{
clearText
}}
</text>
</view>
<view
class=
"uni-datetime-picker-btn-group"
>
<view
class=
"uni-datetime-picker-cancel"
@
click=
"tiggerTimePicker"
>
<text
class=
"uni-datetime-picker-btn-text"
>
{{
cancelText
}}
</text>
</view>
<view
@
click=
"setTime"
>
<text
class=
"uni-datetime-picker-btn-text"
>
{{
okText
}}
</text>
</view>
</view>
</view>
</view>
</view>
</
template
>
<
script
>
import
{
initVueI18n
}
from
'@dcloudio/uni-i18n'
import
i18nMessages
from
'./i18n/index.js'
const
{
t
}
=
initVueI18n
(
i18nMessages
)
import
{
fixIosDateFormat
}
from
'./util'
/**
* DatetimePicker 时间选择器
* @description 可以同时选择日期和时间的选择器
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
* @property {String} type = [datetime | date | time] 显示模式
* @property {Boolean} multiple = [true|false] 是否多选
* @property {String|Number} value 默认值
* @property {String|Number} start 起始日期或时间
* @property {String|Number} end 起始日期或时间
* @property {String} return-type = [timestamp | string]
* @event {Function} change 选中发生变化触发
*/
export
default
{
name
:
'UniDatetimePicker'
,
data
()
{
return
{
indicatorStyle
:
`height: 50px;`
,
visible
:
false
,
fixNvueBug
:
{},
dateShow
:
true
,
timeShow
:
true
,
title
:
'日期和时间'
,
// 输入框当前时间
time
:
''
,
// 当前的年月日时分秒
year
:
1920
,
month
:
0
,
day
:
0
,
hour
:
0
,
minute
:
0
,
second
:
0
,
// 起始时间
startYear
:
1920
,
startMonth
:
1
,
startDay
:
1
,
startHour
:
0
,
startMinute
:
0
,
startSecond
:
0
,
// 结束时间
endYear
:
2120
,
endMonth
:
12
,
endDay
:
31
,
endHour
:
23
,
endMinute
:
59
,
endSecond
:
59
,
}
},
options
:
{
// #ifdef MP-TOUTIAO
virtualHost
:
false
,
// #endif
// #ifndef MP-TOUTIAO
virtualHost
:
true
// #endif
},
props
:
{
type
:
{
type
:
String
,
default
:
'datetime'
},
value
:
{
type
:
[
String
,
Number
],
default
:
''
},
modelValue
:
{
type
:
[
String
,
Number
],
default
:
''
},
start
:
{
type
:
[
Number
,
String
],
default
:
''
},
end
:
{
type
:
[
Number
,
String
],
default
:
''
},
returnType
:
{
type
:
String
,
default
:
'string'
},
disabled
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
border
:
{
type
:
[
Boolean
,
String
],
default
:
true
},
hideSecond
:
{
type
:
[
Boolean
,
String
],
default
:
false
}
},
watch
:
{
// #ifndef VUE3
value
:
{
handler
(
newVal
)
{
if
(
newVal
)
{
this
.
parseValue
(
fixIosDateFormat
(
newVal
))
this
.
initTime
(
false
)
}
else
{
this
.
time
=
''
this
.
parseValue
(
Date
.
now
())
}
},
immediate
:
true
},
// #endif
// #ifdef VUE3
modelValue
:
{
handler
(
newVal
)
{
if
(
newVal
)
{
this
.
parseValue
(
fixIosDateFormat
(
newVal
))
this
.
initTime
(
false
)
}
else
{
this
.
time
=
''
this
.
parseValue
(
Date
.
now
())
}
},
immediate
:
true
},
// #endif
type
:
{
handler
(
newValue
)
{
if
(
newValue
===
'date'
)
{
this
.
dateShow
=
true
this
.
timeShow
=
false
this
.
title
=
'日期'
}
else
if
(
newValue
===
'time'
)
{
this
.
dateShow
=
false
this
.
timeShow
=
true
this
.
title
=
'时间'
}
else
{
this
.
dateShow
=
true
this
.
timeShow
=
true
this
.
title
=
'日期和时间'
}
},
immediate
:
true
},
start
:
{
handler
(
newVal
)
{
this
.
parseDatetimeRange
(
fixIosDateFormat
(
newVal
),
'start'
)
},
immediate
:
true
},
end
:
{
handler
(
newVal
)
{
this
.
parseDatetimeRange
(
fixIosDateFormat
(
newVal
),
'end'
)
},
immediate
:
true
},
// 月、日、时、分、秒可选范围变化后,检查当前值是否在范围内,不在则当前值重置为可选范围第一项
months
(
newVal
)
{
this
.
checkValue
(
'month'
,
this
.
month
,
newVal
)
},
days
(
newVal
)
{
this
.
checkValue
(
'day'
,
this
.
day
,
newVal
)
},
hours
(
newVal
)
{
this
.
checkValue
(
'hour'
,
this
.
hour
,
newVal
)
},
minutes
(
newVal
)
{
this
.
checkValue
(
'minute'
,
this
.
minute
,
newVal
)
},
seconds
(
newVal
)
{
this
.
checkValue
(
'second'
,
this
.
second
,
newVal
)
}
},
computed
:
{
// 当前年、月、日、时、分、秒选择范围
years
()
{
return
this
.
getCurrentRange
(
'year'
)
},
months
()
{
return
this
.
getCurrentRange
(
'month'
)
},
days
()
{
return
this
.
getCurrentRange
(
'day'
)
},
hours
()
{
return
this
.
getCurrentRange
(
'hour'
)
},
minutes
()
{
return
this
.
getCurrentRange
(
'minute'
)
},
seconds
()
{
return
this
.
getCurrentRange
(
'second'
)
},
// picker 当前值数组
ymd
()
{
return
[
this
.
year
-
this
.
minYear
,
this
.
month
-
this
.
minMonth
,
this
.
day
-
this
.
minDay
]
},
hms
()
{
return
[
this
.
hour
-
this
.
minHour
,
this
.
minute
-
this
.
minMinute
,
this
.
second
-
this
.
minSecond
]
},
// 当前 date 是 start
currentDateIsStart
()
{
return
this
.
year
===
this
.
startYear
&&
this
.
month
===
this
.
startMonth
&&
this
.
day
===
this
.
startDay
},
// 当前 date 是 end
currentDateIsEnd
()
{
return
this
.
year
===
this
.
endYear
&&
this
.
month
===
this
.
endMonth
&&
this
.
day
===
this
.
endDay
},
// 当前年、月、日、时、分、秒的最小值和最大值
minYear
()
{
return
this
.
startYear
},
maxYear
()
{
return
this
.
endYear
},
minMonth
()
{
if
(
this
.
year
===
this
.
startYear
)
{
return
this
.
startMonth
}
else
{
return
1
}
},
maxMonth
()
{
if
(
this
.
year
===
this
.
endYear
)
{
return
this
.
endMonth
}
else
{
return
12
}
},
minDay
()
{
if
(
this
.
year
===
this
.
startYear
&&
this
.
month
===
this
.
startMonth
)
{
return
this
.
startDay
}
else
{
return
1
}
},
maxDay
()
{
if
(
this
.
year
===
this
.
endYear
&&
this
.
month
===
this
.
endMonth
)
{
return
this
.
endDay
}
else
{
return
this
.
daysInMonth
(
this
.
year
,
this
.
month
)
}
},
minHour
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsStart
)
{
return
this
.
startHour
}
else
{
return
0
}
}
if
(
this
.
type
===
'time'
)
{
return
this
.
startHour
}
},
maxHour
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsEnd
)
{
return
this
.
endHour
}
else
{
return
23
}
}
if
(
this
.
type
===
'time'
)
{
return
this
.
endHour
}
},
minMinute
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsStart
&&
this
.
hour
===
this
.
startHour
)
{
return
this
.
startMinute
}
else
{
return
0
}
}
if
(
this
.
type
===
'time'
)
{
if
(
this
.
hour
===
this
.
startHour
)
{
return
this
.
startMinute
}
else
{
return
0
}
}
},
maxMinute
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsEnd
&&
this
.
hour
===
this
.
endHour
)
{
return
this
.
endMinute
}
else
{
return
59
}
}
if
(
this
.
type
===
'time'
)
{
if
(
this
.
hour
===
this
.
endHour
)
{
return
this
.
endMinute
}
else
{
return
59
}
}
},
minSecond
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsStart
&&
this
.
hour
===
this
.
startHour
&&
this
.
minute
===
this
.
startMinute
)
{
return
this
.
startSecond
}
else
{
return
0
}
}
if
(
this
.
type
===
'time'
)
{
if
(
this
.
hour
===
this
.
startHour
&&
this
.
minute
===
this
.
startMinute
)
{
return
this
.
startSecond
}
else
{
return
0
}
}
},
maxSecond
()
{
if
(
this
.
type
===
'datetime'
)
{
if
(
this
.
currentDateIsEnd
&&
this
.
hour
===
this
.
endHour
&&
this
.
minute
===
this
.
endMinute
)
{
return
this
.
endSecond
}
else
{
return
59
}
}
if
(
this
.
type
===
'time'
)
{
if
(
this
.
hour
===
this
.
endHour
&&
this
.
minute
===
this
.
endMinute
)
{
return
this
.
endSecond
}
else
{
return
59
}
}
},
/**
* for i18n
*/
selectTimeText
()
{
return
t
(
"uni-datetime-picker.selectTime"
)
},
okText
()
{
return
t
(
"uni-datetime-picker.ok"
)
},
clearText
()
{
return
t
(
"uni-datetime-picker.clear"
)
},
cancelText
()
{
return
t
(
"uni-datetime-picker.cancel"
)
}
},
mounted
()
{
// #ifdef APP-NVUE
const
res
=
uni
.
getSystemInfoSync
();
this
.
fixNvueBug
=
{
top
:
res
.
windowHeight
/
2
,
left
:
res
.
windowWidth
/
2
}
// #endif
},
methods
:
{
/**
* @param {Object} item
* 小于 10 在前面加个 0
*/
lessThanTen
(
item
)
{
return
item
<
10
?
'0'
+
item
:
item
},
/**
* 解析时分秒字符串,例如:00:00:00
* @param {String} timeString
*/
parseTimeType
(
timeString
)
{
if
(
timeString
)
{
let
timeArr
=
timeString
.
split
(
':'
)
this
.
hour
=
Number
(
timeArr
[
0
])
this
.
minute
=
Number
(
timeArr
[
1
])
this
.
second
=
Number
(
timeArr
[
2
])
}
},
/**
* 解析选择器初始值,类型可以是字符串、时间戳,例如:2000-10-02、'08:30:00'、 1610695109000
* @param {String | Number} datetime
*/
initPickerValue
(
datetime
)
{
let
defaultValue
=
null
if
(
datetime
)
{
defaultValue
=
this
.
compareValueWithStartAndEnd
(
datetime
,
this
.
start
,
this
.
end
)
}
else
{
defaultValue
=
Date
.
now
()
defaultValue
=
this
.
compareValueWithStartAndEnd
(
defaultValue
,
this
.
start
,
this
.
end
)
}
this
.
parseValue
(
defaultValue
)
},
/**
* 初始值规则:
* - 用户设置初始值 value
* - 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start
* - 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start
* - 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end
* - 无起始终止时间,则初始值为 value
* - 无初始值 value,则初始值为当前本地时间 Date.now()
* @param {Object} value
* @param {Object} dateBase
*/
compareValueWithStartAndEnd
(
value
,
start
,
end
)
{
let
winner
=
null
value
=
this
.
superTimeStamp
(
value
)
start
=
this
.
superTimeStamp
(
start
)
end
=
this
.
superTimeStamp
(
end
)
if
(
start
&&
end
)
{
if
(
value
<
start
)
{
winner
=
new
Date
(
start
)
}
else
if
(
value
>
end
)
{
winner
=
new
Date
(
end
)
}
else
{
winner
=
new
Date
(
value
)
}
}
else
if
(
start
&&
!
end
)
{
winner
=
start
<=
value
?
new
Date
(
value
)
:
new
Date
(
start
)
}
else
if
(
!
start
&&
end
)
{
winner
=
value
<=
end
?
new
Date
(
value
)
:
new
Date
(
end
)
}
else
{
winner
=
new
Date
(
value
)
}
return
winner
},
/**
* 转换为可比较的时间戳,接受日期、时分秒、时间戳
* @param {Object} value
*/
superTimeStamp
(
value
)
{
let
dateBase
=
''
if
(
this
.
type
===
'time'
&&
value
&&
typeof
value
===
'string'
)
{
const
now
=
new
Date
()
const
year
=
now
.
getFullYear
()
const
month
=
now
.
getMonth
()
+
1
const
day
=
now
.
getDate
()
dateBase
=
year
+
'/'
+
month
+
'/'
+
day
+
' '
}
if
(
Number
(
value
))
{
value
=
parseInt
(
value
)
dateBase
=
0
}
return
this
.
createTimeStamp
(
dateBase
+
value
)
},
/**
* 解析默认值 value,字符串、时间戳
* @param {Object} defaultTime
*/
parseValue
(
value
)
{
if
(
!
value
)
{
return
}
if
(
this
.
type
===
'time'
&&
typeof
value
===
"string"
)
{
this
.
parseTimeType
(
value
)
}
else
{
let
defaultDate
=
null
defaultDate
=
new
Date
(
value
)
if
(
this
.
type
!==
'time'
)
{
this
.
year
=
defaultDate
.
getFullYear
()
this
.
month
=
defaultDate
.
getMonth
()
+
1
this
.
day
=
defaultDate
.
getDate
()
}
if
(
this
.
type
!==
'date'
)
{
this
.
hour
=
defaultDate
.
getHours
()
this
.
minute
=
defaultDate
.
getMinutes
()
this
.
second
=
defaultDate
.
getSeconds
()
}
}
if
(
this
.
hideSecond
)
{
this
.
second
=
0
}
},
/**
* 解析可选择时间范围 start、end,年月日字符串、时间戳
* @param {Object} defaultTime
*/
parseDatetimeRange
(
point
,
pointType
)
{
// 时间为空,则重置为初始值
if
(
!
point
)
{
if
(
pointType
===
'start'
)
{
this
.
startYear
=
1920
this
.
startMonth
=
1
this
.
startDay
=
1
this
.
startHour
=
0
this
.
startMinute
=
0
this
.
startSecond
=
0
}
if
(
pointType
===
'end'
)
{
this
.
endYear
=
2120
this
.
endMonth
=
12
this
.
endDay
=
31
this
.
endHour
=
23
this
.
endMinute
=
59
this
.
endSecond
=
59
}
return
}
if
(
this
.
type
===
'time'
)
{
const
pointArr
=
point
.
split
(
':'
)
this
[
pointType
+
'Hour'
]
=
Number
(
pointArr
[
0
])
this
[
pointType
+
'Minute'
]
=
Number
(
pointArr
[
1
])
this
[
pointType
+
'Second'
]
=
Number
(
pointArr
[
2
])
}
else
{
if
(
!
point
)
{
pointType
===
'start'
?
this
.
startYear
=
this
.
year
-
60
:
this
.
endYear
=
this
.
year
+
60
return
}
if
(
Number
(
point
))
{
point
=
parseInt
(
point
)
}
// datetime 的 end 没有时分秒, 则不限制
const
hasTime
=
/
[
0-9
]
:
[
0-9
]
/
if
(
this
.
type
===
'datetime'
&&
pointType
===
'end'
&&
typeof
point
===
'string'
&&
!
hasTime
.
test
(
point
))
{
point
=
point
+
' 23:59:59'
}
const
pointDate
=
new
Date
(
point
)
this
[
pointType
+
'Year'
]
=
pointDate
.
getFullYear
()
this
[
pointType
+
'Month'
]
=
pointDate
.
getMonth
()
+
1
this
[
pointType
+
'Day'
]
=
pointDate
.
getDate
()
if
(
this
.
type
===
'datetime'
)
{
this
[
pointType
+
'Hour'
]
=
pointDate
.
getHours
()
this
[
pointType
+
'Minute'
]
=
pointDate
.
getMinutes
()
this
[
pointType
+
'Second'
]
=
pointDate
.
getSeconds
()
}
}
},
// 获取 年、月、日、时、分、秒 当前可选范围
getCurrentRange
(
value
)
{
const
range
=
[]
for
(
let
i
=
this
[
'min'
+
this
.
capitalize
(
value
)];
i
<=
this
[
'max'
+
this
.
capitalize
(
value
)];
i
++
)
{
range
.
push
(
i
)
}
return
range
},
// 字符串首字母大写
capitalize
(
str
)
{
return
str
.
charAt
(
0
).
toUpperCase
()
+
str
.
slice
(
1
)
},
// 检查当前值是否在范围内,不在则当前值重置为可选范围第一项
checkValue
(
name
,
value
,
values
)
{
if
(
values
.
indexOf
(
value
)
===
-
1
)
{
this
[
name
]
=
values
[
0
]
}
},
// 每个月的实际天数
daysInMonth
(
year
,
month
)
{
// Use 1 for January, 2 for February, etc.
return
new
Date
(
year
,
month
,
0
).
getDate
();
},
/**
* 生成时间戳
* @param {Object} time
*/
createTimeStamp
(
time
)
{
if
(
!
time
)
return
if
(
typeof
time
===
"number"
)
{
return
time
}
else
{
time
=
time
.
replace
(
/-/g
,
'/'
)
if
(
this
.
type
===
'date'
)
{
time
=
time
+
' '
+
'00:00:00'
}
return
Date
.
parse
(
time
)
}
},
/**
* 生成日期或时间的字符串
*/
createDomSting
()
{
const
yymmdd
=
this
.
year
+
'-'
+
this
.
lessThanTen
(
this
.
month
)
+
'-'
+
this
.
lessThanTen
(
this
.
day
)
let
hhmmss
=
this
.
lessThanTen
(
this
.
hour
)
+
':'
+
this
.
lessThanTen
(
this
.
minute
)
if
(
!
this
.
hideSecond
)
{
hhmmss
=
hhmmss
+
':'
+
this
.
lessThanTen
(
this
.
second
)
}
if
(
this
.
type
===
'date'
)
{
return
yymmdd
}
else
if
(
this
.
type
===
'time'
)
{
return
hhmmss
}
else
{
return
yymmdd
+
' '
+
hhmmss
}
},
/**
* 初始化返回值,并抛出 change 事件
*/
initTime
(
emit
=
true
)
{
this
.
time
=
this
.
createDomSting
()
if
(
!
emit
)
return
if
(
this
.
returnType
===
'timestamp'
&&
this
.
type
!==
'time'
)
{
this
.
$emit
(
'change'
,
this
.
createTimeStamp
(
this
.
time
))
this
.
$emit
(
'input'
,
this
.
createTimeStamp
(
this
.
time
))
this
.
$emit
(
'update:modelValue'
,
this
.
createTimeStamp
(
this
.
time
))
}
else
{
this
.
$emit
(
'change'
,
this
.
time
)
this
.
$emit
(
'input'
,
this
.
time
)
this
.
$emit
(
'update:modelValue'
,
this
.
time
)
}
},
/**
* 用户选择日期或时间更新 data
* @param {Object} e
*/
bindDateChange
(
e
)
{
const
val
=
e
.
detail
.
value
this
.
year
=
this
.
years
[
val
[
0
]]
this
.
month
=
this
.
months
[
val
[
1
]]
this
.
day
=
this
.
days
[
val
[
2
]]
},
bindTimeChange
(
e
)
{
const
val
=
e
.
detail
.
value
this
.
hour
=
this
.
hours
[
val
[
0
]]
this
.
minute
=
this
.
minutes
[
val
[
1
]]
this
.
second
=
this
.
seconds
[
val
[
2
]]
},
/**
* 初始化弹出层
*/
initTimePicker
()
{
if
(
this
.
disabled
)
return
const
value
=
fixIosDateFormat
(
this
.
time
)
this
.
initPickerValue
(
value
)
this
.
visible
=
!
this
.
visible
},
/**
* 触发或关闭弹框
*/
tiggerTimePicker
(
e
)
{
this
.
visible
=
!
this
.
visible
},
/**
* 用户点击“清空”按钮,清空当前值
*/
clearTime
()
{
this
.
time
=
''
this
.
$emit
(
'change'
,
this
.
time
)
this
.
$emit
(
'input'
,
this
.
time
)
this
.
$emit
(
'update:modelValue'
,
this
.
time
)
this
.
tiggerTimePicker
()
},
/**
* 用户点击“确定”按钮
*/
setTime
()
{
this
.
initTime
()
this
.
tiggerTimePicker
()
}
}
}
</
script
>
<
style
lang=
"scss"
>
$uni-primary
:
#007aff
!
default
;
.uni-datetime-picker
{
/* #ifndef APP-NVUE */
/* width: 100%; */
/* #endif */
}
.uni-datetime-picker-view
{
height
:
130px
;
width
:
270px
;
/* #ifndef APP-NVUE */
cursor
:
pointer
;
/* #endif */
}
.uni-datetime-picker-item
{
height
:
50px
;
line-height
:
50px
;
text-align
:
center
;
font-size
:
14px
;
}
.uni-datetime-picker-btn
{
margin-top
:
60px
;
/* #ifndef APP-NVUE */
display
:
flex
;
cursor
:
pointer
;
/* #endif */
flex-direction
:
row
;
justify-content
:
space-between
;
}
.uni-datetime-picker-btn-text
{
font-size
:
14px
;
color
:
$uni-primary
;
}
.uni-datetime-picker-btn-group
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
}
.uni-datetime-picker-cancel
{
margin-right
:
30px
;
}
.uni-datetime-picker-mask
{
position
:
fixed
;
bottom
:
0px
;
top
:
0px
;
left
:
0px
;
right
:
0px
;
background-color
:
rgba
(
0
,
0
,
0
,
0
.4
);
transition-duration
:
0
.3s
;
z-index
:
998
;
}
.uni-datetime-picker-popup
{
border-radius
:
8px
;
padding
:
30px
;
width
:
270px
;
/* #ifdef APP-NVUE */
height
:
500px
;
/* #endif */
/* #ifdef APP-NVUE */
width
:
330px
;
/* #endif */
background-color
:
#fff
;
position
:
fixed
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
transition-duration
:
0
.3s
;
z-index
:
999
;
}
.fix-nvue-height
{
/* #ifdef APP-NVUE */
height
:
330px
;
/* #endif */
}
.uni-datetime-picker-time
{
color
:
grey
;
}
.uni-datetime-picker-column
{
height
:
50px
;
}
.uni-datetime-picker-timebox
{
border
:
1px
solid
#E5E5E5
;
border-radius
:
5px
;
padding
:
7px
10px
;
/* #ifndef APP-NVUE */
box-sizing
:
border-box
;
cursor
:
pointer
;
/* #endif */
}
.uni-datetime-picker-timebox-pointer
{
/* #ifndef APP-NVUE */
cursor
:
pointer
;
/* #endif */
}
.uni-datetime-picker-disabled
{
opacity
:
0
.4
;
/* #ifdef H5 */
cursor
:
not
-
allowed
!
important
;
/* #endif */
}
.uni-datetime-picker-text
{
font-size
:
14px
;
line-height
:
50px
}
.uni-datetime-picker-sign
{
position
:
absolute
;
top
:
53px
;
/* 减掉 10px 的元素高度,兼容nvue */
color
:
#999
;
/* #ifdef APP-NVUE */
font-size
:
16px
;
/* #endif */
}
.sign-left
{
left
:
86px
;
}
.sign-right
{
right
:
86px
;
}
.sign-center
{
left
:
135px
;
}
.uni-datetime-picker__container-box
{
position
:
relative
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
margin-top
:
40px
;
}
.time-hide-second
{
width
:
180px
;
}
</
style
>
uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
0 → 100644
View file @
970699b8
<
template
>
<view
class=
"uni-date"
>
<view
class=
"uni-date-editor"
@
click=
"show"
>
<slot>
<view
class=
"uni-date-editor--x"
:class=
"
{'uni-date-editor--x__disabled': disabled,'uni-date-x--border': border}">
<view
v-if=
"!isRange"
class=
"uni-date-x uni-date-single"
>
<uni-icons
class=
"icon-calendar"
type=
"calendar"
color=
"#c0c4cc"
size=
"22"
></uni-icons>
<view
class=
"uni-date__x-input"
>
{{
displayValue
||
singlePlaceholderText
}}
</view>
</view>
<view
v-else
class=
"uni-date-x uni-date-range"
>
<uni-icons
class=
"icon-calendar"
type=
"calendar"
color=
"#c0c4cc"
size=
"22"
></uni-icons>
<view
class=
"uni-date__x-input text-center"
>
{{
displayRangeValue
.
startDate
||
startPlaceholderText
}}
</view>
<view
class=
"range-separator"
>
{{
rangeSeparator
}}
</view>
<view
class=
"uni-date__x-input text-center"
>
{{
displayRangeValue
.
endDate
||
endPlaceholderText
}}
</view>
</view>
<view
v-if=
"showClearIcon"
class=
"uni-date__icon-clear"
@
click
.
stop=
"clear"
>
<uni-icons
type=
"clear"
color=
"#c0c4cc"
size=
"22"
></uni-icons>
</view>
</view>
</slot>
</view>
<view
v-show=
"pickerVisible"
class=
"uni-date-mask--pc"
@
click=
"close"
></view>
<view
v-if=
"!isPhone"
v-show=
"pickerVisible"
ref=
"datePicker"
class=
"uni-date-picker__container"
>
<view
v-if=
"!isRange"
class=
"uni-date-single--x"
:style=
"pickerPositionStyle"
>
<view
class=
"uni-popper__arrow"
></view>
<view
v-if=
"hasTime"
class=
"uni-date-changed popup-x-header"
>
<input
class=
"uni-date__input text-center"
type=
"text"
v-model=
"inputDate"
:placeholder=
"selectDateText"
/>
<time-picker
type=
"time"
v-model=
"pickerTime"
:border=
"false"
:disabled=
"!inputDate"
:start=
"timepickerStartTime"
:end=
"timepickerEndTime"
:hideSecond=
"hideSecond"
style=
"width: 100%;"
>
<input
class=
"uni-date__input text-center"
type=
"text"
v-model=
"pickerTime"
:placeholder=
"selectTimeText"
:disabled=
"!inputDate"
/>
</time-picker>
</view>
<Calendar
ref=
"pcSingle"
:showMonth=
"false"
:start-date=
"calendarRange.startDate"
:end-date=
"calendarRange.endDate"
:date=
"calendarDate"
@
change=
"singleChange"
:default-value=
"defaultValue"
style=
"padding: 0 8px;"
/>
<view
v-if=
"hasTime"
class=
"popup-x-footer"
>
<text
class=
"confirm-text"
@
click=
"confirmSingleChange"
>
{{
okText
}}
</text>
</view>
</view>
<view
v-else
class=
"uni-date-range--x"
:style=
"pickerPositionStyle"
>
<view
class=
"uni-popper__arrow"
></view>
<view
v-if=
"hasTime"
class=
"popup-x-header uni-date-changed"
>
<view
class=
"popup-x-header--datetime"
>
<input
class=
"uni-date__input uni-date-range__input"
type=
"text"
v-model=
"tempRange.startDate"
:placeholder=
"startDateText"
/>
<time-picker
type=
"time"
v-model=
"tempRange.startTime"
:start=
"timepickerStartTime"
:border=
"false"
:disabled=
"!tempRange.startDate"
:hideSecond=
"hideSecond"
>
<input
class=
"uni-date__input uni-date-range__input"
type=
"text"
v-model=
"tempRange.startTime"
:placeholder=
"startTimeText"
:disabled=
"!tempRange.startDate"
/>
</time-picker>
</view>
<uni-icons
type=
"arrowthinright"
color=
"#999"
style=
"line-height: 40px;"
></uni-icons>
<view
class=
"popup-x-header--datetime"
>
<input
class=
"uni-date__input uni-date-range__input"
type=
"text"
v-model=
"tempRange.endDate"
:placeholder=
"endDateText"
/>
<time-picker
type=
"time"
v-model=
"tempRange.endTime"
:end=
"timepickerEndTime"
:border=
"false"
:disabled=
"!tempRange.endDate"
:hideSecond=
"hideSecond"
>
<input
class=
"uni-date__input uni-date-range__input"
type=
"text"
v-model=
"tempRange.endTime"
:placeholder=
"endTimeText"
:disabled=
"!tempRange.endDate"
/>
</time-picker>
</view>
</view>
<view
class=
"popup-x-body"
>
<Calendar
ref=
"left"
:showMonth=
"false"
:start-date=
"calendarRange.startDate"
:end-date=
"calendarRange.endDate"
:range=
"true"
:pleStatus=
"endMultipleStatus"
@
change=
"leftChange"
@
firstEnterCale=
"updateRightCale"
style=
"padding: 0 8px;"
/>
<Calendar
ref=
"right"
:showMonth=
"false"
:start-date=
"calendarRange.startDate"
:end-date=
"calendarRange.endDate"
:range=
"true"
@
change=
"rightChange"
:pleStatus=
"startMultipleStatus"
@
firstEnterCale=
"updateLeftCale"
style=
"padding: 0 8px;border-left: 1px solid #F1F1F1;"
/>
</view>
<view
v-if=
"hasTime"
class=
"popup-x-footer"
>
<text
@
click=
"clear"
>
{{
clearText
}}
</text>
<text
class=
"confirm-text"
@
click=
"confirmRangeChange"
>
{{
okText
}}
</text>
</view>
</view>
</view>
<Calendar
v-if=
"isPhone"
ref=
"mobile"
:clearDate=
"false"
:date=
"calendarDate"
:defTime=
"mobileCalendarTime"
:start-date=
"calendarRange.startDate"
:end-date=
"calendarRange.endDate"
:selectableTimes=
"mobSelectableTime"
:startPlaceholder=
"startPlaceholder"
:endPlaceholder=
"endPlaceholder"
:default-value=
"defaultValue"
:pleStatus=
"endMultipleStatus"
:showMonth=
"false"
:range=
"isRange"
:hasTime=
"hasTime"
:insert=
"false"
:hideSecond=
"hideSecond"
@
confirm=
"mobileChange"
@
maskClose=
"close"
@
change=
"calendarClick"
/>
</view>
</
template
>
<
script
>
/**
* DatetimePicker 时间选择器
* @description 同时支持 PC 和移动端使用日历选择日期和日期范围
* @tutorial https://ext.dcloud.net.cn/plugin?id=3962
* @property {String} type 选择器类型
* @property {String|Number|Array|Date} value 绑定值
* @property {String} placeholder 单选择时的占位内容
* @property {String} start 起始时间
* @property {String} end 终止时间
* @property {String} start-placeholder 范围选择时开始日期的占位内容
* @property {String} end-placeholder 范围选择时结束日期的占位内容
* @property {String} range-separator 选择范围时的分隔符
* @property {Boolean} border = [true|false] 是否有边框
* @property {Boolean} disabled = [true|false] 是否禁用
* @property {Boolean} clearIcon = [true|false] 是否显示清除按钮(仅PC端适用)
* @property {[String} defaultValue 选择器打开时默认显示的时间
* @event {Function} change 确定日期时触发的事件
* @event {Function} maskClick 点击遮罩层触发的事件
* @event {Function} show 打开弹出层
* @event {Function} close 关闭弹出层
* @event {Function} clear 清除上次选中的状态和值
**/
import
Calendar
from
'./calendar.vue'
import
TimePicker
from
'./time-picker.vue'
import
{
initVueI18n
}
from
'@dcloudio/uni-i18n'
import
i18nMessages
from
'./i18n/index.js'
import
{
getDateTime
,
getDate
,
getTime
,
getDefaultSecond
,
dateCompare
,
checkDate
,
fixIosDateFormat
}
from
'./util'
export
default
{
name
:
'UniDatetimePicker'
,
options
:
{
// #ifdef MP-TOUTIAO
virtualHost
:
false
,
// #endif
// #ifndef MP-TOUTIAO
virtualHost
:
true
// #endif
},
components
:
{
Calendar
,
TimePicker
},
data
()
{
return
{
isRange
:
false
,
hasTime
:
false
,
displayValue
:
''
,
inputDate
:
''
,
calendarDate
:
''
,
pickerTime
:
''
,
calendarRange
:
{
startDate
:
''
,
startTime
:
''
,
endDate
:
''
,
endTime
:
''
},
displayRangeValue
:
{
startDate
:
''
,
endDate
:
''
,
},
tempRange
:
{
startDate
:
''
,
startTime
:
''
,
endDate
:
''
,
endTime
:
''
},
// 左右日历同步数据
startMultipleStatus
:
{
before
:
''
,
after
:
''
,
data
:
[],
fulldate
:
''
},
endMultipleStatus
:
{
before
:
''
,
after
:
''
,
data
:
[],
fulldate
:
''
},
pickerVisible
:
false
,
pickerPositionStyle
:
null
,
isEmitValue
:
false
,
isPhone
:
false
,
isFirstShow
:
true
,
i18nT
:
()
=>
{}
}
},
props
:
{
type
:
{
type
:
String
,
default
:
'datetime'
},
value
:
{
type
:
[
String
,
Number
,
Array
,
Date
],
default
:
''
},
modelValue
:
{
type
:
[
String
,
Number
,
Array
,
Date
],
default
:
''
},
start
:
{
type
:
[
Number
,
String
],
default
:
''
},
end
:
{
type
:
[
Number
,
String
],
default
:
''
},
returnType
:
{
type
:
String
,
default
:
'string'
},
placeholder
:
{
type
:
String
,
default
:
''
},
startPlaceholder
:
{
type
:
String
,
default
:
''
},
endPlaceholder
:
{
type
:
String
,
default
:
''
},
rangeSeparator
:
{
type
:
String
,
default
:
'-'
},
border
:
{
type
:
[
Boolean
],
default
:
true
},
disabled
:
{
type
:
[
Boolean
],
default
:
false
},
clearIcon
:
{
type
:
[
Boolean
],
default
:
true
},
hideSecond
:
{
type
:
[
Boolean
],
default
:
false
},
defaultValue
:
{
type
:
[
String
,
Object
,
Array
],
default
:
''
}
},
watch
:
{
type
:
{
immediate
:
true
,
handler
(
newVal
)
{
this
.
hasTime
=
newVal
.
indexOf
(
'time'
)
!==
-
1
this
.
isRange
=
newVal
.
indexOf
(
'range'
)
!==
-
1
}
},
// #ifndef VUE3
value
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
this
.
isEmitValue
)
{
this
.
isEmitValue
=
false
return
}
this
.
initPicker
(
newVal
)
}
},
// #endif
// #ifdef VUE3
modelValue
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
this
.
isEmitValue
)
{
this
.
isEmitValue
=
false
return
}
this
.
initPicker
(
newVal
)
}
},
// #endif
start
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
!
newVal
)
return
this
.
calendarRange
.
startDate
=
getDate
(
newVal
)
if
(
this
.
hasTime
)
{
this
.
calendarRange
.
startTime
=
getTime
(
newVal
)
}
}
},
end
:
{
immediate
:
true
,
handler
(
newVal
)
{
if
(
!
newVal
)
return
this
.
calendarRange
.
endDate
=
getDate
(
newVal
)
if
(
this
.
hasTime
)
{
this
.
calendarRange
.
endTime
=
getTime
(
newVal
,
this
.
hideSecond
)
}
}
},
},
computed
:
{
timepickerStartTime
()
{
const
activeDate
=
this
.
isRange
?
this
.
tempRange
.
startDate
:
this
.
inputDate
return
activeDate
===
this
.
calendarRange
.
startDate
?
this
.
calendarRange
.
startTime
:
''
},
timepickerEndTime
()
{
const
activeDate
=
this
.
isRange
?
this
.
tempRange
.
endDate
:
this
.
inputDate
return
activeDate
===
this
.
calendarRange
.
endDate
?
this
.
calendarRange
.
endTime
:
''
},
mobileCalendarTime
()
{
const
timeRange
=
{
start
:
this
.
tempRange
.
startTime
,
end
:
this
.
tempRange
.
endTime
}
return
this
.
isRange
?
timeRange
:
this
.
pickerTime
},
mobSelectableTime
()
{
return
{
start
:
this
.
calendarRange
.
startTime
,
end
:
this
.
calendarRange
.
endTime
}
},
datePopupWidth
()
{
// todo
return
this
.
isRange
?
653
:
301
},
/**
* for i18n
*/
singlePlaceholderText
()
{
return
this
.
placeholder
||
(
this
.
type
===
'date'
?
this
.
selectDateText
:
this
.
selectDateTimeText
)
},
startPlaceholderText
()
{
return
this
.
startPlaceholder
||
this
.
startDateText
},
endPlaceholderText
()
{
return
this
.
endPlaceholder
||
this
.
endDateText
},
selectDateText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.selectDate"
)
},
selectDateTimeText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.selectDateTime"
)
},
selectTimeText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.selectTime"
)
},
startDateText
()
{
return
this
.
startPlaceholder
||
this
.
i18nT
(
"uni-datetime-picker.startDate"
)
},
startTimeText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.startTime"
)
},
endDateText
()
{
return
this
.
endPlaceholder
||
this
.
i18nT
(
"uni-datetime-picker.endDate"
)
},
endTimeText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.endTime"
)
},
okText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.ok"
)
},
clearText
()
{
return
this
.
i18nT
(
"uni-datetime-picker.clear"
)
},
showClearIcon
()
{
return
this
.
clearIcon
&&
!
this
.
disabled
&&
(
this
.
displayValue
||
(
this
.
displayRangeValue
.
startDate
&&
this
.
displayRangeValue
.
endDate
))
}
},
created
()
{
this
.
initI18nT
()
this
.
platform
()
},
methods
:
{
initI18nT
()
{
const
vueI18n
=
initVueI18n
(
i18nMessages
)
this
.
i18nT
=
vueI18n
.
t
},
initPicker
(
newVal
)
{
if
((
!
newVal
&&
!
this
.
defaultValue
)
||
Array
.
isArray
(
newVal
)
&&
!
newVal
.
length
)
{
this
.
$nextTick
(()
=>
{
this
.
clear
(
false
)
})
return
}
if
(
!
Array
.
isArray
(
newVal
)
&&
!
this
.
isRange
)
{
if
(
newVal
)
{
this
.
displayValue
=
this
.
inputDate
=
this
.
calendarDate
=
getDate
(
newVal
)
if
(
this
.
hasTime
)
{
this
.
pickerTime
=
getTime
(
newVal
,
this
.
hideSecond
)
this
.
displayValue
=
`
${
this
.
displayValue
}
${
this
.
pickerTime
}
`
}
}
else
if
(
this
.
defaultValue
)
{
this
.
inputDate
=
this
.
calendarDate
=
getDate
(
this
.
defaultValue
)
if
(
this
.
hasTime
)
{
this
.
pickerTime
=
getTime
(
this
.
defaultValue
,
this
.
hideSecond
)
}
}
}
else
{
const
[
before
,
after
]
=
newVal
if
(
!
before
&&
!
after
)
return
const
beforeDate
=
getDate
(
before
)
const
beforeTime
=
getTime
(
before
,
this
.
hideSecond
)
const
afterDate
=
getDate
(
after
)
const
afterTime
=
getTime
(
after
,
this
.
hideSecond
)
const
startDate
=
beforeDate
const
endDate
=
afterDate
this
.
displayRangeValue
.
startDate
=
this
.
tempRange
.
startDate
=
startDate
this
.
displayRangeValue
.
endDate
=
this
.
tempRange
.
endDate
=
endDate
if
(
this
.
hasTime
)
{
this
.
displayRangeValue
.
startDate
=
`
${
beforeDate
}
${
beforeTime
}
`
this
.
displayRangeValue
.
endDate
=
`
${
afterDate
}
${
afterTime
}
`
this
.
tempRange
.
startTime
=
beforeTime
this
.
tempRange
.
endTime
=
afterTime
}
const
defaultRange
=
{
before
:
beforeDate
,
after
:
afterDate
}
this
.
startMultipleStatus
=
Object
.
assign
({},
this
.
startMultipleStatus
,
defaultRange
,
{
which
:
'right'
})
this
.
endMultipleStatus
=
Object
.
assign
({},
this
.
endMultipleStatus
,
defaultRange
,
{
which
:
'left'
})
}
},
updateLeftCale
(
e
)
{
const
left
=
this
.
$refs
.
left
// 设置范围选
left
.
cale
.
setHoverMultiple
(
e
.
after
)
left
.
setDate
(
this
.
$refs
.
left
.
nowDate
.
fullDate
)
},
updateRightCale
(
e
)
{
const
right
=
this
.
$refs
.
right
// 设置范围选
right
.
cale
.
setHoverMultiple
(
e
.
after
)
right
.
setDate
(
this
.
$refs
.
right
.
nowDate
.
fullDate
)
},
platform
()
{
if
(
typeof
navigator
!==
"undefined"
)
{
this
.
isPhone
=
navigator
.
userAgent
.
toLowerCase
().
indexOf
(
'mobile'
)
!==
-
1
return
}
// #ifdef MP-WEIXIN
const
{
windowWidth
}
=
uni
.
getWindowInfo
()
// #endif
// #ifndef MP-WEIXIN
const
{
windowWidth
}
=
uni
.
getSystemInfoSync
()
// #endif
this
.
isPhone
=
windowWidth
<=
500
this
.
windowWidth
=
windowWidth
},
show
()
{
this
.
$emit
(
"show"
)
if
(
this
.
disabled
)
{
return
}
this
.
platform
()
if
(
this
.
isPhone
)
{
setTimeout
(()
=>
{
this
.
$refs
.
mobile
.
open
()
},
0
);
return
}
this
.
pickerPositionStyle
=
{
top
:
'10px'
}
const
dateEditor
=
uni
.
createSelectorQuery
().
in
(
this
).
select
(
".uni-date-editor"
)
dateEditor
.
boundingClientRect
(
rect
=>
{
if
(
this
.
windowWidth
-
rect
.
left
<
this
.
datePopupWidth
)
{
this
.
pickerPositionStyle
.
right
=
0
}
}).
exec
()
setTimeout
(()
=>
{
this
.
pickerVisible
=
!
this
.
pickerVisible
if
(
!
this
.
isPhone
&&
this
.
isRange
&&
this
.
isFirstShow
)
{
this
.
isFirstShow
=
false
const
{
startDate
,
endDate
}
=
this
.
calendarRange
if
(
startDate
&&
endDate
)
{
if
(
this
.
diffDate
(
startDate
,
endDate
)
<
30
)
{
this
.
$refs
.
right
.
changeMonth
(
'pre'
)
}
}
else
{
// this.$refs.right.changeMonth('next')
if
(
this
.
isPhone
)
{
this
.
$refs
.
right
.
cale
.
lastHover
=
false
;
}
}
}
},
50
)
},
close
()
{
setTimeout
(()
=>
{
this
.
pickerVisible
=
false
this
.
$emit
(
'maskClick'
,
this
.
value
)
this
.
$refs
.
mobile
&&
this
.
$refs
.
mobile
.
close
()
},
20
)
},
setEmit
(
value
)
{
if
(
this
.
returnType
===
"timestamp"
||
this
.
returnType
===
"date"
)
{
if
(
!
Array
.
isArray
(
value
))
{
if
(
!
this
.
hasTime
)
{
value
=
value
+
' '
+
'00:00:00'
}
value
=
this
.
createTimestamp
(
value
)
if
(
this
.
returnType
===
"date"
)
{
value
=
new
Date
(
value
)
}
}
else
{
if
(
!
this
.
hasTime
)
{
value
[
0
]
=
value
[
0
]
+
' '
+
'00:00:00'
value
[
1
]
=
value
[
1
]
+
' '
+
'00:00:00'
}
value
[
0
]
=
this
.
createTimestamp
(
value
[
0
])
value
[
1
]
=
this
.
createTimestamp
(
value
[
1
])
if
(
this
.
returnType
===
"date"
)
{
value
[
0
]
=
new
Date
(
value
[
0
])
value
[
1
]
=
new
Date
(
value
[
1
])
}
}
}
this
.
$emit
(
'update:modelValue'
,
value
)
this
.
$emit
(
'input'
,
value
)
this
.
$emit
(
'change'
,
value
)
this
.
isEmitValue
=
true
},
createTimestamp
(
date
)
{
date
=
fixIosDateFormat
(
date
)
return
Date
.
parse
(
new
Date
(
date
))
},
singleChange
(
e
)
{
this
.
calendarDate
=
this
.
inputDate
=
e
.
fulldate
if
(
this
.
hasTime
)
return
this
.
confirmSingleChange
()
},
confirmSingleChange
()
{
if
(
!
checkDate
(
this
.
inputDate
))
{
const
now
=
new
Date
()
this
.
calendarDate
=
this
.
inputDate
=
getDate
(
now
)
this
.
pickerTime
=
getTime
(
now
,
this
.
hideSecond
)
}
let
startLaterInputDate
=
false
let
startDate
,
startTime
if
(
this
.
start
)
{
let
startString
=
this
.
start
if
(
typeof
this
.
start
===
'number'
)
{
startString
=
getDateTime
(
this
.
start
,
this
.
hideSecond
)
}
[
startDate
,
startTime
]
=
startString
.
split
(
' '
)
if
(
this
.
start
&&
!
dateCompare
(
startDate
,
this
.
inputDate
))
{
startLaterInputDate
=
true
this
.
inputDate
=
startDate
}
}
let
endEarlierInputDate
=
false
let
endDate
,
endTime
if
(
this
.
end
)
{
let
endString
=
this
.
end
if
(
typeof
this
.
end
===
'number'
)
{
endString
=
getDateTime
(
this
.
end
,
this
.
hideSecond
)
}
[
endDate
,
endTime
]
=
endString
.
split
(
' '
)
if
(
this
.
end
&&
!
dateCompare
(
this
.
inputDate
,
endDate
))
{
endEarlierInputDate
=
true
this
.
inputDate
=
endDate
}
}
if
(
this
.
hasTime
)
{
if
(
startLaterInputDate
)
{
this
.
pickerTime
=
startTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
if
(
endEarlierInputDate
)
{
this
.
pickerTime
=
endTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
if
(
!
this
.
pickerTime
)
{
this
.
pickerTime
=
getTime
(
Date
.
now
(),
this
.
hideSecond
)
}
this
.
displayValue
=
`
${
this
.
inputDate
}
${
this
.
pickerTime
}
`
}
else
{
this
.
displayValue
=
this
.
inputDate
}
this
.
setEmit
(
this
.
displayValue
)
this
.
pickerVisible
=
false
},
leftChange
(
e
)
{
const
{
before
,
after
}
=
e
.
range
this
.
rangeChange
(
before
,
after
)
const
obj
=
{
before
:
e
.
range
.
before
,
after
:
e
.
range
.
after
,
data
:
e
.
range
.
data
,
fulldate
:
e
.
fulldate
}
this
.
startMultipleStatus
=
Object
.
assign
({},
this
.
startMultipleStatus
,
obj
)
this
.
$emit
(
'calendarClick'
,
e
)
},
rightChange
(
e
)
{
const
{
before
,
after
}
=
e
.
range
this
.
rangeChange
(
before
,
after
)
const
obj
=
{
before
:
e
.
range
.
before
,
after
:
e
.
range
.
after
,
data
:
e
.
range
.
data
,
fulldate
:
e
.
fulldate
}
this
.
endMultipleStatus
=
Object
.
assign
({},
this
.
endMultipleStatus
,
obj
)
this
.
$emit
(
'calendarClick'
,
e
)
},
mobileChange
(
e
)
{
if
(
this
.
isRange
)
{
const
{
before
,
after
}
=
e
.
range
if
(
!
before
)
{
return
;
}
this
.
handleStartAndEnd
(
before
,
after
,
true
)
if
(
this
.
hasTime
)
{
const
{
startTime
,
endTime
}
=
e
.
timeRange
this
.
tempRange
.
startTime
=
startTime
this
.
tempRange
.
endTime
=
endTime
}
this
.
confirmRangeChange
()
}
else
{
if
(
this
.
hasTime
)
{
this
.
displayValue
=
e
.
fulldate
+
' '
+
e
.
time
}
else
{
this
.
displayValue
=
e
.
fulldate
}
this
.
setEmit
(
this
.
displayValue
)
this
.
calendarDate
=
this
.
displayValue
;
}
this
.
$refs
.
mobile
.
close
()
},
rangeChange
(
before
,
after
)
{
if
(
!
(
before
&&
after
))
return
this
.
handleStartAndEnd
(
before
,
after
,
true
)
if
(
this
.
hasTime
)
return
this
.
confirmRangeChange
()
},
confirmRangeChange
()
{
if
(
!
this
.
tempRange
.
startDate
||
!
this
.
tempRange
.
endDate
)
{
this
.
pickerVisible
=
false
return
}
if
(
!
checkDate
(
this
.
tempRange
.
startDate
))
{
this
.
tempRange
.
startDate
=
getDate
(
Date
.
now
())
}
if
(
!
checkDate
(
this
.
tempRange
.
endDate
))
{
this
.
tempRange
.
endDate
=
getDate
(
Date
.
now
())
}
let
start
,
end
let
startDateLaterRangeStartDate
=
false
let
startDateLaterRangeEndDate
=
false
let
startDate
,
startTime
let
compareStartDateString
=
this
.
tempRange
.
startDate
let
compareEndDateString
=
this
.
tempRange
.
endDate
if
(
this
.
hasTime
)
{
compareStartDateString
=
`
${
this
.
tempRange
.
startDate
}
${
this
.
tempRange
.
startTime
}
`
compareEndDateString
=
`
${
this
.
tempRange
.
endDate
}
${
this
.
tempRange
.
endTime
}
`
}
if
(
this
.
start
)
{
let
startString
=
this
.
start
if
(
typeof
this
.
start
===
'number'
)
{
startString
=
getDateTime
(
this
.
start
,
this
.
hideSecond
)
}
[
startDate
,
startTime
]
=
startString
.
split
(
' '
)
if
(
this
.
start
&&
!
dateCompare
(
this
.
start
,
compareStartDateString
))
{
startDateLaterRangeStartDate
=
true
this
.
tempRange
.
startDate
=
startDate
}
if
(
this
.
start
&&
!
dateCompare
(
this
.
start
,
compareEndDateString
))
{
startDateLaterRangeEndDate
=
true
this
.
tempRange
.
endDate
=
startDate
}
}
let
endDateEarlierRangeStartDate
=
false
let
endDateEarlierRangeEndDate
=
false
let
endDate
,
endTime
if
(
this
.
end
)
{
let
endString
=
this
.
end
if
(
typeof
this
.
end
===
'number'
)
{
endString
=
getDateTime
(
this
.
end
,
this
.
hideSecond
)
}
[
endDate
,
endTime
]
=
endString
.
split
(
' '
)
if
(
this
.
end
&&
!
dateCompare
(
compareStartDateString
,
this
.
end
))
{
endDateEarlierRangeStartDate
=
true
this
.
tempRange
.
startDate
=
endDate
}
if
(
this
.
end
&&
!
dateCompare
(
compareEndDateString
,
this
.
end
))
{
endDateEarlierRangeEndDate
=
true
this
.
tempRange
.
endDate
=
endDate
}
}
if
(
!
this
.
hasTime
)
{
start
=
this
.
displayRangeValue
.
startDate
=
this
.
tempRange
.
startDate
end
=
this
.
displayRangeValue
.
endDate
=
this
.
tempRange
.
endDate
}
else
{
if
(
startDateLaterRangeStartDate
)
{
this
.
tempRange
.
startTime
=
startTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
else
if
(
endDateEarlierRangeStartDate
)
{
this
.
tempRange
.
startTime
=
endTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
if
(
!
this
.
tempRange
.
startTime
)
{
this
.
tempRange
.
startTime
=
getTime
(
Date
.
now
(),
this
.
hideSecond
)
}
if
(
startDateLaterRangeEndDate
)
{
this
.
tempRange
.
endTime
=
startTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
else
if
(
endDateEarlierRangeEndDate
)
{
this
.
tempRange
.
endTime
=
endTime
||
getDefaultSecond
(
this
.
hideSecond
)
}
if
(
!
this
.
tempRange
.
endTime
)
{
this
.
tempRange
.
endTime
=
getTime
(
Date
.
now
(),
this
.
hideSecond
)
}
start
=
this
.
displayRangeValue
.
startDate
=
`
${
this
.
tempRange
.
startDate
}
${
this
.
tempRange
.
startTime
}
`
end
=
this
.
displayRangeValue
.
endDate
=
`
${
this
.
tempRange
.
endDate
}
${
this
.
tempRange
.
endTime
}
`
}
if
(
!
dateCompare
(
start
,
end
))
{
[
start
,
end
]
=
[
end
,
start
]
}
this
.
displayRangeValue
.
startDate
=
start
this
.
displayRangeValue
.
endDate
=
end
const
displayRange
=
[
start
,
end
]
this
.
setEmit
(
displayRange
)
this
.
pickerVisible
=
false
},
handleStartAndEnd
(
before
,
after
,
temp
=
false
)
{
if
(
!
before
)
return
if
(
!
after
)
after
=
before
;
const
type
=
temp
?
'tempRange'
:
'range'
const
isStartEarlierEnd
=
dateCompare
(
before
,
after
)
this
[
type
].
startDate
=
isStartEarlierEnd
?
before
:
after
this
[
type
].
endDate
=
isStartEarlierEnd
?
after
:
before
},
/**
* 比较时间大小
*/
dateCompare
(
startDate
,
endDate
)
{
// 计算截止时间
startDate
=
new
Date
(
startDate
.
replace
(
'-'
,
'/'
).
replace
(
'-'
,
'/'
))
// 计算详细项的截止时间
endDate
=
new
Date
(
endDate
.
replace
(
'-'
,
'/'
).
replace
(
'-'
,
'/'
))
return
startDate
<=
endDate
},
/**
* 比较时间差
*/
diffDate
(
startDate
,
endDate
)
{
// 计算截止时间
startDate
=
new
Date
(
startDate
.
replace
(
'-'
,
'/'
).
replace
(
'-'
,
'/'
))
// 计算详细项的截止时间
endDate
=
new
Date
(
endDate
.
replace
(
'-'
,
'/'
).
replace
(
'-'
,
'/'
))
const
diff
=
(
endDate
-
startDate
)
/
(
24
*
60
*
60
*
1000
)
return
Math
.
abs
(
diff
)
},
clear
(
needEmit
=
true
)
{
if
(
!
this
.
isRange
)
{
this
.
displayValue
=
''
this
.
inputDate
=
''
this
.
pickerTime
=
''
if
(
this
.
isPhone
)
{
this
.
$refs
.
mobile
&&
this
.
$refs
.
mobile
.
clearCalender
()
}
else
{
this
.
$refs
.
pcSingle
&&
this
.
$refs
.
pcSingle
.
clearCalender
()
}
if
(
needEmit
)
{
this
.
$emit
(
'change'
,
''
)
this
.
$emit
(
'input'
,
''
)
this
.
$emit
(
'update:modelValue'
,
''
)
}
}
else
{
this
.
displayRangeValue
.
startDate
=
''
this
.
displayRangeValue
.
endDate
=
''
this
.
tempRange
.
startDate
=
''
this
.
tempRange
.
startTime
=
''
this
.
tempRange
.
endDate
=
''
this
.
tempRange
.
endTime
=
''
if
(
this
.
isPhone
)
{
this
.
$refs
.
mobile
&&
this
.
$refs
.
mobile
.
clearCalender
()
}
else
{
this
.
$refs
.
left
&&
this
.
$refs
.
left
.
clearCalender
()
this
.
$refs
.
right
&&
this
.
$refs
.
right
.
clearCalender
()
this
.
$refs
.
right
&&
this
.
$refs
.
right
.
changeMonth
(
'next'
)
}
if
(
needEmit
)
{
this
.
$emit
(
'change'
,
[])
this
.
$emit
(
'input'
,
[])
this
.
$emit
(
'update:modelValue'
,
[])
}
}
},
calendarClick
(
e
)
{
this
.
$emit
(
'calendarClick'
,
e
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
$uni-primary
:
#007aff
!
default
;
.uni-date
{
width
:
100%
;
flex
:
1
;
}
.uni-date-x
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
center
;
border-radius
:
4px
;
background-color
:
#fff
;
color
:
#666
;
font-size
:
14px
;
flex
:
1
;
.icon-calendar
{
padding-left
:
3px
;
}
.range-separator
{
height
:
35px
;
/* #ifndef MP */
padding
:
0
2px
;
/* #endif */
line-height
:
35px
;
}
}
.uni-date-x--border
{
box-sizing
:
border-box
;
border-radius
:
4px
;
border
:
1px
solid
#e5e5e5
;
}
.uni-date-editor--x
{
display
:
flex
;
align-items
:
center
;
position
:
relative
;
}
.uni-date-editor--x
.uni-date__icon-clear
{
padding-right
:
3px
;
display
:
flex
;
align-items
:
center
;
/* #ifdef H5 */
cursor
:
pointer
;
/* #endif */
}
.uni-date__x-input
{
width
:
auto
;
height
:
35px
;
/* #ifndef MP */
padding-left
:
5px
;
/* #endif */
position
:
relative
;
flex
:
1
;
line-height
:
35px
;
font-size
:
14px
;
overflow
:
hidden
;
}
.text-center
{
text-align
:
center
;
}
.uni-date__input
{
height
:
40px
;
width
:
100%
;
line-height
:
40px
;
font-size
:
14px
;
}
.uni-date-range__input
{
text-align
:
center
;
max-width
:
142px
;
}
.uni-date-picker__container
{
position
:
relative
;
}
.uni-date-mask--pc
{
position
:
fixed
;
bottom
:
0px
;
top
:
0px
;
left
:
0px
;
right
:
0px
;
background-color
:
rgba
(
0
,
0
,
0
,
0
);
transition-duration
:
0
.3s
;
z-index
:
996
;
}
.uni-date-single--x
{
background-color
:
#fff
;
position
:
absolute
;
top
:
0
;
z-index
:
999
;
border
:
1px
solid
#EBEEF5
;
box-shadow
:
0
2px
12px
0
rgba
(
0
,
0
,
0
,
0
.1
);
border-radius
:
4px
;
}
.uni-date-range--x
{
background-color
:
#fff
;
position
:
absolute
;
top
:
0
;
z-index
:
999
;
border
:
1px
solid
#EBEEF5
;
box-shadow
:
0
2px
12px
0
rgba
(
0
,
0
,
0
,
0
.1
);
border-radius
:
4px
;
}
.uni-date-editor--x__disabled
{
opacity
:
0
.4
;
cursor
:
default
;
}
.uni-date-editor--logo
{
width
:
16px
;
height
:
16px
;
vertical-align
:
middle
;
}
/* 添加时间 */
.popup-x-header
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
}
.popup-x-header--datetime
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
flex
:
1
;
}
.popup-x-body
{
display
:
flex
;
}
.popup-x-footer
{
padding
:
0
15px
;
border-top-color
:
#F1F1F1
;
border-top-style
:
solid
;
border-top-width
:
1px
;
line-height
:
40px
;
text-align
:
right
;
color
:
#666
;
}
.popup-x-footer
text
:hover
{
color
:
$uni-primary
;
cursor
:
pointer
;
opacity
:
0
.8
;
}
.popup-x-footer
.confirm-text
{
margin-left
:
20px
;
color
:
$uni-primary
;
}
.uni-date-changed
{
text-align
:
center
;
color
:
#333
;
border-bottom-color
:
#F1F1F1
;
border-bottom-style
:
solid
;
border-bottom-width
:
1px
;
}
.uni-date-changed--time
text
{
height
:
50px
;
line-height
:
50px
;
}
.uni-date-changed
.uni-date-changed--time
{
flex
:
1
;
}
.uni-date-changed--time-date
{
color
:
#333
;
opacity
:
0
.6
;
}
.mr-50
{
margin-right
:
50px
;
}
/* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
.
uni-popper__arrow
,
.
uni-popper__arrow
:
:
after
{
position
:
absolute
;
display
:
block
;
width
:
0
;
height
:
0
;
border
:
6px
solid
transparent
;
border-top-width
:
0
;
}
.uni-popper__arrow
{
filter
:
drop-shadow
(
0
2px
12px
rgba
(
0
,
0
,
0
,
0
.03
));
top
:
-6px
;
left
:
10%
;
margin-right
:
3px
;
border-bottom-color
:
#EBEEF5
;
}
.
uni-popper__arrow
:
:
after
{
content
:
" "
;
top
:
1px
;
margin-left
:
-6px
;
border-bottom-color
:
#fff
;
}
</
style
>
uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
0 → 100644
View file @
970699b8
class
Calendar
{
constructor
({
selected
,
startDate
,
endDate
,
range
,
}
=
{})
{
// 当前日期
this
.
date
=
this
.
getDateObj
(
new
Date
())
// 当前初入日期
// 打点信息
this
.
selected
=
selected
||
[];
// 起始时间
this
.
startDate
=
startDate
// 终止时间
this
.
endDate
=
endDate
// 是否范围选择
this
.
range
=
range
// 多选状态
this
.
cleanMultipleStatus
()
// 每周日期
this
.
weeks
=
{}
this
.
lastHover
=
false
}
/**
* 设置日期
* @param {Object} date
*/
setDate
(
date
)
{
const
selectDate
=
this
.
getDateObj
(
date
)
this
.
getWeeks
(
selectDate
.
fullDate
)
}
/**
* 清理多选状态
*/
cleanMultipleStatus
()
{
this
.
multipleStatus
=
{
before
:
''
,
after
:
''
,
data
:
[]
}
}
setStartDate
(
startDate
)
{
this
.
startDate
=
startDate
}
setEndDate
(
endDate
)
{
this
.
endDate
=
endDate
}
getPreMonthObj
(
date
)
{
date
=
fixIosDateFormat
(
date
)
date
=
new
Date
(
date
)
const
oldMonth
=
date
.
getMonth
()
date
.
setMonth
(
oldMonth
-
1
)
const
newMonth
=
date
.
getMonth
()
if
(
oldMonth
!==
0
&&
newMonth
-
oldMonth
===
0
)
{
date
.
setMonth
(
newMonth
-
1
)
}
return
this
.
getDateObj
(
date
)
}
getNextMonthObj
(
date
)
{
date
=
fixIosDateFormat
(
date
)
date
=
new
Date
(
date
)
const
oldMonth
=
date
.
getMonth
()
date
.
setMonth
(
oldMonth
+
1
)
const
newMonth
=
date
.
getMonth
()
if
(
newMonth
-
oldMonth
>
1
)
{
date
.
setMonth
(
newMonth
-
1
)
}
return
this
.
getDateObj
(
date
)
}
/**
* 获取指定格式Date对象
*/
getDateObj
(
date
)
{
date
=
fixIosDateFormat
(
date
)
date
=
new
Date
(
date
)
return
{
fullDate
:
getDate
(
date
),
year
:
date
.
getFullYear
(),
month
:
addZero
(
date
.
getMonth
()
+
1
),
date
:
addZero
(
date
.
getDate
()),
day
:
date
.
getDay
()
}
}
/**
* 获取上一个月日期集合
*/
getPreMonthDays
(
amount
,
dateObj
)
{
const
result
=
[]
for
(
let
i
=
amount
-
1
;
i
>=
0
;
i
--
)
{
const
month
=
dateObj
.
month
-
1
result
.
push
({
date
:
new
Date
(
dateObj
.
year
,
month
,
-
i
).
getDate
(),
month
,
disable
:
true
})
}
return
result
}
/**
* 获取本月日期集合
*/
getCurrentMonthDays
(
amount
,
dateObj
)
{
const
result
=
[]
const
fullDate
=
this
.
date
.
fullDate
for
(
let
i
=
1
;
i
<=
amount
;
i
++
)
{
const
currentDate
=
`
${
dateObj
.
year
}
-
${
dateObj
.
month
}
-
${
addZero
(
i
)}
`
const
isToday
=
fullDate
===
currentDate
// 获取打点信息
const
info
=
this
.
selected
&&
this
.
selected
.
find
((
item
)
=>
{
if
(
this
.
dateEqual
(
currentDate
,
item
.
date
))
{
return
item
}
})
// 日期禁用
let
disableBefore
=
true
let
disableAfter
=
true
if
(
this
.
startDate
)
{
disableBefore
=
dateCompare
(
this
.
startDate
,
currentDate
)
}
if
(
this
.
endDate
)
{
disableAfter
=
dateCompare
(
currentDate
,
this
.
endDate
)
}
let
multiples
=
this
.
multipleStatus
.
data
let
multiplesStatus
=
-
1
if
(
this
.
range
&&
multiples
)
{
multiplesStatus
=
multiples
.
findIndex
((
item
)
=>
{
return
this
.
dateEqual
(
item
,
currentDate
)
})
}
const
checked
=
multiplesStatus
!==
-
1
result
.
push
({
fullDate
:
currentDate
,
year
:
dateObj
.
year
,
date
:
i
,
multiple
:
this
.
range
?
checked
:
false
,
beforeMultiple
:
this
.
isLogicBefore
(
currentDate
,
this
.
multipleStatus
.
before
,
this
.
multipleStatus
.
after
),
afterMultiple
:
this
.
isLogicAfter
(
currentDate
,
this
.
multipleStatus
.
before
,
this
.
multipleStatus
.
after
),
month
:
dateObj
.
month
,
disable
:
(
this
.
startDate
&&
!
dateCompare
(
this
.
startDate
,
currentDate
))
||
(
this
.
endDate
&&
!
dateCompare
(
currentDate
,
this
.
endDate
)),
isToday
,
userChecked
:
false
,
extraInfo
:
info
})
}
return
result
}
/**
* 获取下一个月日期集合
*/
_getNextMonthDays
(
amount
,
dateObj
)
{
const
result
=
[]
const
month
=
dateObj
.
month
+
1
for
(
let
i
=
1
;
i
<=
amount
;
i
++
)
{
result
.
push
({
date
:
i
,
month
,
disable
:
true
})
}
return
result
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo
(
date
)
{
if
(
!
date
)
{
date
=
new
Date
()
}
const
res
=
this
.
calendar
.
find
(
item
=>
item
.
fullDate
===
this
.
getDateObj
(
date
).
fullDate
)
return
res
?
res
:
this
.
getDateObj
(
date
)
}
/**
* 比较时间是否相等
*/
dateEqual
(
before
,
after
)
{
before
=
new
Date
(
fixIosDateFormat
(
before
))
after
=
new
Date
(
fixIosDateFormat
(
after
))
return
before
.
valueOf
()
===
after
.
valueOf
()
}
/**
* 比较真实起始日期
*/
isLogicBefore
(
currentDate
,
before
,
after
)
{
let
logicBefore
=
before
if
(
before
&&
after
)
{
logicBefore
=
dateCompare
(
before
,
after
)
?
before
:
after
}
return
this
.
dateEqual
(
logicBefore
,
currentDate
)
}
isLogicAfter
(
currentDate
,
before
,
after
)
{
let
logicAfter
=
after
if
(
before
&&
after
)
{
logicAfter
=
dateCompare
(
before
,
after
)
?
after
:
before
}
return
this
.
dateEqual
(
logicAfter
,
currentDate
)
}
/**
* 获取日期范围内所有日期
* @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
.
getDateObj
(
new
Date
(
parseInt
(
k
))).
fullDate
)
}
return
arr
}
/**
* 获取多选状态
*/
setMultiple
(
fullDate
)
{
if
(
!
this
.
range
)
return
let
{
before
,
after
}
=
this
.
multipleStatus
if
(
before
&&
after
)
{
if
(
!
this
.
lastHover
)
{
this
.
lastHover
=
true
return
}
this
.
multipleStatus
.
before
=
fullDate
this
.
multipleStatus
.
after
=
''
this
.
multipleStatus
.
data
=
[]
this
.
multipleStatus
.
fulldate
=
''
this
.
lastHover
=
false
}
else
{
if
(
!
before
)
{
this
.
multipleStatus
.
before
=
fullDate
this
.
multipleStatus
.
after
=
undefined
;
this
.
lastHover
=
false
}
else
{
this
.
multipleStatus
.
after
=
fullDate
if
(
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
.
lastHover
=
true
}
}
this
.
getWeeks
(
fullDate
)
}
/**
* 鼠标 hover 更新多选状态
*/
setHoverMultiple
(
fullDate
)
{
//抖音小程序点击会触发hover事件,需要避免一下
// #ifndef MP-TOUTIAO
if
(
!
this
.
range
||
this
.
lastHover
)
return
const
{
before
}
=
this
.
multipleStatus
if
(
!
before
)
{
this
.
multipleStatus
.
before
=
fullDate
}
else
{
this
.
multipleStatus
.
after
=
fullDate
if
(
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
.
getWeeks
(
fullDate
)
// #endif
}
/**
* 更新默认值多选状态
*/
setDefaultMultiple
(
before
,
after
)
{
this
.
multipleStatus
.
before
=
before
this
.
multipleStatus
.
after
=
after
if
(
before
&&
after
)
{
if
(
dateCompare
(
before
,
after
))
{
this
.
multipleStatus
.
data
=
this
.
geDateAll
(
before
,
after
);
this
.
getWeeks
(
after
)
}
else
{
this
.
multipleStatus
.
data
=
this
.
geDateAll
(
after
,
before
);
this
.
getWeeks
(
before
)
}
}
}
/**
* 获取每周数据
* @param {Object} dateData
*/
getWeeks
(
dateData
)
{
const
{
year
,
month
,
}
=
this
.
getDateObj
(
dateData
)
const
preMonthDayAmount
=
new
Date
(
year
,
month
-
1
,
1
).
getDay
()
const
preMonthDays
=
this
.
getPreMonthDays
(
preMonthDayAmount
,
this
.
getDateObj
(
dateData
))
const
currentMonthDayAmount
=
new
Date
(
year
,
month
,
0
).
getDate
()
const
currentMonthDays
=
this
.
getCurrentMonthDays
(
currentMonthDayAmount
,
this
.
getDateObj
(
dateData
))
const
nextMonthDayAmount
=
42
-
preMonthDayAmount
-
currentMonthDayAmount
const
nextMonthDays
=
this
.
_getNextMonthDays
(
nextMonthDayAmount
,
this
.
getDateObj
(
dateData
))
const
calendarDays
=
[...
preMonthDays
,
...
currentMonthDays
,
...
nextMonthDays
]
const
weeks
=
new
Array
(
6
)
for
(
let
i
=
0
;
i
<
calendarDays
.
length
;
i
++
)
{
const
index
=
Math
.
floor
(
i
/
7
)
if
(
!
weeks
[
index
])
{
weeks
[
index
]
=
new
Array
(
7
)
}
weeks
[
index
][
i
%
7
]
=
calendarDays
[
i
]
}
this
.
calendar
=
calendarDays
this
.
weeks
=
weeks
}
}
function
getDateTime
(
date
,
hideSecond
)
{
return
`
${
getDate
(
date
)}
${
getTime
(
date
,
hideSecond
)}
`
}
function
getDate
(
date
)
{
date
=
fixIosDateFormat
(
date
)
date
=
new
Date
(
date
)
const
year
=
date
.
getFullYear
()
const
month
=
date
.
getMonth
()
+
1
const
day
=
date
.
getDate
()
return
`
${
year
}
-
${
addZero
(
month
)}
-
${
addZero
(
day
)}
`
}
function
getTime
(
date
,
hideSecond
)
{
date
=
fixIosDateFormat
(
date
)
date
=
new
Date
(
date
)
const
hour
=
date
.
getHours
()
const
minute
=
date
.
getMinutes
()
const
second
=
date
.
getSeconds
()
return
hideSecond
?
`
${
addZero
(
hour
)}
:
${
addZero
(
minute
)}
`
:
`
${
addZero
(
hour
)}
:
${
addZero
(
minute
)}
:
${
addZero
(
second
)}
`
}
function
addZero
(
num
)
{
if
(
num
<
10
)
{
num
=
`0
${
num
}
`
}
return
num
}
function
getDefaultSecond
(
hideSecond
)
{
return
hideSecond
?
'00:00'
:
'00:00:00'
}
function
dateCompare
(
startDate
,
endDate
)
{
startDate
=
new
Date
(
fixIosDateFormat
(
startDate
))
endDate
=
new
Date
(
fixIosDateFormat
(
endDate
))
return
startDate
<=
endDate
}
function
checkDate
(
date
)
{
const
dateReg
=
/
((
19|20
)\d{2})(
-|
\/)\d{1,2}(
-|
\/)\d{1,2}
/g
return
date
.
match
(
dateReg
)
}
//ios低版本15及以下,无法匹配 没有 ’秒‘ 时的情况,所以需要在末尾 秒 加上 问号
const
dateTimeReg
=
/^
\d{4}
-
(
0
?[
1-9
]
|1
[
012
])
-
(
0
?[
1-9
]
|
[
12
][
0-9
]
|3
[
01
])(
[
0-5
]?[
0-9
]
:
[
0-5
]?[
0-9
](
:
[
0-5
]?[
0-9
])?)?
$/
;
function
fixIosDateFormat
(
value
)
{
if
(
typeof
value
===
'string'
&&
dateTimeReg
.
test
(
value
))
{
value
=
value
.
replace
(
/-/g
,
'/'
)
}
return
value
}
export
{
Calendar
,
getDateTime
,
getDate
,
getTime
,
addZero
,
getDefaultSecond
,
dateCompare
,
checkDate
,
fixIosDateFormat
}
uni_modules/uni-datetime-picker/package.json
0 → 100644
View file @
970699b8
{
"id"
:
"uni-datetime-picker"
,
"displayName"
:
"uni-datetime-picker 日期选择器"
,
"version"
:
"2.2.40"
,
"description"
:
"uni-datetime-picker 日期时间选择器,支持日历,支持范围选择"
,
"keywords"
:
[
"uni-datetime-picker"
,
"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"
,
"uni-icons"
],
"encrypt"
:
[],
"platforms"
:
{
"cloud"
:
{
"tcb"
:
"y"
,
"aliyun"
:
"y"
,
"alipay"
:
"n"
},
"client"
:
{
"App"
:
{
"app-vue"
:
"y"
,
"app-nvue"
:
"n"
,
"app-harmony"
:
"u"
,
"app-uvue"
:
"u"
},
"H5-mobile"
:
{
"Safari"
:
"y"
,
"Android Browser"
:
"y"
,
"微信浏览器(Android)"
:
"y"
,
"QQ浏览器(Android)"
:
"y"
},
"H5-pc"
:
{
"Chrome"
:
"y"
,
"IE"
:
"y"
,
"Edge"
:
"y"
,
"Firefox"
:
"y"
,
"Safari"
:
"y"
},
"小程序"
:
{
"微信"
:
"y"
,
"阿里"
:
"y"
,
"百度"
:
"y"
,
"字节跳动"
:
"y"
,
"QQ"
:
"y"
},
"快应用"
:
{
"华为"
:
"u"
,
"联盟"
:
"u"
},
"Vue"
:
{
"vue2"
:
"y"
,
"vue3"
:
"y"
}
}
}
}
}
uni_modules/uni-datetime-picker/readme.md
0 → 100644
View file @
970699b8
> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护`
## DatetimePicker 时间选择器
> **组件名:uni-datetime-picker**
> 代码块: `uDatetimePicker`
该组件的优势是,支持
**时间戳**
输入和输出(起始时间、终止时间也支持时间戳),可
**同时选择**
日期和时间。
若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
**_点击 picker 默认值规则:_**
-
若设置初始值 value, 会显示在 picker 显示框中
-
若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
\ No newline at end of file
uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
View file @
970699b8
<template>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
</template>
<script>
import { fontData, IconsDataItem } from './uniicons_file'
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number,String} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
</script>
<style scoped>
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
<template>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
</template>
<script>
import { fontData, IconsDataItem } from './uniicons_file'
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number,String} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
</script>
<style scoped>
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
</style>
uni_modules/uni-icons/components/uni-icons/uni-icons.vue
View file @
970699b8
<
template
>
<!-- #ifdef APP-NVUE -->
<text
:style=
"styleObj"
class=
"uni-icons"
@
click=
"_onClick"
>
{{
unicode
}}
</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text
:style=
"styleObj"
class=
"uni-icons"
:class=
"['uniui-'+type,customPrefix,customPrefix?type:'']"
@
click=
"_onClick"
>
<slot></slot>
</text>
<!-- #endif -->
</
template
>
<
script
>
import
{
fontData
}
from
'./uniicons_file_vue.js'
;
const
getVal
=
(
val
)
=>
{
const
reg
=
/^
[
0-9
]
*$/g
return
(
typeof
val
===
'number'
||
reg
.
test
(
val
))
?
val
+
'px'
:
val
;
}
// #ifdef APP-NVUE
var
domModule
=
weex
.
requireModule
(
'dom'
);
import
iconUrl
from
'./uniicons.ttf'
domModule
.
addRule
(
'fontFace'
,
{
'fontFamily'
:
"uniicons"
,
'src'
:
"url('"
+
iconUrl
+
"')"
});
// #endif
/**
* Icons 图标
* @description 用于展示 icons 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export
default
{
name
:
'UniIcons'
,
emits
:
[
'click'
],
props
:
{
type
:
{
type
:
String
,
default
:
''
},
color
:
{
type
:
String
,
default
:
'#333333'
},
size
:
{
type
:
[
Number
,
String
],
default
:
16
},
customPrefix
:
{
type
:
String
,
default
:
''
},
fontFamily
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
icons
:
fontData
}
},
computed
:
{
unicode
()
{
let
code
=
this
.
icons
.
find
(
v
=>
v
.
font_class
===
this
.
type
)
if
(
code
)
{
return
code
.
unicode
}
return
''
},
iconSize
()
{
return
getVal
(
this
.
size
)
},
styleObj
()
{
if
(
this
.
fontFamily
!==
''
)
{
return
`color:
${
this
.
color
}
; font-size:
${
this
.
iconSize
}
; font-family:
${
this
.
fontFamily
}
;`
}
return
`color:
${
this
.
color
}
; font-size:
${
this
.
iconSize
}
;`
}
},
methods
:
{
_onClick
()
{
this
.
$emit
(
'click'
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
/* #ifndef APP-NVUE */
@import
'./uniicons.css'
;
@font-face
{
font-family
:
uniicons
;
src
:
url('./uniicons.ttf')
;
}
/* #endif */
.uni-icons
{
font-family
:
uniicons
;
text-decoration
:
none
;
text-align
:
center
;
}
<
template
>
<!-- #ifdef APP-NVUE -->
<text
:style=
"styleObj"
class=
"uni-icons"
@
click=
"_onClick"
>
{{
unicode
}}
</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text
:style=
"styleObj"
class=
"uni-icons"
:class=
"['uniui-'+type,customPrefix,customPrefix?type:'']"
@
click=
"_onClick"
>
<slot></slot>
</text>
<!-- #endif -->
</
template
>
<
script
>
import
{
fontData
}
from
'./uniicons_file_vue.js'
;
const
getVal
=
(
val
)
=>
{
const
reg
=
/^
[
0-9
]
*$/g
return
(
typeof
val
===
'number'
||
reg
.
test
(
val
))
?
val
+
'px'
:
val
;
}
// #ifdef APP-NVUE
var
domModule
=
weex
.
requireModule
(
'dom'
);
import
iconUrl
from
'./uniicons.ttf'
domModule
.
addRule
(
'fontFace'
,
{
'fontFamily'
:
"uniicons"
,
'src'
:
"url('"
+
iconUrl
+
"')"
});
// #endif
/**
* Icons 图标
* @description 用于展示 icons 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export
default
{
name
:
'UniIcons'
,
emits
:
[
'click'
],
props
:
{
type
:
{
type
:
String
,
default
:
''
},
color
:
{
type
:
String
,
default
:
'#333333'
},
size
:
{
type
:
[
Number
,
String
],
default
:
16
},
customPrefix
:
{
type
:
String
,
default
:
''
},
fontFamily
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
icons
:
fontData
}
},
computed
:
{
unicode
()
{
let
code
=
this
.
icons
.
find
(
v
=>
v
.
font_class
===
this
.
type
)
if
(
code
)
{
return
code
.
unicode
}
return
''
},
iconSize
()
{
return
getVal
(
this
.
size
)
},
styleObj
()
{
if
(
this
.
fontFamily
!==
''
)
{
return
`color:
${
this
.
color
}
; font-size:
${
this
.
iconSize
}
; font-family:
${
this
.
fontFamily
}
;`
}
return
`color:
${
this
.
color
}
; font-size:
${
this
.
iconSize
}
;`
}
},
methods
:
{
_onClick
()
{
this
.
$emit
(
'click'
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
/* #ifndef APP-NVUE */
@import
'./uniicons.css'
;
@font-face
{
font-family
:
uniicons
;
src
:
url('./uniicons.ttf')
;
}
/* #endif */
.uni-icons
{
font-family
:
uniicons
;
text-decoration
:
none
;
text-align
:
center
;
}
</
style
>
uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
View file @
970699b8
export
type
IconsData
=
{
id
:
string
name
:
string
font_family
:
string
css_prefix_text
:
string
description
:
string
glyphs
:
Array
<
IconsDataItem
>
}
export
type
IconsDataItem
=
{
font_class
:
string
unicode
:
string
}
export
type
IconsData
=
{
id
:
string
name
:
string
font_family
:
string
css_prefix_text
:
string
description
:
string
glyphs
:
Array
<
IconsDataItem
>
}
export
type
IconsDataItem
=
{
font_class
:
string
unicode
:
string
}
export
const
fontData
=
[
{
"font_class"
:
"arrow-down"
,
...
...
@@ -659,6 +659,6 @@ export const fontData = [
"font_class"
:
"weixin"
,
"unicode"
:
"
\
ue691"
}
]
as
IconsDataItem
[]
]
as
IconsDataItem
[]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
View file @
970699b8
export
const
fontData
=
[
{
"font_class"
:
"arrow-down"
,
...
...
@@ -644,6 +644,6 @@ export const fontData = [
"font_class"
:
"weixin"
,
"unicode"
:
"
\
ue691"
}
]
]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment