mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'dev' into next
This commit is contained in:
commit
4eb36898e9
15
README.md
15
README.md
@ -2,14 +2,17 @@
|
||||
<img alt="logo" src="https://img.yzcdn.cn/vant/logo.png" width="120" height="120" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
|
||||
<h3 align="center" style="margin: 30px 0 35px;">Mobile UI Components built on Vue</h3>
|
||||
<h1 align="center">Vant</h1>
|
||||
|
||||
<p align="center">Mobile UI Components built on Vue</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/npm/v/vant.svg?style=for-the-badge" alt="npm version" />
|
||||
<img src="https://img.shields.io/github/workflow/status/youzan/vant/CI/dev?style=for-the-badge" alt="npm version" />
|
||||
<img src="https://img.shields.io/codecov/c/github/youzan/vant/dev.svg?style=for-the-badge&color=#4fc08d" alt="Coverage Status" />
|
||||
<img src="https://img.shields.io/npm/dm/vant.svg?style=for-the-badge&color=#4fc08d" alt="downloads" />
|
||||
<img src="https://img.badgesize.io/https://unpkg.com/vant/lib/vant.min.js?compression=gzip&style=for-the-badge&label=gzip%20size&color=#4fc08d" alt="Gzip Size" />
|
||||
<img src="https://img.shields.io/npm/v/vant.svg?style=flat-square" alt="npm version" />
|
||||
<img src="https://img.shields.io/github/workflow/status/youzan/vant/CI/dev?style=flat-square" alt="npm version" />
|
||||
<img src="https://img.shields.io/codecov/c/github/youzan/vant/dev.svg?style=flat-square&color=#4fc08d" alt="Coverage Status" />
|
||||
<img src="https://img.shields.io/npm/dm/vant.svg?style=flat-square&color=#4fc08d" alt="downloads" />
|
||||
<img src="https://img.shields.io/jsdelivr/npm/hm/vant?style=flat-square" alt="Jsdelivr Hits">
|
||||
<img src="https://img.badgesize.io/https://unpkg.com/vant/lib/vant.min.js?compression=gzip&style=flat-square&label=gzip%20size&color=#4fc08d" alt="Gzip Size" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
@ -1,14 +1,18 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://img.yzcdn.cn/vant/logo.png" width="120" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
<h3 align="center" style="margin: 30px 0 35px;">轻量、可靠的移动端 Vue 组件库</h3>
|
||||
|
||||
<h1 align="center">Vant</h1>
|
||||
|
||||
<p align="center">轻量、可靠的移动端 Vue 组件库</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/npm/v/vant.svg?style=for-the-badge" alt="npm version" />
|
||||
<img src="https://img.shields.io/github/workflow/status/youzan/vant/CI/dev?style=for-the-badge" alt="npm version" />
|
||||
<img src="https://img.shields.io/codecov/c/github/youzan/vant/dev.svg?style=for-the-badge&color=#4fc08d" alt="Coverage Status" />
|
||||
<img src="https://img.shields.io/npm/dm/vant.svg?style=for-the-badge&color=#4fc08d" alt="downloads" />
|
||||
<img src="https://img.badgesize.io/https://unpkg.com/vant/lib/vant.min.js?compression=gzip&style=for-the-badge&label=gzip%20size&color=#4fc08d" alt="Gzip Size" />
|
||||
<img src="https://img.shields.io/npm/v/vant.svg?style=flat-square" alt="npm version" />
|
||||
<img src="https://img.shields.io/github/workflow/status/youzan/vant/CI/dev?style=flat-square" alt="npm version" />
|
||||
<img src="https://img.shields.io/codecov/c/github/youzan/vant/dev.svg?style=flat-square&color=#4fc08d" alt="Coverage Status" />
|
||||
<img src="https://img.shields.io/npm/dm/vant.svg?style=flat-square&color=#4fc08d" alt="downloads" />
|
||||
<img src="https://img.shields.io/jsdelivr/npm/hm/vant?style=flat-square" alt="Jsdelivr Hits">
|
||||
<img src="https://img.badgesize.io/https://unpkg.com/vant/lib/vant.min.js?compression=gzip&style=flat-square&label=gzip%20size&color=#4fc08d" alt="Gzip Size" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
@ -10,6 +10,26 @@ Vant follows [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
|
||||
- Minor version:released every one to two months, including backwards compatible features.
|
||||
- Major version:including breaking changes and new features.
|
||||
|
||||
### [v2.9.1-beta.1](https://github.com/youzan/vant/compare/v2.9.0...v2.9.1-beta.1)
|
||||
|
||||
`2020-07-07`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Field: add clear-trigger prop [#6699](https://github.com/youzan/vant/issues/6699)
|
||||
- Search: add clear-trigger prop [#6700](https://github.com/youzan/vant/issues/6700)
|
||||
- Uploader: add preview-cover slot [#6707](https://github.com/youzan/vant/issues/6707)
|
||||
- Sku: improve message datetime picker [8d29e5](https://github.com/youzan/vant/commit/8d29e5c8c6df278800865596f285c17029150963) [7343e5](https://github.com/youzan/vant/commit/7343e55409900635a0e39063edb9f67493048a54)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: subtitle not updated in some cases [#6723](https://github.com/youzan/vant/issues/6723)
|
||||
- Checkbox: dynamic bind group [#6730](https://github.com/youzan/vant/issues/6730)
|
||||
- Image: memory leak during SSR [#6721](https://github.com/youzan/vant/issues/6721)
|
||||
- ImagePreview: swipeTo type should be optional [#6727](https://github.com/youzan/vant/issues/6727)
|
||||
- Picker: click during momentum case incorrect result [#6724](https://github.com/youzan/vant/issues/6724)
|
||||
- Popup: lock-scroll not work in some cases [#6698](https://github.com/youzan/vant/issues/6698)
|
||||
|
||||
### [v2.9.0](https://github.com/youzan/vant/compare/v2.8.7...v2.9.0)
|
||||
|
||||
`2020-07-03`
|
||||
|
@ -10,6 +10,26 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
|
||||
- 次版本号:每隔一至二个月发布,包含新特性和较大的功能更新,向下兼容。
|
||||
- 主版本号:发布时间不定,包含不兼容更新,预计下一个主版本会与 Vue 3.0 同期发布。
|
||||
|
||||
### [v2.9.1-beta.1](https://github.com/youzan/vant/compare/v2.9.0...v2.9.1-beta.1)
|
||||
|
||||
`2020-07-07`
|
||||
|
||||
**Feature**
|
||||
|
||||
- Field: 新增 clear-trigger 属性 [#6699](https://github.com/youzan/vant/issues/6699)
|
||||
- Search: 新增 clear-trigger 属性 [#6700](https://github.com/youzan/vant/issues/6700)
|
||||
- Uploader: 新增 preview-cover 插槽 [#6707](https://github.com/youzan/vant/issues/6707)
|
||||
- Sku: 优化留言栏时间选择交互 [8d29e5](https://github.com/youzan/vant/commit/8d29e5c8c6df278800865596f285c17029150963) [7343e5](https://github.com/youzan/vant/commit/7343e55409900635a0e39063edb9f67493048a54)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Calendar: 修复个别情况下日历标题不更新的问题 [#6723](https://github.com/youzan/vant/issues/6723)
|
||||
- Checkbox: 修复动态设置 bind-group 时不生效的问题 [#6730](https://github.com/youzan/vant/issues/6730)
|
||||
- Image: 修复 SSR 时 LazyLoad 属性存在内存泄露的问题 [#6721](https://github.com/youzan/vant/issues/6721)
|
||||
- ImagePreview: 修复 swipeTo 方法类型定义错误 [#6727](https://github.com/youzan/vant/issues/6727)
|
||||
- Picker: 修复惯性滚动过程中点击选项会导致选中结果错误的问题 [#6724](https://github.com/youzan/vant/issues/6724)
|
||||
- Popup: 修复 lock-scroll 在个别场景下不生效的问题 [#6698](https://github.com/youzan/vant/issues/6698)
|
||||
|
||||
### [v2.9.0](https://github.com/youzan/vant/compare/v2.8.7...v2.9.0)
|
||||
|
||||
`2020-07-03`
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vant",
|
||||
"version": "2.9.0",
|
||||
"version": "2.9.1-beta.1",
|
||||
"description": "Mobile UI Components built on Vue",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -40,8 +40,12 @@
|
||||
"url": "git@github.com:youzan/vant.git"
|
||||
},
|
||||
"keywords": [
|
||||
"ui",
|
||||
"vue",
|
||||
"component"
|
||||
"frontend",
|
||||
"mobile ui",
|
||||
"component",
|
||||
"components"
|
||||
],
|
||||
"author": "youzanfe",
|
||||
"license": "MIT",
|
||||
|
@ -10,6 +10,7 @@
|
||||
>
|
||||
<van-popup
|
||||
v-model="showArea"
|
||||
round
|
||||
slot="extra"
|
||||
position="bottom"
|
||||
get-container="body"
|
||||
|
@ -10,6 +10,7 @@
|
||||
>
|
||||
<van-calendar
|
||||
v-model="showCalendar"
|
||||
round
|
||||
slot="extra"
|
||||
get-container="body"
|
||||
@confirm="onConfirm"
|
||||
|
@ -10,6 +10,7 @@
|
||||
>
|
||||
<van-popup
|
||||
v-model="showPicker"
|
||||
round
|
||||
slot="extra"
|
||||
position="bottom"
|
||||
get-container="body"
|
||||
|
@ -10,6 +10,7 @@
|
||||
>
|
||||
<van-popup
|
||||
v-model="showPicker"
|
||||
round
|
||||
slot="extra"
|
||||
position="bottom"
|
||||
get-container="body"
|
||||
|
@ -30,6 +30,14 @@ export function ChildrenMixin(parent, options = {}) {
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
disableBindRelation(val) {
|
||||
if (!val) {
|
||||
this.bindRelation();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.bindRelation();
|
||||
},
|
||||
|
105
src/sku/components/SkuDateTimeField.js
Normal file
105
src/sku/components/SkuDateTimeField.js
Normal file
@ -0,0 +1,105 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { stringToDate, dateToString } from '../utils/time-helper';
|
||||
|
||||
// Components
|
||||
import Popup from '../../popup';
|
||||
import DateTimePicker from '../../datetime-picker';
|
||||
import Field from '../../field';
|
||||
|
||||
const namespace = createNamespace('sku-datetime-field');
|
||||
const createComponent = namespace[0];
|
||||
const t = namespace[2];
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
value: String,
|
||||
label: String,
|
||||
required: Boolean,
|
||||
placeholder: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'date',
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showDatePicker: false,
|
||||
currentDate: this.type === 'time' ? '' : new Date(),
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
switch (this.type) {
|
||||
case 'time':
|
||||
this.currentDate = val;
|
||||
break;
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
this.currentDate = stringToDate(val) || new Date();
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
title() {
|
||||
return t(`title.${this.type}`);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClick() {
|
||||
this.showDatePicker = true;
|
||||
},
|
||||
onConfirm(val) {
|
||||
let data = val;
|
||||
if (this.type !== 'time') {
|
||||
data = dateToString(val, this.type);
|
||||
}
|
||||
this.$emit('input', data);
|
||||
this.showDatePicker = false;
|
||||
},
|
||||
onCancel() {
|
||||
this.showDatePicker = false;
|
||||
},
|
||||
formatter(type, val) {
|
||||
const word = t(`format.${type}`);
|
||||
return `${val}${word}`;
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Field
|
||||
readonly
|
||||
is-link
|
||||
center
|
||||
value={this.value}
|
||||
label={this.label}
|
||||
required={this.required}
|
||||
placeholder={this.placeholder}
|
||||
onClick={this.onClick}
|
||||
>
|
||||
<Popup
|
||||
vModel={this.showDatePicker}
|
||||
round
|
||||
slot="extra"
|
||||
position="bottom"
|
||||
getContainer="body"
|
||||
>
|
||||
<DateTimePicker
|
||||
type={this.type}
|
||||
title={this.title}
|
||||
value={this.currentDate}
|
||||
formatter={this.formatter}
|
||||
onCancel={this.onCancel}
|
||||
onConfirm={this.onConfirm}
|
||||
/>
|
||||
</Popup>
|
||||
</Field>
|
||||
);
|
||||
},
|
||||
});
|
@ -2,11 +2,11 @@
|
||||
import { createNamespace } from '../../utils';
|
||||
|
||||
// Components
|
||||
import Icon from '../../icon';
|
||||
import Loading from '../../loading';
|
||||
import Uploader from '../../uploader';
|
||||
|
||||
const [createComponent, bem, t] = createNamespace('sku-img-uploader');
|
||||
const namespace = createNamespace('sku-img-uploader');
|
||||
const createComponent = namespace[0];
|
||||
const t = namespace[2];
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
@ -20,26 +20,32 @@ export default createComponent({
|
||||
|
||||
data() {
|
||||
return {
|
||||
// 正在上传的图片 base64
|
||||
paddingImg: '',
|
||||
uploadFail: false,
|
||||
fileList: [],
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
if (val) {
|
||||
this.fileList = [{ url: val, isImage: true }];
|
||||
} else {
|
||||
this.fileList = [];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
afterReadFile(file) {
|
||||
// 上传文件
|
||||
this.paddingImg = file.content;
|
||||
this.uploadFail = false;
|
||||
file.status = 'uploading';
|
||||
file.message = t('uploading');
|
||||
this.uploadImg(file.file, file.content)
|
||||
.then((img) => {
|
||||
file.status = 'done';
|
||||
this.$emit('input', img);
|
||||
this.$nextTick(() => {
|
||||
this.paddingImg = '';
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.uploadFail = true;
|
||||
file.status = 'failed';
|
||||
file.message = t('fail');
|
||||
});
|
||||
},
|
||||
|
||||
@ -47,68 +53,21 @@ export default createComponent({
|
||||
this.$toast(t('oversize', this.maxSize));
|
||||
},
|
||||
|
||||
genUploader(content, disabled = false) {
|
||||
return (
|
||||
<Uploader
|
||||
class={bem('uploader')}
|
||||
disabled={disabled}
|
||||
afterRead={this.afterReadFile}
|
||||
maxSize={this.maxSize * 1024 * 1024}
|
||||
onOversize={this.onOversize}
|
||||
>
|
||||
<div class={bem('img')}>{content}</div>
|
||||
</Uploader>
|
||||
);
|
||||
},
|
||||
|
||||
genMask() {
|
||||
return (
|
||||
<div class={bem('mask')}>
|
||||
{this.uploadFail ? (
|
||||
[
|
||||
<Icon name="warning-o" size="20px" />,
|
||||
<div class={bem('warn-text')} domPropsInnerHTML={t('fail')} />,
|
||||
]
|
||||
) : (
|
||||
<Loading type="spinner" size="20px" color="white" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
onDelete() {
|
||||
this.$emit('input', '');
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div class={bem()}>
|
||||
{this.value &&
|
||||
this.genUploader(
|
||||
[
|
||||
<img src={this.value} />,
|
||||
<Icon
|
||||
name="clear"
|
||||
class={bem('delete')}
|
||||
onClick={() => {
|
||||
this.$emit('input', '');
|
||||
}}
|
||||
/>,
|
||||
],
|
||||
true
|
||||
)}
|
||||
|
||||
{this.paddingImg &&
|
||||
this.genUploader(
|
||||
[<img src={this.paddingImg} />, this.genMask()],
|
||||
!this.uploadFail
|
||||
)}
|
||||
|
||||
{!this.value &&
|
||||
!this.paddingImg &&
|
||||
this.genUploader(
|
||||
<div class={bem('trigger')}>
|
||||
<Icon name="photograph" size="22px" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Uploader
|
||||
vModel={this.fileList}
|
||||
maxCount={1}
|
||||
afterRead={this.afterReadFile}
|
||||
maxSize={this.maxSize * 1024 * 1024}
|
||||
onOversize={this.onOversize}
|
||||
onDelete={this.onDelete}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -7,6 +7,7 @@ import { isNumeric } from '../../utils/validate/number';
|
||||
import Cell from '../../cell';
|
||||
import Field from '../../field';
|
||||
import SkuImgUploader from './SkuImgUploader';
|
||||
import SkuDateTimeField from './SkuDateTimeField';
|
||||
|
||||
const [createComponent, bem, t] = createNamespace('sku-messages');
|
||||
|
||||
@ -48,18 +49,14 @@ export default createComponent({
|
||||
if (message.type === 'id_no') {
|
||||
return 'text';
|
||||
}
|
||||
return message.datetime > 0 ? 'datetime-local' : message.type;
|
||||
return message.datetime > 0 ? 'datetime' : message.type;
|
||||
},
|
||||
|
||||
getMessages() {
|
||||
const messages = {};
|
||||
|
||||
this.messageValues.forEach((item, index) => {
|
||||
let { value } = item;
|
||||
if (this.messages[index].datetime > 0) {
|
||||
value = value.replace(/T/g, ' ');
|
||||
}
|
||||
messages[`message_${index}`] = value;
|
||||
messages[`message_${index}`] = item.value;
|
||||
});
|
||||
|
||||
return messages;
|
||||
@ -69,12 +66,8 @@ export default createComponent({
|
||||
const messages = {};
|
||||
|
||||
this.messageValues.forEach((item, index) => {
|
||||
let { value } = item;
|
||||
const message = this.messages[index];
|
||||
if (message.datetime > 0) {
|
||||
value = value.replace(/T/g, ' ');
|
||||
}
|
||||
messages[message.name] = value;
|
||||
messages[message.name] = item.value;
|
||||
});
|
||||
|
||||
return messages;
|
||||
@ -125,7 +118,6 @@ export default createComponent({
|
||||
<Cell
|
||||
key={`${this.goodsId}-${index}`}
|
||||
title={message.name}
|
||||
label={t('imageLabel')}
|
||||
class={bem('image-cell')}
|
||||
required={String(message.required) === '1'}
|
||||
valueClass={bem('image-cell-value')}
|
||||
@ -135,14 +127,31 @@ export default createComponent({
|
||||
maxSize={this.messageConfig.uploadMaxSize}
|
||||
uploadImg={this.messageConfig.uploadImg}
|
||||
/>
|
||||
<div class={bem('image-cell-label')}>{t('imageLabel')}</div>
|
||||
</Cell>
|
||||
);
|
||||
}
|
||||
|
||||
// 时间和日期使用的vant选择器
|
||||
const isDateOrTime = ['date', 'time'].indexOf(message.type) > -1;
|
||||
if (isDateOrTime) {
|
||||
return (
|
||||
<SkuDateTimeField
|
||||
vModel={this.messageValues[index].value}
|
||||
label={message.name}
|
||||
key={`${this.goodsId}-${index}`}
|
||||
required={String(message.required) === '1'}
|
||||
placeholder={this.getPlaceholder(message)}
|
||||
type={this.getType(message)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Field
|
||||
vModel={this.messageValues[index].value}
|
||||
maxlength="200"
|
||||
center={!message.multiple}
|
||||
label={message.name}
|
||||
key={`${this.goodsId}-${index}`}
|
||||
required={String(message.required) === '1'}
|
||||
|
@ -314,12 +314,6 @@
|
||||
&-messages {
|
||||
padding-bottom: @padding-xl;
|
||||
|
||||
.van-cell::after {
|
||||
top: 0;
|
||||
right: @padding-md;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
&__image-cell {
|
||||
.van-cell__title {
|
||||
max-width: @field-label-width;
|
||||
@ -330,75 +324,13 @@
|
||||
overflow: visible;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-img-uploader {
|
||||
display: inline-block;
|
||||
|
||||
&__uploader {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&__img {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin-right: @padding-xs;
|
||||
background: @sku-item-background-color;
|
||||
border-radius: @border-radius-sm;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
&-label {
|
||||
color: @cell-label-color;
|
||||
font-size: @cell-label-font-size;
|
||||
line-height: @cell-label-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
&__delete {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
right: -14px;
|
||||
z-index: 1;
|
||||
padding: 6px;
|
||||
color: @sku-upload-mask-color;
|
||||
opacity: 0.8;
|
||||
|
||||
&::before {
|
||||
background-color: @white;
|
||||
border-radius: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: white;
|
||||
background: @sku-upload-mask-color;
|
||||
}
|
||||
|
||||
&__warn-text {
|
||||
margin-top: 6px;
|
||||
font-size: @font-size-sm;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
&__trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: @sku-icon-gray-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-actions {
|
||||
|
@ -26,7 +26,8 @@ export default {
|
||||
vanSkuImgUploader: {
|
||||
oversize: (maxSize: number) =>
|
||||
`最大可上传图片为${maxSize}MB,请尝试压缩图片尺寸`,
|
||||
fail: '上传失败<br />重新上传',
|
||||
fail: '上传失败',
|
||||
uploading: '上传中...',
|
||||
},
|
||||
vanSkuStepper: {
|
||||
quotaLimit: (quota: number) => `限购${quota}件`,
|
||||
@ -45,18 +46,32 @@ export default {
|
||||
id_no: '请填写正确的身份证号码',
|
||||
},
|
||||
placeholder: {
|
||||
id_no: '输入身份证号码',
|
||||
text: '输入文本',
|
||||
tel: '输入数字',
|
||||
email: '输入邮箱',
|
||||
date: '点击选择日期',
|
||||
time: '点击选择时间',
|
||||
textarea: '点击填写段落文本',
|
||||
mobile: '输入手机号码',
|
||||
id_no: '请填写身份证号',
|
||||
text: '请填写留言',
|
||||
tel: '请填写数字',
|
||||
email: '请填写邮箱',
|
||||
date: '请选择日期',
|
||||
time: '请选择时间',
|
||||
textarea: '请填写留言',
|
||||
mobile: '请填写手机号',
|
||||
},
|
||||
},
|
||||
vanSkuRow: {
|
||||
multiple: '可多选',
|
||||
},
|
||||
vanSkuDatetimeField: {
|
||||
title: {
|
||||
date: '选择年月日',
|
||||
time: '选择时间',
|
||||
datetime: '选择日期时间',
|
||||
},
|
||||
format: {
|
||||
year: '年',
|
||||
month: '月',
|
||||
day: '日',
|
||||
hour: '时',
|
||||
minute: '分',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { mount } from '../../../test';
|
||||
import Sku from '..';
|
||||
import { getSkuData, initialSku } from '../demo/data';
|
||||
import { stringToDate, dateToString } from '../utils/time-helper';
|
||||
|
||||
const skuData = getSkuData();
|
||||
|
||||
@ -30,3 +31,14 @@ test('resetSelectedSku method', () => {
|
||||
wrapper.find('.van-button--danger').trigger('click');
|
||||
expect(wrapper.emitted('buy-clicked').length).toEqual(1);
|
||||
});
|
||||
|
||||
test('stringToDate', () => {
|
||||
expect(dateToString(stringToDate(''))).toEqual('');
|
||||
expect(dateToString(stringToDate('2020-07-01'))).toEqual('2020-07-01');
|
||||
expect(dateToString(stringToDate('2020-07-01 22:44'), 'datetime')).toEqual(
|
||||
'2020-07-01 22:44'
|
||||
);
|
||||
expect(dateToString(stringToDate('2020-12-31 23:59'), 'datetime')).toEqual(
|
||||
'2020-12-31 23:59'
|
||||
);
|
||||
});
|
||||
|
28
src/sku/utils/time-helper.js
Normal file
28
src/sku/utils/time-helper.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { padZero } from '../../utils/format/string';
|
||||
|
||||
// 字符串转 Date
|
||||
// 只处理 YYYY-MM-DD 或者 YYYY-MM-DD HH:MM 格式
|
||||
export function stringToDate(timeString) {
|
||||
if (!timeString) {
|
||||
return null;
|
||||
}
|
||||
return new Date(timeString.replace(/-/g, '/'));
|
||||
}
|
||||
|
||||
// Date 转字符串
|
||||
// type: date or datetime
|
||||
export function dateToString(date, type = 'date') {
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
let timeString = `${year}-${padZero(month)}-${padZero(day)}`;
|
||||
if (type === 'datetime') {
|
||||
const hours = date.getHours();
|
||||
const minute = date.getMinutes();
|
||||
timeString += ` ${padZero(hours)}:${padZero(minute)}`;
|
||||
}
|
||||
return timeString;
|
||||
}
|
6
types/image-preview.d.ts
vendored
6
types/image-preview.d.ts
vendored
@ -20,9 +20,9 @@ export type ImagePreviewOptions =
|
||||
closeOnPopstate?: boolean;
|
||||
closeIconPosition?: string;
|
||||
getContainer?: string | (() => Element);
|
||||
onClose?: () => void;
|
||||
onChange?: (index: number) => void;
|
||||
swipeTo(index: number, options?: SwipeToOptions): void;
|
||||
onClose?(): void;
|
||||
onChange?(index: number): void;
|
||||
swipeTo?(index: number, options?: SwipeToOptions): void;
|
||||
};
|
||||
|
||||
export class VanImagePreview extends VanPopupMixin {
|
||||
|
Loading…
x
Reference in New Issue
Block a user