混入小程序

This commit is contained in:
mactj 2021-01-12 18:04:14 +08:00
parent 42d3c2c828
commit 645d1f49cb
738 changed files with 29490 additions and 0 deletions

9
mini-app/.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

1
mini-app/.eslintignore Normal file
View File

@ -0,0 +1 @@
dist/*

32
mini-app/.eslintrc.js Normal file
View File

@ -0,0 +1,32 @@
module.exports = {
root: true,
globals: { wx: true },
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: 'standard',
// required to lint *.wpy files
plugins: [
'html'
],
settings: {
'html/html-extensions': ['.html', '.wpy']
},
// add your custom rules here
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'space-before-function-paren': 0
}
};

3
mini-app/.prettierrc Normal file
View File

@ -0,0 +1,3 @@
{
"singleQuote": true
}

4
mini-app/.wepyignore Normal file
View File

@ -0,0 +1,4 @@
node_modules
dist
.DS_Store
*.wpy___jb_tmp___

42
mini-app/package.json Normal file
View File

@ -0,0 +1,42 @@
{
"name": "hope_wine",
"version": "0.0.2",
"description": "A WePY project",
"main": "weapp/app.js",
"scripts": {
"dev": "./node_modules/.bin/wepy build --watch",
"build": "cross-env NODE_ENV=production ./node_modules/.bin/wepy build --no-cache",
"clean": "rm -rf weapp",
"test": "echo \"Error: no test specified\" && exit 1"
},
"wepy": {
"module-a": false,
"./src/components/list": "./src/components/wepy-list.wpy"
},
"author": "Machengtianjiang <myxmctj@gmail.com>",
"license": "MIT",
"dependencies": {
"@wepy/core": "^2.0.0-alpha.16",
"@wepy/x": "^2.0.2",
"miniprogram-slide-view": "0.0.3"
},
"devDependencies": {
"@babel/core": "^7.1.0",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/preset-env": "^7.1.0",
"@wepy/babel-plugin-import-regenerator": "0.0.2",
"@wepy/cli": "^2.0.0-alpha.28",
"@wepy/compiler-babel": "^2.0.1",
"@wepy/compiler-less": "^2.0.1",
"babel-eslint": "^7.2.1",
"cross-env": "^5.1.3",
"eslint": "^3.18.0",
"eslint-config-standard": "^7.1.0",
"eslint-friendly-formatter": "^2.0.7",
"eslint-plugin-html": "^2.0.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^2.0.1",
"less": "^3.8.1",
"wepy-eslint": "^1.5.3"
}
}

View File

@ -0,0 +1,112 @@
{
"description": "A WePY project",
"setting": {
"urlCheck": false,
"es6": false,
"enhance": true,
"postcss": false,
"preloadBackgroundData": false,
"minified": false,
"newFeature": true,
"coverView": true,
"nodeModules": true,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"compileType": "miniprogram",
"appid": "wx76ec015fc31a1946",
"projectname": "hope_wine",
"miniprogramRoot": "weapp/",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"plugin": {
"current": -1,
"list": []
},
"game": {
"list": []
},
"gamePlugin": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": [
{
"id": -1,
"name": "pages/form1",
"pathName": "pages/form1",
"query": "",
"scene": null
},
{
"id": -1,
"name": "pages/form2",
"pathName": "pages/form2",
"query": "",
"scene": null
},
{
"id": -1,
"name": "pages/form3",
"pathName": "pages/form3",
"query": "",
"scene": null
},
{
"id": -1,
"name": "pages/form4",
"pathName": "pages/form4",
"query": "",
"scene": null
},
{
"id": -1,
"name": "pages/form5",
"pathName": "pages/form5",
"query": "",
"scene": null
},
{
"id": -1,
"name": "pages/form6",
"pathName": "pages/form6",
"query": "",
"scene": null
},
{
"id": -1,
"name": "商城首页",
"pathName": "pages/mall/index",
"query": "",
"scene": null
},
{
"id": -1,
"name": "商品详情",
"pathName": "pages/mall/goods-detail",
"scene": null
}
]
}
}
}

View File

@ -0,0 +1,65 @@
import request from '../js/request'
import { baseUrl, formHeader, jsonHeader } from './xiao4rApis'
import { MINI_DEPTID } from '../config'
/**
* 用户相关接口
*/
class UserApis {
/**
* 注册
* @param data
* @returns {Promise实例对象}
*/
registrationByMini(data) {
data.deptId = MINI_DEPTID
return request.post({
url: baseUrl + 'mini/user/registrationByMini',
data: data
})
}
/**
* 登录
* @param data
* @returns {Promise实例对象}
*/
loginByMini(data) {
data.deptId = MINI_DEPTID
return request.post({
url: baseUrl + 'mini/user/loginByMini',
data: data
})
}
getSession(code) {
return request.get({
url: baseUrl + 'mini/user/getSession',
header: formHeader,
data: {
'code': code,
'deptId': MINI_DEPTID
}
})
}
sendMobile(data) {
data.deptId = MINI_DEPTID
return request.post({
url: baseUrl + 'mini/user/sendMobile',
header: jsonHeader,
data: data
})
}
getAuthTest(data) {
return request.get({
url: baseUrl + 'mini/user/test',
header: formHeader,
data: data
})
}
}
export default new UserApis()

View File

@ -0,0 +1,38 @@
import request from '../js/request'
export const baseUrl = 'http://127.0.0.1:18989/winery/'
// export const baseUrl = 'http://36.1.50.18:18989/winery/'
// export const baseUrl = 'http://62.234.123.172:18989/api/'
// export const baseUrl = 'https://www.xiao4r.com/wine/winery/'
export const jsonHeader = {
'Content-Type': 'application/json'
}
export const formHeader = {
'Content-Type': 'application/x-www-form-urlencoded'
}
/**
* 接口
*/
class Xiao4rApis {
postForm(data) {
return request.post({
url: baseUrl + 'mini/postForm',
header: jsonHeader,
data: data
})
}
getForm(data) {
return request.get({
url: baseUrl + 'mini/getForm',
header: formHeader,
data: data
})
}
}
export default new Xiao4rApis()

143
mini-app/src/app.wpy Normal file
View File

@ -0,0 +1,143 @@
<style lang="less">
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.buttonColor {
background: #AC1630;
color: #fff;
}
.buttonColor-cancel {
background: #fff;
color: #333;
}
.background-color {
background: #AC1630;
}
.cell-title {
padding: 10px 16px;
font-weight: bold;
}
.cell {
margin-top: 10px;
}
.boom {
background-color: #F0F1F2;
width: 100%;
height: 15px;
}
</style>
<script>
import wepy from '@wepy/core'
import eventHub from './common/eventHub'
import vuex from '@wepy/x'
wepy.use(vuex)
wepy.app({
hooks: {
// App 级别 hook对整个 App 生效
// 同时存在 Page hook 和 App hook 时,优先执行 Page hook返回值再交由 App hook 处
'before-setData': function(dirty) {
console.log('setData dirty: ', dirty)
return dirty
}
},
globalData: {
userInfo: null
},
onLaunch() {
// this.testAsync()
eventHub.$on('app-launch', (...args) => {
console.log('app-launch event emitted, the params are:')
console.log(args)
})
},
methods: {
// sleep(s) {
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('promise resolved')
// }, s * 1000)
// })
// },
// async testAsync() {
// let d = await this.sleep(3)
// console.log(d)
// }
}
})
</script>
<config>
{
pages: [
'pages/index',
'pages/form1',
'pages/form2',
'pages/form3',
'pages/form4',
'pages/form5',
'pages/form6',
'pages/mall/index',
'pages/mall/goods-detail'
],
navigateToMiniProgramAppIdList: [
'wx88736d7d39e2eda6'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'white',
navigationStyle: 'custom',
},
usingComponents: {
'nav-bar': './components/nav-bar',
'van-button': './vant/button/index',
'van-divider': './vant/divider/index',
'van-field': './vant/field/index',
'van-radio': './vant/radio/index',
'van-radio-group': './vant/radio-group/index',
'van-checkbox': './vant/checkbox/index',
'van-checkbox-group': './vant/checkbox-group/index',
'van-cell': './vant/cell/index',
'van-cell-group': './vant/cell-group/index',
'van-datetime-picker': './vant/datetime-picker/index',
'van-nav-bar': './vant/nav-bar/index',
'van-icon': './vant/icon/index',
'van-steps': './vant/steps/index',
'van-row': './vant/row/index',
'van-col': './vant/col/index',
'van-col': './vant/col/index',
'van-tabbar': './vant/tabbar/index',
'van-tabbar-item': './vant/tabbar-item/index',
'van-card': './vant/card/index',
'van-popup': './vant/popup/index',
'van-stepper': './vant/stepper/index',
'van-submit-bar': './vant/submit-bar/index',
'van-panel': './vant/panel/index',
"van-grid": "./vant/grid/index",
"van-grid-item": "./vant/grid-item/index",
"van-dialog": "./vant/dialog/index",
"van-image": "./vant/image/index"
}
}
</config>

View File

@ -0,0 +1,5 @@
import wepy from '@wepy/core';
let eventHub = new wepy();
export default eventHub;

View File

@ -0,0 +1,77 @@
<style lang="less">
.counter {
text-align: left;
font-size: 12px;
}
.count {
font-size: 18px;
font-weight: bold;
&.red {
color: red;
}
&.green {
color: green;
}
}
</style>
<template>
<div class="counter {{style}}">
<button @tap="plus" size="mini"> + </button>
<button @tap="minus" size="mini"> - </button>
<button @tap="increment" size="mini"> INCREMENT </button>
<button @tap="decrement" size="mini"> DECREMENT </button>
<button @tap="incrementAsync" size="mini"> ASYNC INCREMENT </button>
<span class="count"> {{counter}} </span>
</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '../store';
import { mapState, mapActions } from '@wepy/x';
wepy.component({
store,
props: {
num: {
type: [Number, String],
coerce: function (v) {
return +v
},
default: 50
}
},
computed: mapState([ 'counter' ]),
events: {
'index-broadcast': (...args) => {
let $event = args[args.length - 1]
console.log(`${this.$name} receive ${$event.name} from ${$event.source.$name}`)
}
},
watch: {
num (curVal, oldVal) {
console.log(`旧值:${oldVal},新值:${curVal}`)
}
},
methods: {
...mapActions([
'increment',
'decrement',
'incrementAsync'
]),
plus () {
this.num = this.num + 1
console.log('plus tapped in component');
this.$emit('index-emit', this.num);
},
minus () {
this.num = this.num - 1
console.log(this.$name + ' minus tap')
}
}
})
</script>

View File

@ -0,0 +1,41 @@
<style type="less">
.group {}
</style>
<template>
<div class="group">
<span class="id">{{grouplist.id}}. </span>
<span class="name" @tap="tap">{{grouplist.name}}</span>
<div>
<div v-for="item in grouplist.list">
<groupitem :gitem="item"></groupitem>
</div>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core';
//import GroupItem from './groupitem'
wepy.component({
props: {
grouplist: {},
index: {}
},
methods: {
tap () {
this.grouplist.name = `Parent Random(${Math.random()})`
let groups = this.$parent.$children.filter(com => com.$is === 'components/group');
let index = groups.indexOf(this);
console.log(`Clicked Group ${index}, ID is ${this.grouplist.id}`)
}
}
});
</script>
<config>
{
usingComponents: {
'groupitem': './groupitem'
}
}
</config>

View File

@ -0,0 +1,28 @@
<style type="less">
.groupitem {
}
</style>
<template>
<div class="groupitem">
--<span class="id">{{gitem.childid}}.</span>
<span class="name" @tap="tap"> {{gitem.childname}}</span>
</div>
</template>
<script>
import wepy from '@wepy/core';
wepy.component({
props: {
gitem: {}
},
data: {
},
methods: {
tap () {
this.gitem.childname = `Child Random(${Math.random()})`
let index = this.$parent.$children.indexOf(this);
console.log(`Item ${index}, ID is ${this.gitem.childid}`)
}
}
});
</script>

View File

@ -0,0 +1,48 @@
<style lang="less">
.mylist:odd {
color: red;
}
.mylist:even {
color: green;
}
</style>
<template>
<div class="list">
This component is not used. because list is an aliasField in package.json
</div>
</template>
<script>
import wepy from '@wepy/core'
wepy.component({
data: {
list: [
{
id: '0',
title: 'loading'
}
]
},
events: {
'index-broadcast': (...args) => {
let $event = args[args.length - 1]
console.log(`${this.$name} receive ${$event.name} from ${$event.source.name}`)
}
},
methods: {
tap () {
// this.num = this.num + 1
console.log(this.$name + ' tap')
},
add () {
let len = this.list.length
this.list.push({id: len + 1, title: 'title_' + len})
}
}
onLoad () {
}
});
</script>

View File

@ -0,0 +1,108 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<template>
<view style="padding: 10px;">
<van-row>
<van-col span="8">
<van-image src="" />
</van-col>
<van-col span="8">span: 8</van-col>
</van-row>
<van-panel v-for="(item,index) in list" :key="index" :title="item.user" desc="三星客户" status=" " use-footer-slot>
<view style="display: flex;font-size: 14px;">{{item.context}}</view>
<van-grid column-num="3" border="{{ false }}">
<van-grid-item use-slot wx:for="{{ 3 }}" wx:for-item="index">
<image
style="width: 100%; height: 90px;"
src="https://img.yzcdn.cn/vant/apple-{{ index + 1 }}.jpg"
/>
</van-grid-item>
</van-grid>
<van-divider />
<view style="display: flex;font-size: 14px;">
<span style="color: cornflowerblue;">用户xxx<span
style="color: #333333;">的回复: 内容很牛逼,挺内容很牛逼,挺内容很牛逼,挺内容很牛逼,挺内容很牛逼,挺</span></span>
</view>
<view slot="footer">
<view style="display: flex;justify-content: flex-end;">
<van-button v-if="true" size="small">删除</van-button>
<van-button v-if="true" size="small" type="danger" style="margin-left: 10px;">编辑</van-button>
<van-button size="small" type="danger" style="margin-left: 10px;" @tap="onReply(item)">回复</van-button>
</view>
</view>
</van-panel>
<van-dialog
use-slot
title="标题"
show="{{ isShowInput }}"
show-cancel-button
bind:close="onCloseInput"
bind:confirm="onConfirmInput"
>
<image src="https://img.yzcdn.cn/1.jpg" />
</van-dialog>
</view>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.component({
store,
hooks: {},
data: {
user: store.state.user,
list: [],
isShowInput: false
},
computed: {},
methods: {
onReply(item) {
console.log(item)
this.isShowInput = true
},
onCloseInput() {
this.isShowInput = false
},
onConfirmInput() {
this.isShowInput = false
}
},
ready() {
console.log('user:', this.user)
for (let i = 0; i < 10; i++) {
this.list.push({ title: '标题', user: '用户1', context: '长篇大论长篇大论长篇大论长篇大论长篇大论长篇大论长篇大论长篇大论长篇大论长篇大论' })
}
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,121 @@
<template>
<view style="padding: 0 10px 110px 0;background: #fafafa;">
<van-checkbox-group :value="selectedList" bind:change="onChangeSelect">
<view v-for="(item, index) in list" :key="index"
style="margin-top: 10px;border: #fafafa 1px solid; border-radius: 10px;">
<van-card
:price="item.price/100"
desc="描述信息"
title="商品标题"
nun="n"
>
<view slot="thumb">
<div style="display: inline-flex;align-items: center;margin-top: 12px;">
<van-checkbox :name="item.id" />
<image class="van-card__thumb"
src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg" />
</div>
</view>
</van-card>
</view>
</van-checkbox-group>
<van-submit-bar
:price="price"
button-text="提交订单"
bind:submit="onSubmit"
button-class="submit-btn"
>
<van-checkbox style="margin-top:5px;" :value="isAllSelect" bind:change="onAllSelect">全选</van-checkbox>
</van-submit-bar>
</view>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.component({
store,
hooks: {},
data: {
active: 0,
checked: false,
list: [],
selectedList: [],
isAllSelect: false,
price: 10000
},
computed: {
},
methods: {
onChangeSelect(e) {
this.selectedList = e.$wx.detail
this.isAllSelect = this.selectedList.length === this.list.length
},
onAllSelect(e) {
this.isAllSelect = e.$wx.detail
if (this.isAllSelect) {
this.selectedList = this.list.map(x => x.id)
} else {
this.selectedList = []
}
},
onSubmit() {
// 订单提交
}
},
ready() {
for (let i = 0; i < 15; i++) {
this.list.push(
{
id: i + '',
name: '商品',
price: 599
})
}
}
})
</script>
<config>
{
navigationBarTitleText: '',
usingComponents: {
},
styleIsolation: 'shared',
addGlobalClass: true,
}
</config>
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
.van-card__thumb {
position: relative;
-webkit-flex: none;
flex: none;
width: 66px;
height: 66px;
margin-left: 8px;
}
.submit-btn {
border-radius: 20px !important;
border: #AC1630 1px solid !important;
}
</style>

View File

@ -0,0 +1,49 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<template>
<div>
home
</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.component({
store,
hooks: {
},
data: {
},
computed: {
},
methods: {
},
ready() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,45 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<template>
<div>my</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.component({
store,
hooks: {
},
data: {
active: 0
},
computed: {
},
methods: {
},
ready() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,66 @@
<template>
<view style="padding: 0 10px;background: #fafafa;">
<view v-for="(item, index) in list" :key="index" style="margin-top: 10px;border: #fafafa 1px solid; border-radius: 10px;">
<van-card
price="2.00"
desc="描述信息"
title="商品标题"
thumb="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg"
@tap="onItem(item)"
>
<view slot="num" style="float:right;">
<div>{{"已优惠¥xx元"}} </div>
</view>
</van-card>
</view>
</view>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
import xiao4rBase from '../../xiao4rBase'
wepy.component({
store,
hooks: {},
data: {
active: 0,
list: [1, 2, 3, 4]
},
computed: {},
methods: {
onItem(item) {
console.log(item)
xiao4rBase.navigateTo(`goods-detail?id=${item}`)
}
},
ready() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>

View File

@ -0,0 +1,43 @@
<style lang="less">
</style>
<template>
<van-nav-bar
bind:click-left="onBack"
border="{{false}}"
custom-style="background:#AC1630;color:#FFF;"
>
<van-icon name="arrow-left" slot="left" color="#fff" />
<span style="color: #fff;" slot="title">{{title}}</span>
</van-nav-bar>
</template>
<script>
import wepy from '@wepy/core'
wepy.component({
props: {
title: {
type: String,
default: '贺兰山酒庄普查'
}
},
data: {
},
events: {
},
methods: {
onBack() {
wx.navigateBack()
}
},
onLoad () {
}
})
</script>

View File

@ -0,0 +1,40 @@
<style lang="less">
panel {
width: 100%;
}
.panel {
width: 100%;
margin-top: 20rpx;
text-align: left;
font-size: 12px;
padding-top: 20rpx;
padding-left: 50rpx;
padding-bottom: 20rpx;
border: 1px solid #ccc;
.title {
padding-bottom: 20rpx;
font-size: 14px;
font-weight: bold;
}
.info {
padding: 15rpx;
}
.testcounter {
margin-top: 15rpx;
position: absolute;
}
.counterview {
margin-left: 120rpx;
}
}
</style>
<template>
<div class="panel">
<slot name="title">
Title
</slot>
<slot>
</slot>
</div>
</template>

View File

@ -0,0 +1,190 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<template>
<div>
<van-dialog
use-slot
title="新用户注册"
:show="isShow"
show-cancel-button
bind:close="onClose"
bind:cancel="onClose"
confirm-button-open-type="getUserInfo"
bind:getuserinfo="getUserInfo"
:asyncClose="true"
>
<van-field
label="手机号:"
title-width="60px"
value="{{ user.mobile }}"
center
clearable
readonly
placeholder="请实名授权获取手机号"
border="{{ false }}"
use-button-slot
>
<van-button slot="button" size="small" plain type="info" open-type="getPhoneNumber"
bind:getphonenumber="onGetMobile">授权
</van-button>
</van-field>
<!-- <van-divider customStyle="font-size: 18px; margin: 5px 5px;" />-->
<!-- <van-field-->
<!-- label="昵称:"-->
<!-- title-width="60px"-->
<!-- value="{{ user.userInfo.nickName }}"-->
<!-- center-->
<!-- clearable-->
<!-- readonly-->
<!-- placeholder="请点击授权获取您的微信信息"-->
<!-- border="{{ false }}"-->
<!-- use-button-slot-->
<!-- >-->
<!-- <van-button slot="button" size="small" plain type="info" open-type="getUserInfo"-->
<!-- bind:getuserinfo="getUserInfo">获取昵称-->
<!-- </van-button>-->
<!-- </van-field>-->
<view style="margin:10px;">
<van-checkbox :value="isChecked" shape="square" bind:change="onChangeCheak" checked-color="#AC1630"
style="font-size: 14px;color: #AC1630;">
我同意<span style="color: cornflowerblue;">xxxxx </span>用户协议
</van-checkbox>
</view>
</van-dialog>
</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions, mapState } from '@wepy/x'
import eventHub from '../../common/eventHub'
import xiao4rBase from '../../xiao4rBase'
import userApis from '../../apis/userApis'
wepy.component({
store,
props: {},
hooks: {},
data: {
that: this,
isShow: false,
model: {},
isChecked: false,
},
computed: mapState(['user']),
events: {},
methods: {
...mapActions([
'setUserAction',
'setUserInfoAction',
'setMobileAction',
'setTokenAction'
]),
getUserInfo(event) {
console.log('getUserInfo:', event.$wx.detail)
this.setUserInfoAction(event.$wx.detail.userInfo)
console.log('userInfo:', store.state.user.userInfo)
if (!this.isChecked) {
xiao4rBase.showToast('请确认xxxx协议.')
return false
}
if (!this.user.mobile) {
xiao4rBase.showToast('请授权获取手机号码.')
return false
}
if (!this.user.userInfo) {
xiao4rBase.showToast('请授权获取用户昵称.')
return false
}
let self = this
userApis.registrationByMini(this.user).then(r => {
if (r.code === 200) {
xiao4rBase.showToast('注册成功!')
self.isShow = false
self.setTokenAction(r.token)
} else {
xiao4rBase.showToast(r.msg)
}
}).catch(e => {
xiao4rBase.showToast('注册失败!')
})
},
async onGetMobile(e) {
console.log(e.$wx.detail)
wx.showLoading({ title: '获取中...', mask: true })
try {
let rsp = await userApis.sendMobile({
openid: xiao4rBase.getOpenid(),
detail: e.$wx.detail
})
console.log(rsp)
if (rsp.code === 200) {
this.setMobileAction(rsp.data.mobile)
} else {
xiao4rBase.showToast('服务器连接异常.')
}
} catch (e) {
xiao4rBase.showToast('服务器连接异常.')
} finally {
wx.hideLoading()
}
},
onChangeCheak(e) {
this.isChecked = e.$wx.detail
},
onClose() {
this.isShow = false
}
},
ready() {
// 获取系统信息
let self = this
wx.getSystemInfo({
success(res) {
self.model = res.model
}
})
console.log(this)
this.page = this
eventHub.$on('onShowDialogUserInfo', (...args) => {
this.isShow = true
})
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,49 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<template>
<div>
</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.component({
store,
hooks: {
},
data: {
active: 0
},
computed: {
},
methods: {
},
ready() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,58 @@
<style lang="less">
.mylist:odd {
color: red;
}
.mylist:even {
color: green;
}
</style>
<template>
<div class="wepy-list">
<div>
<button @tap="add" size="mini">添加列表another</button>
</div>
<div v-for="(item, index) in list">
<div @tap="tap" class="mylist">
<span>{{item.id}}</span>: {{item.title}} <span @tap="remove(index)"> X </span>
</div>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core'
wepy.component({
data: {
list: [
{
id: '0',
title: 'loading'
}
]
},
events: {
'index-broadcast': (...args) => {
let $event = args[args.length - 1]
console.log(`${this.$name} receive ${$event.name} from ${$event.source.name}`)
}
},
methods: {
tap () {
// this.num = this.num + 1
console.log(this.$name + ' tap')
},
add () {
let len = this.list.length
this.list.push({id: len + 1, title: 'title_' + len})
},
remove (index) {
this.$delete(this.list, index);
}
},
onLoad () {
}
});
</script>

5
mini-app/src/config.js Normal file
View File

@ -0,0 +1,5 @@
/**
* 常量
*/
export const MINI_DEPTID = 100

View File

@ -0,0 +1,71 @@
import xiao4rBase from '../xiao4rBase'
import { uuid } from './utils/uuid'
import store from '@/store'
class Xiao4rRequest {
// 网络请求任务对象 Map
requestTaskMap = new Map()
/**
* requestPromise用于将wx.request改写成Promise方式
* @param{string} myUrl 接口地址
* @return: Promise实例对象
*/
requestPromise(req) {
let id = uuid()
let self = this
if (store.state.user.token) {
if (req.header) {
req.header['Authorization'] = store.state.user.token
} else {
req.header = {
Authorization: store.state.user.token
}
}
}
let promise = new Promise((resolve, reject) => {
const task = wx.request({
url: req.url,
method: req.method,
header: req.header,
data: req.data,
success: rsp => resolve(rsp.data),
fail: error => {
xiao4rBase.showToast('网络连接异常.')
reject(error)
},
complete: () => {
this.requestTaskMap.delete(id)
}
})
self.requestTaskMap.set(id, task)
})
// 返回一个Promise实例对象
promise.taskId = id
return promise
}
post(req) {
req.method = 'POST'
return this.requestPromise(req)
}
get(req) {
req.method = 'GET'
return this.requestPromise(req)
}
put(req) {
req.method = 'PUT'
return this.requestPromise(req)
}
del(req) {
req.method = 'DEL'
return this.requestPromise(req)
}
}
export default new Xiao4rRequest()

View File

@ -0,0 +1,14 @@
export function uuid() {
var s = []
var hexDigits = '0123456789abcdef'
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
}
s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = '-'
var uuid = s.join('')
return uuid
}

View File

@ -0,0 +1,23 @@
class ValidateUtils {
isEmail(value) {
const reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
return reg.test(value)
}
/**
* 校验数字或者小数
* @param text
* @returns {boolean}
*/
isIntOrDecimal(text) {
let pattern = /^[0-9]+([.]{1}[0-9]+){0,1}$/;
return pattern.test(text)
}
}
export default new ValidateUtils()

View File

@ -0,0 +1,19 @@
export default {
data: {
mixin: 'MixinText'
},
methods: {
mixintap () {
this.mixin = 'MixinText' + (Math.random() + '').substring(3, 7);
console.log('mixin method tap');
},
tap () {
console.log('tap in mixin');
}
},
created () {
console.log('created in mixin');
}
}

View File

@ -0,0 +1,267 @@
<style lang="less">
.header {
width: 100%;
height: 100rpx;
display: flex;
}
input {
margin: 12px 15px;
font-size: 14px;
}
.cell-input {
display: flex;
justify-content: space-between;
margin-right: 15px;
}
.cell-item {
margin-left: 22px;
margin-top: 12px;
width: 300rpx;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<span style="font-size: 26px;margin: 0px 0 0 15px;color: #FFF;">酒庄基础信息填写</span>
</div>
<div style="margin-top: 32px;">
<div>
<span class="cell-title">绑定手机号</span>
<van-field
value="{{ wineryForm.mobile }}"
center
clearable
readonly
placeholder="请点击授权获取手机号"
border="{{ false }}"
use-button-slot
>
<van-button slot="button" size="small" plain type="info" open-type="getPhoneNumber"
bindgetphonenumber="onGetMobile">授权
</van-button>
</van-field>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">酒庄全称</span>
<input
v-model="wineryForm.wineryName"
center
clearable
placeholder="请输入酒庄全称"
style="color: #AC1630;"
/>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">酒庄成立时间</span>
<picker mode="date" v-model="wineryForm.date" end="{{maxDate}}" bindchange="bindDateChange">
<van-field
value="{{ wineryForm.buildTime }}"
center
clearable
readonly
placeholder="请选择"
border="{{ false }}"
/>
</picker>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">酒庄地址(省市区)</span>
<picker mode="region" v-model="wineryForm.region" bindchange="bindRegionChange">
<van-field
value="{{ wineryForm.region }}"
center
clearable
readonly
placeholder="请选择"
border="{{ false }}"
/>
</picker>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">酒庄地址(详细)</span>
<input
v-model="wineryForm.address"
center
clearable
placeholder="请输入酒庄地址"
/>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">酒庄总面积</span>
<div class="cell-input">
<input
v-model="wineryForm.wineryArea"
type="number"
center
clearable
placeholder="请输入酒庄总面积"
use-button-slot
/>
<span slot="button" size="small">亩</span>
</div>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div class="cell">
<span class="cell-title">建筑总面积</span>
<div class="cell-input">
<input
v-model="wineryForm.buildArea"
type="number"
center
clearable
placeholder="请输入建筑总面积"
use-button-slot
/>
<span slot="button" size="small">平方米</span>
</div>
<van-divider customStyle="margin: 0 5px;" />
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">酒庄现状</span>
<van-radio-group value="{{ wineryForm.wineryStatus }}" bind:change="onChangeWineryStatus">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item" v-for="(item,index) in wineryStatusType">
<van-radio class="cell2-radio" name="{{item}}" checked-color="#AC3016">{{item}}</van-radio>
</div>
</div>
</van-radio-group>
</div>
<div class="boom" />
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor" style="width: 686rpx;" @tap="onNext()">下一步</button>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapState, mapActions } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import userApis from '../apis/userApis'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
'before-setData': function(dirty) {
if (Math.random() < 0.2) {
console.log('setData canceled')
return false // Cancel setData
}
dirty.time = +new Date()
return dirty
}
},
data: {
form: store.state.wineryForm,
wineryStatusType: ['已建成投产', '在建已投产', '在建未投产', '已停产']
},
computed: mapState(['wineryForm']),
methods: {
...mapActions([
'setWineryFormAction'
]),
bindDateChange(event) {
this.wineryForm.buildTime = event.$wx.detail.value
},
bindRegionChange(event) {
this.wineryForm.region = event.$wx.detail.value
},
onChangeWineryStatus(e) {
this.wineryForm.wineryStatus = e.$wx.detail
},
async onGetMobile(e) {
wx.showLoading({ title: '获取中...', mask: true })
try {
let rsp = await userApis.sendMobile({
openid: xiao4rBase.getOpenid(),
detail: e.$wx.detail
})
if (rsp.code === 200) {
this.wineryForm.mobile = rsp.data.mobile
}
xiao4rBase.showToast(rsp.msg)
} catch (e) {
xiao4rBase.showToast('服务器连接异常,请联系管理员.')
} finally {
wx.hideLoading()
}
},
onNext() {
console.log(this.form)
if (!this.wineryForm.mobile) {
xiao4rBase.showToast('请授权获取您的手机号')
return
}
if (!this.wineryForm.wineryName) {
xiao4rBase.showToast('请输入您的酒庄名称')
return
}
if (!this.wineryForm.buildTime) {
xiao4rBase.showToast('请输入您的酒庄成立时间')
return
}
if (!this.wineryForm.address) {
xiao4rBase.showToast('请输入您的酒庄地址')
return
}
if (!this.wineryForm.wineryArea) {
xiao4rBase.showToast('请输入您的酒庄总面积')
return
}
if (!this.wineryForm.buildArea) {
xiao4rBase.showToast('请输入您的建筑总面积')
return
}
// this.setFormAction(this.form)
xiao4rBase.navigateTo('form2')
}
},
created() {
let self = this
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,139 @@
<style lang="less">
page {
background-color: #F0F1F2;
}
.header {
width: 100%;
height: 320px;
display: flex;
}
.header-cell {
margin: 15px 15px 0 15px;
display: flex;
justify-content: space-between;
}
.header-title {
width: 260rpx;
}
.header-value {
width: 420rpx;
}
.fream {
position: absolute;
top: 265px;
left: 0;
right: 0;
margin: 0 auto 0 auto;
background: white;
width: 610rpx;
height: 638rpx;
border: white 1px solid;
border-radius: 10px;
padding: 20px;
display: flex;
align-items: center;
justify-items: center;
justify-content: center;
flex-direction: column;
}
.step-point {
z-index: 99;
background: white;
color: #AC1630;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<div style="font-size: 15px;font-weight: lighter;color: #FFF; width: 100%;">
<div class="header-cell">
<span class="header-title">酒庄名称:</span>
<span class="header-value">{{wineryForm.wineryName}}</span>
</div>
<div class="header-cell">
<span class="header-title">酒庄面积:</span>
<span class="header-value">{{wineryForm.wineryArea}}亩</span>
</div>
<div class="header-cell">
<span class="header-title">酒庄成立时间:</span>
<span class="header-value">{{wineryForm.buildTime}}</span>
</div>
<div class="header-cell">
<span class="header-title">酒庄地址:</span>
<span class="header-value">{{wineryForm.region}} {{wineryForm.address}} </span>
</div>
</div>
</div>
<div class="fream">
<div style="width: 558rpx; text-align: left; flex-direction: column;display: flex;">
<sapn style="color: #333;font-size: 20px;font-weight: bold;">填报指南</sapn>
<sapn style="color: #999; font-size: 14px;">您好,仅需三步即可完成自主填报</sapn>
</div>
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/step.png" style="width: 558rpx;margin-top: 16px;" />
</div>
<div style="display: flex;align-items: center; width: 100%;margin: 520rpx 0 25px 0;">
<button class="buttonColor" style="width: 686rpx;" @tap="onNext()">下一步</button>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapState } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
'before-setData': function(dirty) {
if (Math.random() < 0.2) {
console.log('setData canceled')
return false // Cancel setData
}
dirty.time = +new Date()
return dirty
}
},
data: {
},
computed: mapState(['wineryForm']),
methods: {
onNext() {
xiao4rBase.navigateTo('form3')
}
},
created() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,374 @@
<style lang="less">
.header {
width: 100%;
height: 150rpx;
display: flex;
justify-content: center;
}
.cell-full-area {
border: #ddd 1px solid;
border-radius: 8px;
width: 620rpx;
padding: 16px;
margin: 11px 15px;
display: flex;
}
.cell1 {
flex: 1;
display: flex;
}
.cell1-input {
width: 215rpx;
}
.cell2-radio {
margin-left: 22px;
}
.cell3-cheakbox {
margin-top: 10px;
text-align: center;
flex: 0 0 30%;
width: 200rpx;
}
.cell3-cheakbox-checked {
margin-top: 10px;
text-align: center;
flex: 1;
width: 100%;
}
.cell3-input-line {
flex: 1;
display: flex;
font-size: 14px;
text-align: center;
align-items: center;
margin-left: 15px;
margin-top: 5px;
}
.cell3-input {
width: 96rpx;
border: #ddd 1px solid;
background: #FAFAFA;
margin: 5px;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/step1.png" style="width:612rpx; height:120rpx;" />
</div>
<div style="margin-top: 32px;">
<div>
<span class="cell-title">种植总面积</span>
<div class="cell-full-area">
<div class="cell1">
<input class="cell1-input" v-model="wineryForm.plantArea" type="number" placeholder="请输入" />
<span>亩</span>
</div>
<div class="cell1">
<input class="cell1-input" v-model="wineryForm.plantWeight" type="number" placeholder="请输入" />
<span>斤</span>
</div>
</div>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">土壤类型</span>
<van-radio-group value="{{ wineryForm.soilType }}" bind:change="onChangeSoilType">
<div style="display: flex;margin-top: 22px;">
<van-radio v-for="(item,index) in soilTypes" class="cell2-radio" name="{{item}}" checked-color="#AC1630">
{{item}}
</van-radio>
</div>
</van-radio-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 10px">
<span class="cell-title">红葡萄品种</span>
<van-checkbox-group value="{{ wineryForm.redVariety.checked }}" bind:change="onChangeRedVariety">
<div style="display: flex;flex-direction: column;">
<div v-for="(item,index) in wineryForm.redVariety.params">
<div v-if="item.isChecked" style="margin-top: 5px;margin-bottom: 5px;">
<div style="margin-left:20px;">
<van-checkbox name="{{item.name}}" checked-color="#AC1630">{{item.name}}</van-checkbox>
</div>
<div class="cell3-input-line">
<span>种地</span>
<input class="cell3-input" v-model="item.msg.area" type="number" placeholder="请输入" />
<span>亩树龄</span>
<input class="cell3-input" v-model="item.msg.treeOld" type="number" placeholder="请输入" />
<span>年,最大树龄</span>
<input class="cell3-input" v-model="item.msg.treeMaxOld" type="number" placeholder="请输入" />
<span>年</span>
</div>
</div>
</div>
</div>
<div style="display: flex;margin: 5px 15px;flex-wrap: wrap;">
<div v-for="(item,index) in wineryForm.redVariety.params">
<div v-if="!item.isChecked" class="cell3-cheakbox">
<van-checkbox name="{{item.name}}" checked-color="#AC1630">{{item.name}}</van-checkbox>
</div>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 10px">
<span class="cell-title">白葡萄品种</span>
<van-checkbox-group value="{{ wineryForm.whiteVariety.checked }}" bind:change="onChangeWhiteVariety">
<div style="display: flex;flex-direction: column;">
<div v-for="(item,index) in wineryForm.whiteVariety.params">
<div v-if="item.isChecked" style="margin-top: 10px;margin-bottom: 5px;">
<div style="margin-left:20px;">
<van-checkbox name="{{item.name}}" checked-color="#AC1630">{{item.name}}</van-checkbox>
</div>
<div class="cell3-input-line">
<span>种地</span>
<input class="cell3-input" v-model="item.msg.area" type="number" placeholder="请输入" />
<span>亩树龄</span>
<input class="cell3-input" v-model="item.msg.treeOld" type="number" placeholder="请输入" />
<span>年,最大树龄</span>
<input class="cell3-input" v-model="item.msg.treeMaxOld" type="number" placeholder="请输入" />
<span>年</span>
</div>
</div>
</div>
</div>
<div style="display: flex;margin: 5px 15px;flex-wrap: wrap;">
<div v-for="(item,index) in wineryForm.whiteVariety.params">
<div v-if="!item.isChecked" class="cell3-cheakbox">
<van-checkbox name="{{item.name}}" checked-color="#AC1630">{{item.name}}</van-checkbox>
</div>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">主要灌溉方式</span>
<van-radio-group value="{{ wineryForm.irrigationType }}" bind:change="onChangeIrrigationType">
<div style="display: flex;margin-top: 22px;">
<van-radio v-for="(item,index) in irrigationTypes" class="cell2-radio" name="{{item}}"
checked-color="#AC1630">
{{item}}
</van-radio>
</div>
</van-radio-group>
</div>
<div class="boom" />
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor-cancel" style="width: 326rpx;" @tap="onBack()">上一步</button>
<button class="buttonColor" style="width: 326rpx;" @tap="onNext()">下一步</button>
</div>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapActions,mapState } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import xiao4rApis from '../apis/xiao4rApis'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
// 'before-setData': function(dirty) {
// if (Math.random() < 0.2) {
// console.log('setData canceled')
// return false // Cancel setData
// }
// dirty.time = +new Date()
// return dirty
// }
},
data: {
soilTypes: [
'沙石', '砾石', '石灰岩', '混合'
],
irrigationTypes: ['漫灌', '喷灌', '滴灌'],
redVarieties: [
'赤霞珠',
'梅洛',
'品丽珠',
'黑皮诺',
'西拉',
'歌海娜',
'桑娇维塞',
'内比奥罗',
'丹魄',
'马尔贝克',
'其他'
],
whiteVarieties: [
'霞多丽',
'长相思',
'雷司令',
'灰皮诺',
'赛美蓉',
'琼瑶浆',
'其他'
]
},
computed: mapState(['wineryForm']),
watch: {},
methods: {
...mapActions([
'setFormAction'
]),
onChangeSoilType(e) {
this.wineryForm.soilType = e.$wx.detail
},
onChangeIrrigationType(e) {
this.wineryForm.irrigationType = e.$wx.detail
},
onChangeRedVariety(e) {
this.wineryForm.redVariety.checked = e.$wx.detail
this.changeItem(this.wineryForm.redVariety.checked, this.wineryForm.redVariety.params)
},
onChangeWhiteVariety(e) {
console.log(e)
this.wineryForm.whiteVariety.checked = e.$wx.detail
this.changeItem(this.wineryForm.whiteVariety.checked, this.wineryForm.whiteVariety.params)
},
changeItem(types, items) {
for (let i = 0; i < items.length; i++) {
let isChecked = false
for (let j = 0; j < types.length; j++) {
// console.log(types[j])
// console.log(items[i].name)
if (types[j] === items[i].name) {
isChecked = true
break
}
}
items[i].isChecked = isChecked
if (!items[i].isChecked) {
items[i].msg = {
area: '',
treeOld: '',
treeMaxOld: ''
}
}
}
},
initVariety(types, fromList) {
for (let i = 0; i < types.length; i++) {
fromList.push({
name: types[i],
isChecked: false,
msg: {
area: '',
treeOld: '',
treeMaxOld: ''
}
})
}
},
onNext() {
if (!this.wineryForm.plantArea) {
xiao4rBase.showToast('请输入种植面积!')
return
}
if (!this.wineryForm.plantWeight) {
xiao4rBase.showToast('请输入产量!')
return
}
let error = this.checkVariety(this.wineryForm.redVariety)
if (error) {
xiao4rBase.showToast('请检查红葡萄信息:' + error)
return
}
error = this.checkVariety(this.wineryForm.whiteVariety)
if (error) {
xiao4rBase.showToast('请检查白葡萄信息:' + error)
return
}
// this.setFormAction(this.form)
xiao4rBase.navigateTo('form4')
},
onBack() {
// this.setFormAction(this.form)
wx.navigateBack()
},
checkVariety(variety) {
let errorMsg = ''
let isChecked = false
for (let i = 0; i < variety.params.length; i++) {
let item = variety.params[i]
if (item.isChecked) {
isChecked = true
if (!item.msg.area || !item.msg.treeOld || !item.msg.treeMaxOld) {
errorMsg = '请完善' + item.name + '品种信息!'
}
}
}
if (!isChecked) {
errorMsg = '请选择葡萄品种!'
}
return errorMsg
}
},
created() {
if (this.wineryForm.redVariety.params.length < 1) {
this.initVariety(this.redVarieties, this.wineryForm.redVariety.params)
}
if (this.wineryForm.whiteVariety.params.length < 1) {
this.initVariety(this.whiteVarieties, this.wineryForm.whiteVariety.params)
}
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,158 @@
<style lang="less">
.header {
width: 100%;
height: 150rpx;
display: flex;
justify-content: center;
}
.cell-item {
margin-left: 22px;
margin-top: 12px;
width: 300rpx;
}
.cell-item2 {
margin-left: 22px;
margin-top: 12px;
width: 150rpx;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/step2.png" style="width:612rpx; height:120rpx;" />
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">酒精发酵工艺</span>
<van-checkbox-group value="{{ wineryForm.fermentationProcess }}" bind:change="onChangeFermentationProcess">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item" v-for="(item,index) in fermentationProcessType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">热化容器</span>
<van-checkbox-group value="{{ wineryForm.container }}" bind:change="onChangeContainer">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item" v-for="(item,index) in containerType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">澄清方式</span>
<van-checkbox-group value="{{ wineryForm.clarificationMethod }}" bind:change="onChangeClarificationMethod">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item2" v-for="(item,index) in clarificationMethodType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor-cancel" style="width: 326rpx;" @tap="onBack()">上一步</button>
<button class="buttonColor" style="width: 326rpx;" @tap="onNext()">下一步</button>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapActions,mapState } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import xiao4rApis from '../apis/xiao4rApis'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
// 'before-setData': function(dirty) {
// if (Math.random() < 0.2) {
// console.log('setData canceled')
// return false // Cancel setData
// }
// dirty.time = +new Date()
// return dirty
// }
},
data: {
fermentationProcessType: ['冷浸渍', '倒灌', '压帽', '二氧化碳浸渍', '整串发酵', '半二氧化碳浸渍', '酒泥陈酿'],
containerType: ['不锈钢罐', '橡木桶'],
clarificationMethodType: ['沉淀', '下胶', '过滤']
},
computed: mapState(['wineryForm']),
watch: {},
methods: {
onChangeFermentationProcess(e) {
this.wineryForm.fermentationProcess = e.$wx.detail
},
onChangeContainer(e) {
this.wineryForm.container = e.$wx.detail
},
onChangeClarificationMethod(e) {
this.wineryForm.clarificationMethod = e.$wx.detail
},
onNext() {
if (this.wineryForm.fermentationProcess.length < 1) {
xiao4rBase.showToast('请选择酒精发酵工艺!')
return
}
if (this.wineryForm.container.length < 1) {
xiao4rBase.showToast('请选择热化容器!')
return
}
if (this.wineryForm.clarificationMethod.length < 1) {
xiao4rBase.showToast('请选择澄清方式!')
return
}
xiao4rBase.navigateTo('form5')
},
onBack() {
wx.navigateBack()
}
},
created() {
console.log(this.form)
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,242 @@
<style lang="less">
.header {
width: 100%;
height: 150rpx;
display: flex;
justify-content: center;
}
.cell-input {
margin-left: 10px;
margin-top: 12px;
display: flex;
justify-content: center;
align-items: center;
input {
border: #dddddd solid 1px;
border-radius: 8px;
padding: 5px;
width: 572rpx;
margin-right: 10px;
}
}
.cell-item {
margin-left: 22px;
margin-top: 12px;
width: 300rpx;
}
.cell-item2 {
margin-left: 12px;
margin-top: 12px;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/step3.png" style="width:612rpx; height:120rpx;" />
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">年产量</span>
<div class="cell-input">
<input class="input" v-model="wineryForm.annualOutput" type="digit" placeholder="请输入" />
<span>万瓶</span>
</div>
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">现有库存</span>
<div class="cell-input">
<input class="input" v-model="wineryForm.stock" type="digit" placeholder="请输入" />
<span>万瓶</span>
</div>
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">橡木桶数量</span>
<div class="cell-input">
<input class="input" v-model="wineryForm.bucketCount" type="number" placeholder="请输入" />
<span> 个</span>
</div>
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">主要产品定价</span>
<van-checkbox-group value="{{ wineryForm.mainPrice }}" bind:change="onChangeMainPrice">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item" v-for="(item,index) in mainPriceType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title">销售方式</span>
<van-checkbox-group value="{{ wineryForm.salesMode }}" bind:change="onChangeSalesMode">
<div style="display: flex;margin: 5px;flex-wrap: wrap;">
<div class="cell-item2" v-for="(item,index) in salesModeType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<div style="display: flex;align-items: center;">
<span class="cell-title">获奖信息</span>
<span style="font-size: 12px;">(选填)</span>
</div>
<van-checkbox-group value="{{ wineryForm.awards }}" bind:change="onChangeAwards">
<div style="display: flex;margin: 5px 5px;flex-wrap: wrap;">
<div class="cell-item2" v-for="(item,index) in awardType">
<van-checkbox name="{{item}}" checked-color="#AC1630">{{item}}</van-checkbox>
</div>
</div>
</van-checkbox-group>
<div style="display: flex;align-items: center;">
<span class="cell-title">其他奖项</span>
</div>
<div style="margin: 10px;border: #ddd 1px solid; border-radius: 8px;padding: 5px;">
<textarea
v-model="wineryForm.awardInformation "
auto-height="{{false}}"
clearable
autosize
/>
</div>
</div>
<div class="boom" />
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor-cancel" style="width: 326rpx;" @tap="onBack()">上一步</button>
<button class="buttonColor" style="width: 326rpx;" @tap="onNext()">下一步</button>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapState } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import xiao4rApis from '../apis/xiao4rApis'
import validateUtils from '../js/utils/validateUtils'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
// 'before-setData': function(dirty) {
// if (Math.random() < 0.2) {
// console.log('setData canceled')
// return false // Cancel setData
// }
// dirty.time = +new Date()
// return dirty
// }
},
data: {
mainPriceType:
['100以下', '100199', '200299', '300399', '400499', '500599', '600699', '700799', '800899', '900999', '1000或以上'],
salesModeType: ['自销', '渠道代理', '包销', '网销'],
awardType: [
'2017柏林葡萄酒大奖赛',
'2017年第24届布鲁塞尔葡萄酒大赛',
'第六届宁夏贺兰山东麓国际葡萄酒博览会',
'2018柏林葡萄酒大奖赛',
'2018第25届布鲁塞尔葡萄酒大赛',
'2018Decanter品醇客世界葡萄酒大赛',
'2019柏林葡萄酒大奖赛',
'2019Decanter品醇客世界葡萄酒大赛',
'2019第26届布鲁塞尔葡萄酒大赛',
'第八届宁夏贺兰山东麓国际葡萄酒博览会',
'2020柏林葡萄酒大奖赛',
'2020第27届布鲁塞尔葡萄酒大赛',
'第九届宁夏贺兰山东麓国际葡萄酒博览会'
]
},
computed: mapState(['wineryForm']),
watch: {},
methods: {
onChangeMainPrice(e) {
this.wineryForm.mainPrice = e.$wx.detail
},
onChangeSalesMode(e) {
this.wineryForm.salesMode = e.$wx.detail
},
onChangeAwards(e) {
console.log(e.$wx.detail)
this.wineryForm.awards = e.$wx.detail
},
onNext() {
if (!validateUtils.isIntOrDecimal(this.wineryForm.annualOutput)) {
xiao4rBase.showToast('请输入正确的年产量!')
return
}
if (!validateUtils.isIntOrDecimal(this.wineryForm.stock)) {
xiao4rBase.showToast('请输入正确的当前库存!')
return
}
if (!this.wineryForm.bucketCount) {
xiao4rBase.showToast('请输入橡木桶数量!')
return
}
if (this.wineryForm.mainPrice.length < 1) {
xiao4rBase.showToast('请选择主要产品定价!')
return
}
if (this.wineryForm.salesMode.length < 1) {
xiao4rBase.showToast('请选择销售方式!')
return
}
xiao4rBase.navigateTo('form6')
},
onBack() {
wx.navigateBack()
}
},
created() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,204 @@
<style lang="less">
.header {
width: 100%;
height: 150rpx;
display: flex;
justify-content: center;
}
.cell-input {
display: flex;
justify-content: center;
align-items: center;
input {
margin-left: 10px;
border: #dddddd solid 1px;
border-radius: 8px;
padding: 5px 10px;
width: 480rpx;
}
}
input {
margin-left: 8px;
padding: 5px 10px;
width: 480rpx;
}
.cell-item {
margin-left: 22px;
margin-top: 12px;
display: flex;
align-items: center;
}
</style>
<template>
<nav-bar />
<div class="header background-color">
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/step4.png" style="width:612rpx; height:120rpx;" />
</div>
<div
style="margin-top: 32px;margin-bottom: 20px;display: flex;justify-content: center;flex-direction: column;align-items: center;">
<image src="https://www.xiao4r.com/xiao4rstatic/hope_wine/success.png" style="width:110rpx; height:110rpx;" />
<span style="color:#333;margin-top: 24px;">填报完成</span>
<span style="color: #999;margin-top: 8px;font-size: 13px;">感谢您的填报,还有最后一步!</span>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<div class="cell">
<span class="cell-title">姓名</span>
<input
v-model="wineryForm.personName"
center
clearable
placeholder="请输入您的姓名"
/>
<van-divider customStyle="margin: 0 5px;" />
</div>
</div>
<div style="margin-top: 10px;padding-bottom: 20px;">
<div class="cell">
<span class="cell-title">联系邮箱</span>
<input
v-model="wineryForm.email"
center
clearable
placeholder="请输入您的联系邮箱"
/>
<van-divider customStyle="margin: 0 5px;" />
</div>
</div>
<div class="boom" />
<div style="margin-top: 10px;padding-bottom: 20px;">
<span class="cell-title" style="color: #AC1630;">贺兰山产区红酒传播语征集</span>
<van-radio-group value="{{ wineryForm.slogan }}" bind:change="onChangeSlogan">
<div style="display: flex;margin: 5px;flex-direction: column;">
<div class="cell-item" v-for="(item,index) in sloganType">
<div v-if="index === 4" class="cell-input">
<van-radio name="{{item}}" checked-color="#AC1630" />
<input
v-model="slogan"
clearable
placeholder="请输入您的口号"
/>
</div>
<div v-else>
<van-radio name="{{item}}" checked-color="#AC1630">{{item}}</van-radio>
</div>
</div>
</div>
</van-radio-group>
</div>
<div class="boom" />
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor-cancel" style="width: 326rpx;" @tap="onBack()">上一步</button>
<button class="buttonColor" style="width: 326rpx;" @tap="onNext()">提交上报</button>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapState } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import xiao4rApis from '../apis/xiao4rApis'
import validateUtils from '../js/utils/validateUtils'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
// 'before-setData': function(dirty) {
// if (Math.random() < 0.2) {
// console.log('setData canceled')
// return false // Cancel setData
// }
// dirty.time = +new Date()
// return dirty
// }
},
data: {
form: {},
sloganType: ['葡萄酒·贺兰山', '葡萄酒之乡·神奇贺兰山', '中国葡萄酒·当然贺兰山', '中国葡萄酒·要喝贺兰山','其他'],
slogan: ''
},
computed: mapState(['wineryForm']),
watch: {},
methods: {
onChangeSlogan(e) {
this.wineryForm.slogan = e.$wx.detail
},
async onNext() {
if (!this.wineryForm.personName) {
xiao4rBase.showToast('请输入您的姓名!')
return
}
if (!validateUtils.isEmail(this.wineryForm.email)) {
xiao4rBase.showToast('请正确输入您的邮箱!')
return
}
let form = this.wineryForm
if (this.wineryForm.slogan === '其他') {
form.slogan = this.slogan
}
form.openid = xiao4rBase.getOpenid()
wx.showLoading({ title: '正在提交...', mask: true })
try {
let rsp = await xiao4rApis.postForm(form)
if (rsp.code === 200) {
xiao4rBase.showToast('提交成功!')
wx.reLaunch({ url: 'index' })
} else {
xiao4rBase.showToast('提交失败.' + rsp.msg)
}
} catch (e) {
xiao4rBase.showToast('提交失败.', e)
} finally {
wx.hideLoading()
}
},
onBack() {
wx.navigateBack()
}
},
created() {
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,180 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<wxs module="m1" lang="babel">
const getTime = (time) => {
let date = getDate(time);
let hour = date.getHours();
let mins = date.getMinutes();
let sec = date.getSeconds();
let milli = date.getMilliseconds();
return `${hour}:${mins}:${sec}.${milli}`;
}
module.exports.getTime = getTime;
</wxs>
<template>
<image class="header" src="https://www.xiao4r.com/xiao4rstatic/hope_wine/head.png" />
<div class="container" style="margin: 0px 25px;">
<span style="color: #333;font-size: 26px;">贺兰山东麓葡萄酒产区普查</span>
<span style="color: #333;font-size: 13px;">Helan Mountain winery census</span>
<div style="display: flex;flex-direction:column; margin-top: 24px;">
<span style="color: #333;font-size: 16px;">欢迎您参加贺兰山酒庄普查!</span>
<text style="color: #666;font-size: 16px;margin-top: 4px;">
  在宁夏回族自治区政府大力推动以红酒产业为首的九大产业之际为更好的服务我区酒庄及红酒企业自治区红酒局决定于近期开展2021年贺兰山产区酒庄普查。
非常感谢您选择自主填报的方式参加酒庄普查。您通过微信小程序填报的信息会经加密存储在宁夏回族自治区红酒局,数据仅作为服务我区红酒产业总体规划使用。
</text>
</div>
</div>
<div style="display: flex;align-items: center; width: 100%;margin: 25px 0 25px 0;">
<button class="buttonColor" style="width: 686rpx;" @tap="onNext()">已阅知</button>
</div>
</template>
<script>
import wepy from '@wepy/core'
import eventHub from '../common/eventHub'
import store from '../store'
import { mapActions } from '@wepy/x'
import xiao4rBase from '../xiao4rBase'
import xiao4rApis from '../apis/xiao4rApis'
import userApis from '../apis/userApis'
import request from '../js/request'
wepy.page({
store,
hooks: {
// Page 级别 hook, 只对当前 Page 的 setData 生效。
'before-setData': function(dirty) {
if (Math.random() < 0.2) {
console.log('setData canceled')
return false // Cancel setData
}
dirty.time = +new Date()
return dirty
}
},
data: {
user: store.state.user
},
computed: {
testcomputed() {
return 'computed - '
},
openid() {
return store.state.user.openid
}
},
methods: {
...mapActions([
'setUserAction',
'setWineryFormAction'
]),
handleViewTap() {
console.log('handleVieTap clicked')
},
tap() {
},
callAppLaunch() {
eventHub.$emit('app-launch', { a: 1 }, { b: 2 })
},
onNext() {
xiao4rBase.navigateTo('form1')
// xiao4rApis.getAuthTest({ openid: store.state.user.openid }).then(r => {
// wx.navigateToMiniProgram({
// appId: 'wx88736d7d39e2eda6',
// path: 'pages/oauth/authindex',
// extraData: r.data
// })
// })
},
login() {
let self = this
wx.showLoading({ title: '正在连接...', mask: true })
wx.login({
success(res) {
let req = userApis.getSession(res.code)
req.then(rsp => {
if (rsp.data.openid) {
self.init(rsp.data.openid)
} else {
xiao4rBase.showToast('登录失败!' + res.errMsg)
wx.hideLoading()
}
})
// request.requestTaskMap.get(req.taskId).abort()
// console.log('中断请求,req:', req.taskId)
},
fail(res) {
xiao4rBase.showToast('登录失败,正在重试.')
wx.hideLoading()
self.login()
}
})
},
async init(openid) {
let self = this
xiao4rBase.saveOpenid(openid)
wx.getUserInfo({
success(res) {
self.setUserAction({
openid: xiao4rBase.getOpenid(),
userInfo: res.userInfo
})
}
})
await this.getForm()
wx.hideLoading()
},
async getForm() {
try {
let rsp = await xiao4rApis.getForm({ openid: xiao4rBase.getOpenid() })
if (rsp.code === 200) {
let temp = rsp.data
temp.region = temp.region.split(',')
temp.fermentationProcess = temp.fermentationProcess.split(',')
temp.clarificationMethod = temp.clarificationMethod.split(',')
temp.mainPrice = temp.mainPrice.split(',')
temp.salesMode = temp.salesMode.split(',')
temp.container = temp.container.split(',')
temp.awards = temp.awards.split(',')
temp.redVariety = JSON.parse(temp.redVariety)
temp.whiteVariety = JSON.parse(temp.whiteVariety)
this.setWineryFormAction(temp)
}
} catch (e) {
xiao4rBase.showToast('获取用户信息失败.' + e)
}
}
},
ready() {
this.login()
}
})
</script>
<config>
{
navigationBarTitleText: ''
}
</config>

View File

@ -0,0 +1,155 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<wxs module="m1" lang="babel">
const getTime = (time) => {
let date = getDate(time);
let hour = date.getHours();
let mins = date.getMinutes();
let sec = date.getSeconds();
let milli = date.getMilliseconds();
return `${hour}:${mins}:${sec}.${milli}`;
}
module.exports.getTime = getTime;
</wxs>
<template>
<nav-bar title="商品详情" />
<swiper indicator-dots="true" autoplay="true" interval="3000">
<block v-for="(item,index) in goodsImages" wx:key="index">
<swiper-item>
<view class="swiper-item">
<image :src="item" />
</view>
</swiper-item>
</block>
</swiper>
<van-cell title="标题能显示多长标题能显示多长" value="内容能显示多长" label="描述信息描述信息描述信息描述信息描述信息描述信息描述信息描述信息" border="{{ false }}" />
<van-cell title="选择规格" is-link @tap="onShowSpec" />
<div style="margin: 10px 15px;">
<span>商品详情</span>
<div style="margin-top: 10px;">
<rich-text :nodes="detail" />
</div>
</div>
<van-popup
:show="isShowSpec"
closeable
position="bottom"
custom-style="height: 240px"
bind:close="onCloseSpec"
>
<van-card
price="2.00"
desc="描述信息"
title="商品标题"
thumb="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg"
>
<view slot="num" style="float:right;">
<div>{{'已优惠¥xx元'}}</div>
</view>
</van-card>
<van-divider />
<van-row>
<van-col offset="1" span="8">
<div style="display: flex; flex-direction: column;">
<span>购买数量</span>
<span style="font-size: 12px; color: #cccccc;">剩余:xx</span>
</div>
</van-col>
<van-col offset="7" span="8">
<van-stepper :value="count" bind:change="onChangeCount" />
</van-col>
</van-row>
<van-button round type="danger" size="small" style="float:right;margin-top:10px;margin-right: 10px;">下一步</van-button>
</van-popup>
<van-goods-action>
<van-goods-action-icon icon="cart-o" text="购物车" info="5" />
<van-goods-action-icon icon="shop-o" text="酒庄" />
<van-goods-action-button color="#be99ff" text="加入购物车" type="warning" @tap="onShowSpec" />
<van-goods-action-button color="#7232dd" text="立即购买" @tap="onShowSpec" />
</van-goods-action>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
wepy.page({
store,
hooks: {},
data: {
goodsImages: [
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=751441608,3469454349&fm=15&gp=0.jpg'
],
detail: '<p style=\'color: #AC1630\'>富文本详情</p>',
isShowSpec: false,
count: 1
},
computed: {},
methods: {
...mapActions([
'setUserAction',
'setFormAction'
]),
handleViewTap() {
console.log('handleVieTap clicked')
},
tap() {
},
onShowSpec() {
this.isShowSpec = true
},
onCloseSpec() {
this.isShowSpec = false
},
onChangeCount(e) {
console.log(e)
},
callAppLaunch() {
}
},
ready() {
}
})
</script>
<config>
{
navigationBarTitleText: '',
usingComponents: {
"van-goods-action": "../../vant/goods-action/index",
"van-goods-action-icon": "../../vant/goods-action-icon/index",
"van-goods-action-button": "../../vant/goods-action-button/index"
}
}
</config>

View File

@ -0,0 +1,139 @@
<style lang="less">
.header {
width: 100%;
height: 536rpx;
z-index: -10;
}
</style>
<wxs module="m1" lang="babel">
const getTime = (time) => {
let date = getDate(time);
let hour = date.getHours();
let mins = date.getMinutes();
let sec = date.getSeconds();
let milli = date.getMilliseconds();
return `${hour}:${mins}:${sec}.${milli}`;
}
module.exports.getTime = getTime;
</wxs>
<template>
<van-tabbar active="{{ pageIndex }}" bind:change="onChange">
<van-tabbar-item icon="home-o">热点</van-tabbar-item>
<van-tabbar-item icon="shopping-cart-o">购物</van-tabbar-item>
<van-tabbar-item icon="comment-o">交流</van-tabbar-item>
<van-tabbar-item icon="shopping-cart-o">购物车</van-tabbar-item>
<van-tabbar-item icon="user-o">我的</van-tabbar-item>
</van-tabbar>
<mall-home v-if="pageIndex === 0" />
<mall-shopping v-else-if="pageIndex === 1" />
<mall-bbs v-else-if="pageIndex === 2" />
<mall-car v-else-if="pageIndex === 3" />
<mall-my v-else-if="pageIndex === 4" />
<dialog-registration />
<van-button @tap="onTest" >测试</van-button>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import { mapActions } from '@wepy/x'
import userApis from '../../apis/userApis'
import xiao4rBase from '../../xiao4rBase'
import eventHub from '../../common/eventHub'
wepy.page({
store,
hooks: {
},
data: {
pageIndex: 0
},
computed: {
},
methods: {
...mapActions([
'setUserAction',
'setTokenAction',
'setOpenidAction',
]),
onTest() {
eventHub.$emit('onShowDialogUserInfo')
},
handleViewTap() {
console.log('handleVieTap clicked')
},
tap() {
},
onChange(event) {
this.pageIndex = event.$wx.detail
},
callAppLaunch() {
},
login() {
let self = this
wx.showLoading({ title: '正在连接...', mask: true })
wx.login({
success(res) {
let req = userApis.getSession(res.code)
req.then(rsp => {
if (rsp.data.openid) {
self.init(rsp.data.openid)
} else {
xiao4rBase.showToast('登录失败!' + res.errMsg)
wx.hideLoading()
}
}).catch(e => {
xiao4rBase.showToast('登录失败!' + res.errMsg)
})
// request.requestTaskMap.get(req.taskId).abort()
// console.log('中断请求,req:', req.taskId)
},
fail(res) {
xiao4rBase.showToast('登录失败,正在重试.')
wx.hideLoading()
self.login()
}
})
},
async init(openid) {
xiao4rBase.saveOpenid(openid)
let rsp = await userApis.loginByMini({openid: openid})
if (rsp.token) {
this.setTokenAction(rsp.token)
}
wx.hideLoading()
}
},
ready() {
this.login()
},
onShow() {
}
})
</script>
<config>
{
navigationBarTitleText: '',
usingComponents: {
'mall-home': '../../components/mall/mall-home',
'mall-shopping': '../../components/mall/mall-shopping',
'mall-bbs': '../../components/mall/mall-bbs',
'mall-car': '../../components/mall/mall-car',
'mall-my': '../../components/mall/mall-my',
'dialog-registration': '../../components/user/dialog-registration'
}
}
</config>

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

View File

@ -0,0 +1,59 @@
import Vuex from '@wepy/x'
import { wineryForm } from './wineryForm'
export default new Vuex.Store({
state: {
user: {
openid: '',
mobile: '',
userInfo: {},
token: ''
},
wineryForm
},
mutations: {
setUser(state, user) {
state.user = user
},
setOpenid(state, openid) {
state.user.openid = openid
console.log('state.user.openid:', state.user.openid)
},
setMobile(state, mobile) {
state.user.mobile = mobile
},
setUserInfo(state, userInfo) {
state.user.userInfo = userInfo
},
setToken(state, token) {
state.user.token = token
},
setWineryForm(state, form) {
console.log('远程酒庄表单:', form)
state.wineryForm = form
console.log('本地酒庄表单:', state.wineryForm)
}
},
actions: {
setUserAction({ commit }, user) {
commit('setUser', user)
},
setOpenidAction({ commit }, openid) {
commit('setOpenid', openid)
},
setMobileAction({ commit }, user) {
commit('setMobile', user)
},
setUserInfoAction({ commit }, userInfo) {
commit('setUserInfo', userInfo)
},
setTokenAction({ commit }, token) {
commit('setToken', token)
},
setWineryFormAction({ commit }, form) {
commit('setWineryForm', form)
}
}
})

View File

@ -0,0 +1,37 @@
export const wineryForm = {
openid: '',
email: '',
personName: '',
mobile: '',
wineryName: '', // 酒庄名称(具体)
buildTime: '', // 建立时间(具体)
region: ['宁夏回族自治区', '银川市', '西夏区'], // 酒庄地址(区)
address: '', // 酒庄地址(具体)
wineryArea: '', // 总面积
buildArea: '', // 建筑面积
wineryStatus: '已建成投产', // 酒庄现状
plantArea: '', // 面积(亩)
plantWeight: '', // 产量(斤)
soilType: '沙粒', // 土壤类型
redVariety: {
params: [],
checked: []
}, // 红葡萄品种
whiteVariety: {
params: [],
checked: []
}, // 白葡萄品种
irrigationType: '漫灌', // 灌溉方式
fermentationProcess: [], // 发酵工艺
container: [], // 热化容器
clarificationMethod: [], // 澄清方式
annualOutput: '', // 年产量
stock: '', // 库存
bucketCount: '', // 酒桶数量
mainPrice: [], // 主要产品定价
salesMode: [], // 销售方式
awards: [], // 获奖信息
awardInformation: '', // 获奖信息
slogan: '葡萄酒·贺兰山' // 征集口号
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,62 @@
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true,
},
zIndex: {
type: Number,
value: 100,
},
actions: {
type: Array,
value: [],
},
overlay: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
closeOnClickAction: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.$emit('select', item);
if (this.data.closeOnClickAction) {
this.onClose();
}
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
},
},
});

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}

View File

@ -0,0 +1,69 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup
show="{{ show }}"
position="bottom"
round="{{ round }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view wx:if="{{ title }}" class="van-action-sheet__header">
{{ title }}
<van-icon
name="cross"
custom-class="van-action-sheet__close"
bind:click="onClose"
/>
</view>
<view wx:if="{{ description }}" class="van-action-sheet__description van-hairline--bottom">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view防止actions动态变化导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
open-type="{{ item.openType }}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
bind:tap="onSelect"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
lang="{{ lang }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
>
<block wx:if="{{ !item.loading }}">
{{ item.name }}
<view wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</view>
</block>
<van-loading wx:else custom-class="van-action-sheet__loading" size="22px" />
</button>
</view>
<slot />
<block wx:if="{{ cancelText }}">
<view class="van-action-sheet__gap" />
<view
class="van-action-sheet__cancel"
hover-class="van-action-sheet__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
</block>
</van-popup>

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{padding:14px 16px;text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:22px;line-height:var(--action-sheet-item-line-height,22px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:after,.van-action-sheet__item:after{border-width:0}.van-action-sheet__cancel{color:#646566;color:var(--action-sheet-cancel-text-color,#646566)}.van-action-sheet__gap{display:block;height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f7f8fa;background-color:var(--action-sheet-cancel-padding-color,#f7f8fa)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-top:8px;margin-top:var(--padding-xs,8px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#969799;color:var(--action-sheet-subname-color,#969799);line-height:20px;line-height:var(--action-sheet-subname-line-height,20px)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:48px;line-height:var(--action-sheet-header-height,48px)}.van-action-sheet__description{text-align:center;padding:20px 16px;padding:20px var(--padding-md,16px);color:#969799;color:var(--action-sheet-description-color,#969799);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 16px;padding:var(--action-sheet-close-icon-padding,0 16px);font-size:22px!important;font-size:var(--action-sheet-close-icon-size,22px)!important;color:#c8c9cc;color:var(--action-sheet-close-icon-color,#c8c9cc)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important}

1
mini-app/src/vant/area/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,232 @@
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
import { requestAnimationFrame } from '../common/utils';
const EMPTY_CODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), {
value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
},
},
areaList: {
type: Object,
value: {},
observer: 'setValues',
},
columnsNum: {
type: null,
value: 3,
},
columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
},
});
},
},
}),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {},
},
mounted() {
requestAnimationFrame(() => {
this.setValues();
});
},
methods: {
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel(event) {
this.emit('cancel', event.detail);
},
onConfirm(event) {
const { index } = event.detail;
let { value } = event.detail;
value = this.parseValues(value);
this.emit('confirm', { value, index });
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
parseValues(values) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
if (
value &&
(!value.code || value.name === columnsPlaceholder[index])
) {
return Object.assign(Object.assign({}, value), {
code: '',
name: '',
});
}
return value;
});
},
onChange(event) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
this.setValues().then(() => {
this.$emit('change', {
picker,
values: this.parseValues(picker.getValues()),
index,
});
});
},
getConfig(type) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
if (type !== 'province' && !code) {
return [];
}
const { typeToColumnsPlaceholder } = this.data;
const list = this.getConfig(type);
let result = Object.keys(list).map((code) => ({
code,
name: list[code],
}));
if (code != null) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter((item) => item.code.indexOf(code) === 0);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill =
type === 'province'
? ''
: type === 'city'
? EMPTY_CODE.slice(2, 4)
: EMPTY_CODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type],
});
}
return result;
},
getIndex(type, code) {
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
const list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (let i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues() {
const picker = this.getPicker();
if (!picker) {
return;
}
let code = this.code || this.getDefaultCode();
const provinceList = this.getList('province');
const cityList = this.getList('city', code.slice(0, 2));
const stack = [];
const indexes = [];
const { columnsNum } = this.data;
if (columnsNum >= 1) {
stack.push(picker.setColumnValues(0, provinceList, false));
indexes.push(this.getIndex('province', code));
}
if (columnsNum >= 2) {
stack.push(picker.setColumnValues(1, cityList, false));
indexes.push(this.getIndex('city', code));
if (cityList.length && code.slice(2, 4) === '00') {
[{ code }] = cityList;
}
}
if (columnsNum === 3) {
stack.push(
picker.setColumnValues(
2,
this.getList('county', code.slice(0, 4)),
false
)
);
indexes.push(this.getIndex('county', code));
}
return Promise.all(stack)
.catch(() => {})
.then(() => picker.setIndexes(indexes))
.catch(() => {});
},
getDefaultCode() {
const { columnsPlaceholder } = this.data;
if (columnsPlaceholder.length) {
return EMPTY_CODE;
}
const countyCodes = Object.keys(this.getConfig('county'));
if (countyCodes[0]) {
return countyCodes[0];
}
const cityCodes = Object.keys(this.getConfig('city'));
if (cityCodes[0]) {
return cityCodes[0];
}
return '';
},
getValues() {
const picker = this.getPicker();
if (!picker) {
return [];
}
return this.parseValues(picker.getValues().filter((value) => !!value));
},
getDetail() {
const values = this.getValues();
const area = {
code: '',
country: '',
province: '',
city: '',
county: '',
};
if (!values.length) {
return area;
}
const names = values.map((item) => item.name);
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
} else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset(code) {
this.code = code || '';
return this.setValues();
},
},
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}

View File

@ -0,0 +1,20 @@
<wxs src="./index.wxs" module="computed" />
<van-picker
class="van-area__picker"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
show-toolbar
value-key="name"
title="{{ title }}"
loading="{{ loading }}"
columns="{{ computed.displayColumns(columns, columnsNum) }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
cancel-button-text="{{ cancelButtonText }}"
confirm-button-text="{{ confirmButtonText }}"
bind:change="onChange"
bind:confirm="onConfirm"
bind:cancel="onCancel"
/>

View File

@ -0,0 +1,8 @@
/* eslint-disable */
function displayColumns(columns, columnsNum) {
return columns.slice(0, +columnsNum);
}
module.exports = {
displayColumns: displayColumns,
};

View File

@ -0,0 +1 @@
@import '../common/index.wxss';

1
mini-app/src/vant/button/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,58 @@
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
import { canIUseFormFieldButton } from '../common/version';
const mixins = [button, openType];
if (canIUseFormFieldButton()) {
mixins.push('wx://form-field-button');
}
VantComponent({
mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick() {
if (!this.data.loading) {
this.$emit('click');
}
},
noop() {},
},
});

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}

View File

@ -0,0 +1,53 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<button
id="{{ id }}"
data-detail="{{ dataset }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
form-type="{{ formType }}"
style="{{ computed.rootStyle({ plain, color }) }} {{ customStyle }}"
open-type="{{ disabled ? '' : openType }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
>
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
type="{{ loadingType }}"
color="{{ computed.loadingColor({ type, color, plain }) }}"
/>
<view wx:if="{{ loadingText }}" class="van-button__loading-text">
{{ loadingText }}
</view>
</block>
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class-prefix="{{ classPrefix }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
<view class="van-button__text">
<slot />
</view>
</block>
</button>

View File

@ -0,0 +1,39 @@
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return '';
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style(properties);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);line-height:20px;line-height:var(--button-line-height,20px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background:#fff;background:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background:#07c160;background:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background:#1989fa;background:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background:#ee0a24;background:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background:#ff976a;background:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background:#fff;background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}

View File

@ -0,0 +1,57 @@
<wxs src="./index.wxs" module="computed"></wxs>
<template name="calendar">
<view class="van-calendar">
<header
title="{{ title }}"
showTitle="{{ showTitle }}"
subtitle="{{ subtitle }}"
showSubtitle="{{ showSubtitle }}"
>
<slot name="title" slot="title"></slot>
</header>
<scroll-view class="van-calendar__body" scroll-y scroll-into-view="{{ scrollIntoView }}">
<month
wx:for="{{ computed.getMonths(minDate, maxDate) }}"
wx:key="index"
id="month{{ index }}"
class="month"
data-date="{{ item }}"
date="{{ item }}"
type="{{ type }}"
color="{{ color }}"
minDate="{{ minDate }}"
maxDate="{{ maxDate }}"
showMark="{{ showMark }}"
formatter="{{ formatter }}"
rowHeight="{{ rowHeight }}"
currentDate="{{ currentDate }}"
showSubtitle="{{ showSubtitle }}"
allowSameDay="{{ allowSameDay }}"
showMonthTitle="{{ index !== 0 || !showSubtitle }}"
bind:click="onClickDay"
/>
</scroll-view>
<view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
<slot name="footer"></slot>
</view>
<view class="van-calendar__footer {{ safeAreaInsetBottom ? 'van-calendar__footer--safe-area-inset-bottom' : '' }}">
<van-button
wx:if="{{ showConfirm }}"
round
block
type="danger"
color="{{ color }}"
custom-class="van-calendar__confirm"
disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
nativeType="text"
bind:click="onConfirm"
>
{{ computed.getButtonDisabled(type, currentDate) ? confirmDisabledText : confirmText }}
</van-button>
</view>
</view>
</template>

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,16 @@
import { VantComponent } from '../../../common/component';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
subtitle: String,
showTitle: Boolean,
showSubtitle: Boolean,
},
data: {
weekdays: ['日', '一', '二', '三', '四', '五', '六'],
},
methods: {},
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1,16 @@
<view class="van-calendar__header">
<block wx:if="{{ showTitle }}">
<view class="van-calendar__header-title"><slot name="title"></slot></view>
<view class="van-calendar__header-title">{{ title }}</view>
</block>
<view wx:if="{{ showSubtitle }}" class="van-calendar__header-subtitle">
{{ subtitle }}
</view>
<view class="van-calendar__weekdays">
<view wx:for="{{ weekdays }}" wx:key="index" class="van-calendar__weekday">
{{ item }}
</view>
</view>
</view>

View File

@ -0,0 +1 @@
@import '../../../common/index.wxss';.van-calendar__header{-webkit-flex-shrink:0;flex-shrink:0;box-shadow:0 2px 10px rgba(125,126,128,.16);box-shadow:var(--calendar-header-box-shadow,0 2px 10px rgba(125,126,128,.16))}.van-calendar__header-subtitle,.van-calendar__header-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__header-title+.van-calendar__header-title,.van-calendar__header-title:empty{display:none}.van-calendar__header-title:empty+.van-calendar__header-title{display:block!important}.van-calendar__weekdays{display:-webkit-flex;display:flex}.van-calendar__weekday{-webkit-flex:1;flex:1;text-align:center;font-size:12px;font-size:var(--calendar-weekdays-font-size,12px);line-height:30px;line-height:var(--calendar-weekdays-height,30px)}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,157 @@
import { VantComponent } from '../../../common/component';
import {
getMonthEndDay,
compareDay,
getPrevDay,
getNextDay,
} from '../../utils';
VantComponent({
props: {
date: {
type: null,
observer: 'setDays',
},
type: {
type: String,
observer: 'setDays',
},
color: String,
minDate: {
type: null,
observer: 'setDays',
},
maxDate: {
type: null,
observer: 'setDays',
},
showMark: Boolean,
rowHeight: [Number, String],
formatter: {
type: null,
observer: 'setDays',
},
currentDate: {
type: [null, Array],
observer: 'setDays',
},
allowSameDay: Boolean,
showSubtitle: Boolean,
showMonthTitle: Boolean,
},
data: {
visible: true,
days: [],
},
methods: {
onClick(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.days[index];
if (item.type !== 'disabled') {
this.$emit('click', item);
}
},
setDays() {
const days = [];
const startDate = new Date(this.data.date);
const year = startDate.getFullYear();
const month = startDate.getMonth();
const totalDay = getMonthEndDay(
startDate.getFullYear(),
startDate.getMonth() + 1
);
for (let day = 1; day <= totalDay; day++) {
const date = new Date(year, month, day);
const type = this.getDayType(date);
let config = {
date,
type,
text: day,
bottomInfo: this.getBottomInfo(type),
};
if (this.data.formatter) {
config = this.data.formatter(config);
}
days.push(config);
}
this.setData({ days });
},
getMultipleDayType(day) {
const { currentDate } = this.data;
if (!Array.isArray(currentDate)) {
return '';
}
const isSelected = (date) =>
currentDate.some((item) => compareDay(item, date) === 0);
if (isSelected(day)) {
const prevDay = getPrevDay(day);
const nextDay = getNextDay(day);
const prevSelected = isSelected(prevDay);
const nextSelected = isSelected(nextDay);
if (prevSelected && nextSelected) {
return 'multiple-middle';
}
if (prevSelected) {
return 'end';
}
return nextSelected ? 'start' : 'multiple-selected';
}
return '';
},
getRangeDayType(day) {
const { currentDate, allowSameDay } = this.data;
if (!Array.isArray(currentDate)) {
return;
}
const [startDay, endDay] = currentDate;
if (!startDay) {
return;
}
const compareToStart = compareDay(day, startDay);
if (!endDay) {
return compareToStart === 0 ? 'start' : '';
}
const compareToEnd = compareDay(day, endDay);
if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
return 'start-end';
}
if (compareToStart === 0) {
return 'start';
}
if (compareToEnd === 0) {
return 'end';
}
if (compareToStart > 0 && compareToEnd < 0) {
return 'middle';
}
},
getDayType(day) {
const { type, minDate, maxDate, currentDate } = this.data;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
return 'disabled';
}
if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : '';
}
if (type === 'multiple') {
return this.getMultipleDayType(day);
}
/* istanbul ignore else */
if (type === 'range') {
return this.getRangeDayType(day);
}
},
getBottomInfo(type) {
if (this.data.type === 'range') {
if (type === 'start') {
return '开始';
}
if (type === 'end') {
return '结束';
}
if (type === 'start-end') {
return '开始/结束';
}
}
},
},
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1,39 @@
<wxs src="./index.wxs" module="computed"></wxs>
<wxs src="../../../wxs/utils.wxs" module="utils" />
<view class="van-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
<view wx:if="{{ showMonthTitle }}" class="van-calendar__month-title">
{{ computed.formatMonthTitle(date) }}
</view>
<view wx:if="{{ visible }}" class="van-calendar__days">
<view wx:if="{{ showMark }}" class="van-calendar__month-mark">
{{ computed.getMark(date) }}
</view>
<view
wx:for="{{ days }}"
wx:key="index"
style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
data-index="{{ index }}"
bindtap="onClick"
>
<view wx:if="{{ item.type === 'selected' }}" class="van-calendar__selected-day" style="background: {{ color }}">
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
<view wx:else>
<view wx:if="{{ item.topInfo }}" class="van-calendar__top-info">{{ item.topInfo }}</view>
{{ item.text }}
<view wx:if="{{ item.bottomInfo }}" class="van-calendar__bottom-info">
{{ item.bottomInfo }}
</view>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,67 @@
/* eslint-disable */
var utils = require('../../utils.wxs');
function getMark(date) {
return getDate(date).getMonth() + 1;
}
var ROW_HEIGHT = 64;
function getDayStyle(type, index, date, rowHeight, color) {
var style = [];
var offset = getDate(date).getDay();
if (index === 0) {
style.push(['margin-left', (100 * offset) / 7 + '%']);
}
if (rowHeight !== ROW_HEIGHT) {
style.push(['height', rowHeight + 'px']);
}
if (color) {
if (
type === 'start' ||
type === 'end' ||
type === 'multiple-selected' ||
type === 'multiple-middle'
) {
style.push(['background', color]);
} else if (type === 'middle') {
style.push(['color', color]);
}
}
return style
.map(function(item) {
return item.join(':');
})
.join(';');
}
function formatMonthTitle(date) {
date = getDate(date);
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
}
function getMonthStyle(visible, date, rowHeight) {
if (!visible) {
date = getDate(date);
var totalDay = utils.getMonthEndDay(
date.getFullYear(),
date.getMonth() + 1
);
var offset = getDate(date).getDay();
var padding = Math.ceil((totalDay + offset) / 7) * rowHeight;
return 'padding-bottom:' + padding + 'px';
}
}
module.exports = {
getMark: getMark,
getDayStyle: getDayStyle,
formatMonthTitle: formatMonthTitle,
getMonthStyle: getMonthStyle
};

View File

@ -0,0 +1 @@
@import '../../../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__month-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:14px;font-size:var(--calendar-month-title-font-size,14px);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__days{position:relative;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{position:absolute;top:50%;left:50%;z-index:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);pointer-events:none;color:rgba(242,243,245,.8);color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:160px;font-size:var(--calendar-month-mark-font-size,160px)}.van-calendar__day,.van-calendar__selected-day{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;text-align:center}.van-calendar__day{position:relative;width:14.285%;height:64px;height:var(--calendar-day-height,64px);font-size:16px;font-size:var(--calendar-day-font-size,16px)}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{color:#fff;color:var(--calendar-range-edge-color,#fff);background-color:#ee0a24;background-color:var(--calendar-range-edge-background-color,#ee0a24)}.van-calendar__day--start{border-radius:4px 0 0 4px;border-radius:var(--border-radius-md,4px) 0 0 var(--border-radius-md,4px)}.van-calendar__day--end{border-radius:0 4px 4px 0;border-radius:0 var(--border-radius-md,4px) var(--border-radius-md,4px) 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px;border-radius:var(--border-radius-md,4px)}.van-calendar__day--middle{color:#ee0a24;color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{position:absolute;top:0;right:0;bottom:0;left:0;background-color:currentColor;content:"";opacity:.1;opacity:var(--calendar-range-middle-background-opacity,.1)}.van-calendar__day--disabled{cursor:default;color:#c8c9cc;color:var(--calendar-day-disabled-color,#c8c9cc)}.van-calendar__bottom-info,.van-calendar__top-info{position:absolute;right:0;left:0;font-size:10px;font-size:var(--calendar-info-font-size,10px);line-height:14px;line-height:var(--calendar-info-line-height,14px)}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{width:54px;width:var(--calendar-selected-day-size,54px);height:54px;height:var(--calendar-selected-day-size,54px);color:#fff;color:var(--calendar-selected-day-color,#fff);background-color:#ee0a24;background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;border-radius:var(--border-radius-md,4px)}

1
mini-app/src/vant/calendar/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,297 @@
import { VantComponent } from '../common/component';
import {
ROW_HEIGHT,
getNextDay,
compareDay,
copyDates,
calcDateNum,
formatMonthTitle,
compareMonth,
getMonths,
getDayByOffset,
} from './utils';
import Toast from '../toast/toast';
import { requestAnimationFrame } from '../common/utils';
VantComponent({
props: {
title: {
type: String,
value: '日期选择',
},
color: String,
show: {
type: Boolean,
observer(val) {
if (val) {
this.initRect();
this.scrollIntoView();
}
},
},
formatter: null,
confirmText: {
type: String,
value: '确定',
},
rangePrompt: String,
defaultDate: {
type: [Number, Array],
observer(val) {
this.setData({ currentDate: val });
this.scrollIntoView();
},
},
allowSameDay: Boolean,
confirmDisabledText: String,
type: {
type: String,
value: 'single',
observer: 'reset',
},
minDate: {
type: null,
value: Date.now(),
},
maxDate: {
type: null,
value: new Date(
new Date().getFullYear(),
new Date().getMonth() + 6,
new Date().getDate()
).getTime(),
},
position: {
type: String,
value: 'bottom',
},
rowHeight: {
type: [Number, String],
value: ROW_HEIGHT,
},
round: {
type: Boolean,
value: true,
},
poppable: {
type: Boolean,
value: true,
},
showMark: {
type: Boolean,
value: true,
},
showTitle: {
type: Boolean,
value: true,
},
showConfirm: {
type: Boolean,
value: true,
},
showSubtitle: {
type: Boolean,
value: true,
},
safeAreaInsetBottom: {
type: Boolean,
value: true,
},
closeOnClickOverlay: {
type: Boolean,
value: true,
},
maxRange: {
type: [Number, String],
value: null,
},
},
data: {
subtitle: '',
currentDate: null,
scrollIntoView: '',
},
created() {
this.setData({
currentDate: this.getInitialDate(),
});
},
mounted() {
if (this.data.show || !this.data.poppable) {
this.initRect();
this.scrollIntoView();
}
},
methods: {
reset() {
this.setData({ currentDate: this.getInitialDate() });
this.scrollIntoView();
},
initRect() {
if (this.contentObserver != null) {
this.contentObserver.disconnect();
}
const contentObserver = this.createIntersectionObserver({
thresholds: [0, 0.1, 0.9, 1],
observeAll: true,
});
this.contentObserver = contentObserver;
contentObserver.relativeTo('.van-calendar__body');
contentObserver.observe('.month', (res) => {
if (res.boundingClientRect.top <= res.relativeRect.top) {
// @ts-ignore
this.setData({ subtitle: formatMonthTitle(res.dataset.date) });
}
});
},
getInitialDate() {
const { type, defaultDate, minDate } = this.data;
if (type === 'range') {
const [startDay, endDay] = defaultDate || [];
return [
startDay || minDate,
endDay || getNextDay(new Date(minDate)).getTime(),
];
}
if (type === 'multiple') {
return defaultDate || [minDate];
}
return defaultDate || minDate;
},
scrollIntoView() {
requestAnimationFrame(() => {
const {
currentDate,
type,
show,
poppable,
minDate,
maxDate,
} = this.data;
// @ts-ignore
const targetDate = type === 'single' ? currentDate : currentDate[0];
const displayed = show || !poppable;
if (!targetDate || !displayed) {
return;
}
const months = getMonths(minDate, maxDate);
months.some((month, index) => {
if (compareMonth(month, targetDate) === 0) {
this.setData({ scrollIntoView: `month${index}` });
return true;
}
return false;
});
});
},
onOpen() {
this.$emit('open');
},
onOpened() {
this.$emit('opened');
},
onClose() {
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onClickDay(event) {
const { date } = event.detail;
const { type, currentDate, allowSameDay } = this.data;
if (type === 'range') {
// @ts-ignore
const [startDay, endDay] = currentDate;
if (startDay && !endDay) {
const compareToStart = compareDay(date, startDay);
if (compareToStart === 1) {
this.select([startDay, date], true);
} else if (compareToStart === -1) {
this.select([date, null]);
} else if (allowSameDay) {
this.select([date, date]);
}
} else {
this.select([date, null]);
}
} else if (type === 'multiple') {
let selectedIndex;
// @ts-ignore
const selected = currentDate.some((dateItem, index) => {
const equal = compareDay(dateItem, date) === 0;
if (equal) {
selectedIndex = index;
}
return equal;
});
if (selected) {
// @ts-ignore
const cancelDate = currentDate.splice(selectedIndex, 1);
this.setData({ currentDate });
this.unselect(cancelDate);
} else {
// @ts-ignore
this.select([...currentDate, date]);
}
} else {
this.select(date, true);
}
},
unselect(dateArray) {
const date = dateArray[0];
if (date) {
this.$emit('unselect', copyDates(date));
}
},
select(date, complete) {
if (complete && this.data.type === 'range') {
const valid = this.checkRange(date);
if (!valid) {
// auto selected to max range if showConfirm
if (this.data.showConfirm) {
this.emit([
date[0],
getDayByOffset(date[0], this.data.maxRange - 1),
]);
} else {
this.emit(date);
}
return;
}
}
this.emit(date);
if (complete && !this.data.showConfirm) {
this.onConfirm();
}
},
emit(date) {
const getTime = (date) => (date instanceof Date ? date.getTime() : date);
this.setData({
currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date),
});
this.$emit('select', copyDates(date));
},
checkRange(date) {
const { maxRange, rangePrompt } = this.data;
if (maxRange && calcDateNum(date) > maxRange) {
Toast({
context: this,
message: rangePrompt || `选择天数不能超过 ${maxRange}`,
});
return false;
}
return true;
},
onConfirm() {
if (
this.data.type === 'range' &&
!this.checkRange(this.data.currentDate)
) {
return;
}
wx.nextTick(() => {
// @ts-ignore
this.$emit('confirm', copyDates(this.data.currentDate));
});
},
},
});

View File

@ -0,0 +1,10 @@
{
"component": true,
"usingComponents": {
"header": "./components/header/index",
"month": "./components/month/index",
"van-button": "../button/index",
"van-popup": "../popup/index",
"van-toast": "../toast/index"
}
}

View File

@ -0,0 +1,31 @@
<wxs src="./index.wxs" module="computed" />
<import src="./calendar.wxml" />
<van-popup
wx:if="{{ poppable }}"
custom-class="van-calendar__popup--{{ position }}"
close-icon-class="van-calendar__close-icon"
show="{{ show }}"
round="{{ round }}"
position="{{ position }}"
closeable="{{ showTitle || showSubtitle }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:enter="onOpen"
bind:close="onClose"
bind:after-enter="onOpened"
bind:after-leave="onClosed"
>
<template
is="calendar"
data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
/>
</van-popup>
<template
wx:else
is="calendar"
data="{{ title, subtitle, showTitle, showSubtitle, minDate, maxDate, type, color, showMark, formatter, rowHeight, currentDate, safeAreaInsetBottom, showConfirm, confirmDisabledText, confirmText, scrollIntoView, allowSameDay }}"
/>
<van-toast id="van-toast" />

View File

@ -0,0 +1,37 @@
/* eslint-disable */
var utils = require('./utils.wxs');
function getMonths(minDate, maxDate) {
var months = [];
var cursor = getDate(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
return months;
}
function getButtonDisabled(type, currentDate) {
if (currentDate == null) {
return true;
}
if (type === 'range') {
return !currentDate[0] || !currentDate[1];
}
if (type === 'multiple') {
return !currentDate.length;
}
return !currentDate;
}
module.exports = {
getMonths: getMonths,
getButtonDisabled: getButtonDisabled
};

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-calendar{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;height:100%;height:var(--calendar-height,100%);background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__close-icon{top:11px}.van-calendar__popup--bottom,.van-calendar__popup--top{height:80%;height:var(--calendar-popup-height,80%)}.van-calendar__popup--left,.van-calendar__popup--right{height:100%}.van-calendar__body{-webkit-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch}.van-calendar__footer{-webkit-flex-shrink:0;flex-shrink:0;padding:0 16px;padding:0 var(--padding-md,16px)}.van-calendar__footer--safe-area-inset-bottom{padding-bottom:env(safe-area-inset-bottom)}.van-calendar__footer+.van-calendar__footer,.van-calendar__footer:empty{display:none}.van-calendar__footer:empty+.van-calendar__footer{display:block!important}.van-calendar__confirm{height:36px!important;height:var(--calendar-confirm-button-height,36px)!important;margin:7px 0!important;margin:var(--calendar-confirm-button-margin,7px 0)!important;line-height:34px!important;line-height:var(--calendar-confirm-button-line-height,34px)!important}

17
mini-app/src/vant/calendar/utils.d.ts vendored Normal file
View File

@ -0,0 +1,17 @@
export declare const ROW_HEIGHT = 64;
export declare function formatMonthTitle(date: Date): string;
export declare function compareMonth(
date1: Date | number,
date2: Date | number
): 0 | 1 | -1;
export declare function compareDay(
day1: Date | number,
day2: Date | number
): 0 | 1 | -1;
export declare function getDayByOffset(date: Date, offset: number): Date;
export declare function getPrevDay(date: Date): Date;
export declare function getNextDay(date: Date): Date;
export declare function calcDateNum(date: [Date, Date]): number;
export declare function copyDates(dates: Date | Date[]): Date | Date[];
export declare function getMonthEndDay(year: number, month: number): number;
export declare function getMonths(minDate: number, maxDate: number): number[];

View File

@ -0,0 +1,78 @@
export const ROW_HEIGHT = 64;
export function formatMonthTitle(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
return `${date.getFullYear()}${date.getMonth() + 1}`;
}
export function compareMonth(date1, date2) {
if (!(date1 instanceof Date)) {
date1 = new Date(date1);
}
if (!(date2 instanceof Date)) {
date2 = new Date(date2);
}
const year1 = date1.getFullYear();
const year2 = date2.getFullYear();
const month1 = date1.getMonth();
const month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
export function compareDay(day1, day2) {
if (!(day1 instanceof Date)) {
day1 = new Date(day1);
}
if (!(day2 instanceof Date)) {
day2 = new Date(day2);
}
const compareMonthResult = compareMonth(day1, day2);
if (compareMonthResult === 0) {
const date1 = day1.getDate();
const date2 = day2.getDate();
return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
}
return compareMonthResult;
}
export function getDayByOffset(date, offset) {
date = new Date(date);
date.setDate(date.getDate() + offset);
return date;
}
export function getPrevDay(date) {
return getDayByOffset(date, -1);
}
export function getNextDay(date) {
return getDayByOffset(date, 1);
}
export function calcDateNum(date) {
const day1 = new Date(date[0]).getTime();
const day2 = new Date(date[1]).getTime();
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
}
export function copyDates(dates) {
if (Array.isArray(dates)) {
return dates.map((date) => {
if (date === null) {
return date;
}
return new Date(date);
});
}
return new Date(dates);
}
export function getMonthEndDay(year, month) {
return 32 - new Date(year, month - 1, 32).getDate();
}
export function getMonths(minDate, maxDate) {
const months = [];
const cursor = new Date(minDate);
cursor.setDate(1);
do {
months.push(cursor.getTime());
cursor.setMonth(cursor.getMonth() + 1);
} while (compareMonth(cursor, maxDate) !== 1);
return months;
}

View File

@ -0,0 +1,25 @@
/* eslint-disable */
function getMonthEndDay(year, month) {
return 32 - getDate(year, month - 1, 32).getDate();
}
function compareMonth(date1, date2) {
date1 = getDate(date1);
date2 = getDate(date2);
var year1 = date1.getFullYear();
var year2 = date2.getFullYear();
var month1 = date1.getMonth();
var month2 = date2.getMonth();
if (year1 === year2) {
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
}
return year1 > year2 ? 1 : -1;
}
module.exports = {
getMonthEndDay: getMonthEndDay,
compareMonth: compareMonth
};

1
mini-app/src/vant/card/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,49 @@
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class',
],
mixins: [link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: {
type: String,
observer: 'updatePrice',
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit',
},
currency: {
type: String,
value: '¥',
},
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : '',
});
},
onClickThumb() {
this.jumpLink('thumbLink');
},
},
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}

View File

@ -0,0 +1,56 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class van-card">
<view class="{{ utils.bem('card__header', { center: centered }) }}">
<view class="van-card__thumb" bind:tap="onClickThumb">
<image
wx:if="{{ thumb }}"
src="{{ thumb }}"
mode="{{ thumbMode }}"
lazy-load="{{ lazyLoad }}"
class="van-card__img thumb-class"
/>
<slot wx:else name="thumb" />
<van-tag
wx:if="{{ tag }}"
mark
type="danger"
custom-class="van-card__tag"
>
{{ tag }}
</van-tag>
<slot wx:else name="tag" />
</view>
<view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
<view>
<view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
<slot wx:else name="title" />
<view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
<slot wx:else name="desc" />
<slot name="tags" />
</view>
<view class="van-card__bottom">
<slot name="price-top" />
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">
<text>{{ currency }}</text>
<text class="van-card__price-integer">{{ integerStr }}</text>
<text class="van-card__price-decimal">{{ decimalStr }}</text>
</view>
<slot wx:else name="price" />
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<slot wx:else name="origin-price" />
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot wx:else name="num" />
<slot name="bottom" />
</view>
</view>
</view>
<view class="van-card__footer">
<slot name="footer" />
</view>
</view>

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-card{position:relative;box-sizing:border-box;padding:8px 16px;padding:var(--card-padding,8px 16px);font-size:12px;font-size:var(--card-font-size,12px);color:#323233;color:var(--card-text-color,#323233);background-color:#fafafa;background-color:var(--card-background-color,#fafafa)}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;-webkit-flex:none;flex:none;width:88px;width:var(--card-thumb-size,88px);height:88px;height:var(--card-thumb-size,88px);margin-right:8px;margin-right:var(--padding-xs,8px)}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%;border-radius:8px;border-radius:var(--border-radius-lg,8px)}.van-card__content{position:relative;display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:space-between;justify-content:space-between;min-width:0;min-height:88px;min-height:var(--card-thumb-size,88px)}.van-card__content--center{-webkit-justify-content:center;justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:16px;line-height:var(--card-title-line-height,16px)}.van-card__desc{line-height:20px;line-height:var(--card-desc-line-height,20px);color:#646566;color:var(--card-desc-color,#646566)}.van-card__bottom{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#ee0a24;color:var(--card-price-color,#ee0a24);font-size:12px;font-size:var(--card-price-font-size,12px)}.van-card__price-integer{font-size:16px;font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{display:inline-block;margin-left:5px;text-decoration:line-through;font-size:10px;font-size:var(--card-origin-price-font-size,10px);color:#646566;color:var(--card-origin-price-color,#646566)}.van-card__num{float:right}.van-card__tag{position:absolute!important;top:2px;left:0}.van-card__footer{-webkit-flex:none;flex:none;width:100%;text-align:right}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,10 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
},
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1,9 @@
<view
wx:if="{{ title }}"
class="van-cell-group__title"
>
{{ title }}
</view>
<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}

1
mini-app/src/vant/cell/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,38 @@
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class',
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}

View File

@ -0,0 +1,45 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
hover-class="van-cell--hover hover-class"
hover-stay-time="70"
style="{{ customStyle }}"
bind:tap="onClick"
>
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
class="van-cell__left-icon-wrap"
custom-class="van-cell__left-icon"
/>
<slot wx:else name="icon" />
<view
style="{{ (titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth + ';' : '') + titleStyle }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
<view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
<slot wx:if="{{ useLabelSlot }}" name="label" />
<block wx:elif="{{ label }}">{{ label }}</block>
</view>
</view>
<view class="van-cell__value value-class">
<block wx:if="{{ value || value === 0 }}">{{ value }}</block>
<slot wx:else />
</view>
<van-icon
wx:if="{{ isLink }}"
name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
class="van-cell__right-icon-wrap right-icon-class"
custom-class="van-cell__right-icon"
/>
<slot wx:else name="right-icon" />
<slot name="extra" />
</view>

View File

@ -0,0 +1 @@
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;right:16px;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:4px;margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{margin-left:4px;margin-left:var(--padding-base,4px);color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:16px;font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,35 @@
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'checkbox',
type: 'descendant',
current: 'checkbox-group',
linked(target) {
this.updateChild(target);
},
},
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren',
},
disabled: {
type: Boolean,
observer: 'updateChildren',
},
},
methods: {
updateChildren() {
(this.children || []).forEach((child) => this.updateChild(child));
},
updateChild(child) {
const { value, disabled } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled,
});
},
},
});

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1 @@
<slot />

View File

@ -0,0 +1 @@
@import '../common/index.wxss';

Some files were not shown because too many files have changed in this diff Show More