提交 9c9abdfc 作者: ZhangLingKun

功能:项目重构

上级 f5293a92
index.html
*.d.ts
\ No newline at end of file
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
'vue/setup-compiler-macros': true
},
extends: [
'plugin:vue/vue3-recommended',
'airbnb-base',
// 一定要放在最后一项
'plugin:prettier/recommended'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
settings: {
'import/resolver': {
alias: {
map: [['@', './src']],
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
}
},
globals: {
/** 避免uni报错 */
wx: true,
getApp: true,
uni: true,
UniApp: true
},
rules: {
'no-console': 'off',
'prettier/prettier': [
'error',
{
trailingComma: 'none',
printWidth: 100,
tabWidth: 2,
semi: false,
singleQuote: true,
endOfLine: 'auto'
}
],
// 解决vite+airbnb导致eslint报错import/extensions
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never'
}
],
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
'vue/multi-word-component-names': 'off',
'no-use-before-define': 'off',
'no-restricted-syntax': 0
}
}
.DS_Store
node_modules
/dist
/node_modules
#unpackage/
node_modules/
.idea/
unpackage/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Lock files
package-lock.json
yarn.lock
pnpm-lock.yaml*
yarn-lock.yaml*
package-lock.yaml*
# Editor directories and files
.idea
.vscode
.hbuilderx
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}
{
"trailingComma": "none",
"printWidth": 100,
"tabWidth": 4,
"semi": false,
"singleQuote": true,
"endOfLine": "auto"
}
**/*.js
**/*.ts
dist
node_modules
index.html
*.md
\ No newline at end of file
<script>
export default {
onLaunch: function(option) {
// console.log('option--->',option)
// uni.showToast({
// title:window.location.search,
// icon:'none'
// })
},
onShow: function() {
},
onHide: function() {
}
}
</script>
<style>
/*每个页面公共css */
@import "static/utils/css/animate.min.css";
</style>
MIT License
Copyright (c) 2020 www.uviewui.com
Copyright (c) 2022 betty.gao66
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
SOFTWARE.
// 测试服务器
// const baseURL = 'https://testapi.sharefly.mmcuav.cn/'
// const baseURL = 'https://jytestapi.sharefly.mmcuav.cn/'
// const baseURL = 'https://uav.hnjcloud.cn/jyapi/'
// const baseURL = 'https://test.iuav.shop'
// 正式服 123
// const baseURL = "https://www.iuav.shop"
const baseURL=''
const api = {
getWebSitList:'/release/website/getWebsiteList',
flyerDotList:'/release/website/flyer/bitmap' ,
deviceDotList:'/release/website/uav/bitmap'
}
export {
api,
baseURL,
}
import { baseURL, api } from './index.js'
export const httpRequest = (params) => {
return new Promise(async (resolve, reject) => {
await getNetWork()
let { url, method, data } = params
// uni.showLoading({
// title: '加载中'
// });
uni.request({
url: baseURL + url,
method: method || 'GET',
data: data || {},
header: {
'token': uni.getStorageSync('token')
},
success(res) {
if(res.statusCode === 200){
if(res.data.code == "200"){
resolve(res.data)
}else{
if(res.data.code == 602 || res.data.code == 603|| res.data.code == 605 || res.data.code == 6004){
resetLogin()
}else{
const urls = [api.listEntLicense]
if(!urls.includes(url)){
setTimeout(()=>{
console.log('报错提示 -->',url,res)
uni.showToast({
title: res.data.message,
icon: 'none'
})
},500)
}
}
resolve(res.data)
}
}else{
resolve({})
}
},
complete(err) {
// console.log('err--->', err)
if(err.statusCode === 500 || err.statusCode === 502){
uni.showToast({
title: '服务器异常!',
icon: 'none'
})
}else{
// uni.hideLoading()
}
}
})
})
}
const getNetWork = () => {
return new Promise((resolve, reject) => {
uni.getNetworkType({
success(res) {
if(res.networkType != 'none'){
resolve()
}else{
uni.showToast({
title: '网络异常',
icon: 'none'
})
}
}
})
})
}
const resetLogin = () => {
uni.login({
success: async ({ code }) => {
console.log('小程序登录过期,自动重新登录---->', code)
uni.request({
url:baseURL + api.appletAuth,
method: 'POST',
data: {
code,
portType:0
},
success(res) {
if (res.code == 200) {
console.log('登录成功')
uni.setStorageSync('checked', res?.result.phoneNum?true:false);
uni.setStorageSync('token', res?.result.token);
uni.setStorageSync('phoneNum', res?.result.phoneNum);
uni.setStorageSync('repoAccountId',res?.result.repoAccountId)
uni.setStorageSync('accountType',res?.result.accountType)
uni.setStorageSync('sessionKey',res?.result.sessionKey)
uni.setStorageSync('unionId',res?.result.unionId)
uni.showToast({
title: '登录过期,已自动为您重新登录',
icon:'none'
})
}
},
complete: c => {
console.log('c----->', c)
}
})
}
})
}
export const uploadFile = (url, file) => {
return new Promise((resolve, reject) => {
uni.showLoading({
title: '上传中'
});
uni.uploadFile({
url: baseURL + url,
filePath: file,
name: 'uploadFile',
header: {
'token': uni.getStorageSync('token')
},
success: (res) => {
let data = JSON.parse(res.data)
resolve(data)
},
fail() {
uni.showToast({
title:'上传失败',
icon:'none'
})
},
complete() {
uni.hideLoading()
}
})
})
}
\ No newline at end of file
<template>
<picker
mode="multiSelector"
:value="multiIndex"
:range="multiArray"
@change="handleValueChange"
@columnchange="handleColumnChange"
>
<slot></slot>
</picker>
</template>
<script>
import CHINA_REGIONS from './regions.json'
export default {
props: {
defaultRegions: {
type: Array,
default() {
return []
}
},
defaultRegionCode: {
type: String
},
defaultRegion: [String, Array]
},
data() {
return {
cityArr: CHINA_REGIONS[0].childs,
districtArr: CHINA_REGIONS[0].childs[0].childs,
multiIndex: [0, 0, 0],
isInitMultiArray: true
}
},
computed: {
multiArray() {
return this.pickedArr.map((arr) => arr.map((item) => item.name))
},
pickedArr() {
// 进行初始化
if (this.isInitMultiArray) {
return [CHINA_REGIONS, CHINA_REGIONS[0].childs, CHINA_REGIONS[0].childs[0].childs]
}
return [CHINA_REGIONS, this.cityArr, this.districtArr]
}
},
watch: {
defaultRegion: {
handler(region, oldRegion) {
if (Array.isArray(region)) {
// 避免传的是字面量的时候重复触发
oldRegion = oldRegion || []
if (region.join('') !== oldRegion.join('')) {
this.handleDefaultRegion(region)
}
} else if (region && region.length == 6) {
this.handleDefaultRegion(region)
} else {
console.warn('defaultRegion非有效格式')
}
},
immediate: true
}
},
methods: {
handleColumnChange(e) {
// console.log(e);
this.isInitMultiArray = false
const that = this
const col = e.detail.column
const row = e.detail.value
that.multiIndex[col] = row
try {
switch (col) {
case 0:
if (CHINA_REGIONS[that.multiIndex[0]].childs.length == 0) {
that.cityArr = that.districtArr = [CHINA_REGIONS[that.multiIndex[0]]]
break
}
that.cityArr = CHINA_REGIONS[that.multiIndex[0]].childs
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[that.multiIndex[1]].childs
break
case 1:
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[that.multiIndex[1]].childs
break
case 2:
break
}
} catch (e) {
// console.log(e);
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[0].childs
}
},
handleValueChange(e) {
// 结构赋值
const [index0, index1, index2] = e.detail.value
const [arr0, arr1, arr2] = this.pickedArr
const address = [arr0[index0], arr1[index1], arr2[index2]]
// console.log(address);
this.$emit('getRegion', address)
},
handleDefaultRegion(region) {
const isCode = !Array.isArray(region)
this.isInitMultiArray = false
let children = CHINA_REGIONS
for (let i = 0; i < 3; i++) {
for (let j = 0; j < children.length; j++) {
const condition = isCode
? children[j].code == region.slice(0, (i + 1) * 2)
: children[j].name.includes(region[i])
if (condition) {
// 匹配成功进行赋值
// console.log(i,j,children.length-1);
children = children[j].childs
if (i == 0) {
this.cityArr = children
} else if (i == 1) {
this.districtArr = children
}
this.$set(this.multiIndex, i, j)
// console.log(this.multiIndex);
break
} else {
// 首次匹配失败就用默认的初始化
// console.log(i,j,children.length-1);
if (i == 0 && j == children.length - 1) {
this.isInitMultiArray = true
}
}
}
}
}
}
}
</script>
This source diff could not be displayed because it is too large. You can view the blob instead.
# 请求接口地址
#VITE_REQUEST_BASE_URL='https://www.iuav.shop'
VITE_REQUEST_BASE_URL='https://test.iuav.shop'
# 请求接口地址
#VITE_REQUEST_BASE_URL='https://www.iuav.shop'
VITE_REQUEST_BASE_URL='https://test.iuav.shop'
/** 扩展环境变量import.meta.env */
interface ImportMetaEnv {
VITE_REQUEST_BASE_URL: string
}
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>MMC-云享飞</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/network/static/index.63b34199.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/network/static/js/chunk-vendors.7c0b3116.js></script><script src=/network/static/js/index.53945dd9.js></script></body></html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<title></title>
<!--preload-links-->
<!--app-context-->
<!-- 配置H5的 web图标static/logo.png -->
<link rel="icon" href="./static/logo.png" />
</head>
<body>
<div id="app">
<!--app-html-->
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
\ No newline at end of file
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import { api } from 'api/index.js'
import { httpRequest} from 'api/request.js'
import uView from '@/uni_modules/uview-ui'
Vue.config.productionTip = false
App.mpType = 'app'
Vue.use(uView)
Vue.prototype.$api = api;
Vue.prototype.$httpRequest = httpRequest;
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
\ No newline at end of file
{
"name" : "map-h5",
"appid" : "__UNI__E0F71DB",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {},
/* SDK配置 */
"sdkConfigs" : {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2",
"h5" : {
"template" : "",
"router" : {
"base" : "/network/",
"mode" : "hash"
},
"title" : "MMC-云享飞",
"devServer" : {
"https" : true
},
"sdkConfigs" : {
"maps" : {}
}
}
}
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
client_max_body_size 100M;
server {
listen 80;
server_name _;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' '*';
add_header 'Access-Control-Allow-Headers' '*';
location /network {
alias /var/www/html/h5;
index index.html;
try_files $uri $uri/ /index.html;
}
location = /ItnIxOQr0x.txt {
root /var/www/html/wechat;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
\ No newline at end of file
{
"name": "uni-preset-vue",
"version": "0.0.0",
"scripts": {
"dev:app": "uni -p app",
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-weixin": "uni build -p mp-weixin",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
"lint:js": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src",
"lint:css": "stylelint src/**/*.{html,vue,css,scss}",
"lint": "prettier --write src/**/*.{vue,css,scss,json,js,ts,jsx,tsx} && npm run lint:js && npm run lint:css"
},
"dependencies": {
"weixin-js-sdk": "^1.6.0"
"@dcloudio/uni-app": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-app-plus": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-components": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-h5": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-alipay": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-baidu": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-kuaishou": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-lark": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-qq": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-toutiao": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-mp-weixin": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-quickapp-webview": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-ui": "^1.4.12",
"@ttou/uview-typings": "^2.0.4",
"@vue/reactivity": "^3.3.4",
"clipboard": "^2.0.11",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.7",
"image-tools": "^1.4.0",
"js-base64": "^3.7.5",
"js-md5": "^0.7.3",
"miniprogram-api-typings": "^3.5.0",
"pinia": "^2.0.17",
"querystringify": "^2.2.0",
"uview-plus": "^3.1.30",
"vue": "^3.2.26",
"vue-i18n": "^9.1.9",
"vuex": "^4.0.2",
"z-weixin-ts": "^1.2.0",
"@amap/amap-jsapi-loader": "^1.0.1"
},
"devDependencies": {
"@dcloudio/types": "^2.5.15",
"@dcloudio/uni-automator": "^3.0.0-alpha-3080120230428001",
"@dcloudio/uni-cli-shared": "^3.0.0-alpha-3080120230428001",
"@dcloudio/vite-plugin-uni": "^3.0.0-alpha-3080120230428001",
"@types/js-cookie": "^3.0.3",
"@types/node": "^18.6.2",
"@types/querystringify": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^5.12.1",
"@typescript-eslint/parser": "^5.12.1",
"autoprefixer": "^10.4.0",
"eslint": "^8.2.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.4.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.5.0",
"prettier": "^2.5.1",
"sass": "^1.49.9",
"sass-loader": "^10.3.1",
"stylelint": "^14.5.3",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-recommended-scss": "^5.0.2",
"stylelint-config-recommended-vue": "^1.3.0",
"stylelint-config-standard-scss": "^3.0.0",
"stylelint-order": "^5.0.0",
"typescript": "^4.5.2",
"vite": "^4.3.9"
}
}
<template>
<view class="marketing-wrap">
<template v-for="(i,j) in list">
<image class="marketing-image" :src="`${image}${j+1}@2x.png`" :key="j" mode="widthFix"></image>
</template>
<view class="marketing-view" :style="{'height':`${height}px`}">
<image class="marketing-image-form" :src="`${image}5@2x.png`" mode="widthFix"></image>
<view class="marketing-form">
<u-form :model="formData" :rules="rules" ref="uForm" labelPosition="top" labelWidth="300">
<u-form-item label="Your name" prop="name" required>
<u-input v-model="formData.name" type="text" maxlength="50"></u-input>
</u-form-item>
<u-form-item label="Your email" prop="email" required>
<u-input v-model="formData.email" type="email" maxlength="50"></u-input>
</u-form-item>
<u-form-item label="WhatsApp" prop="whatsApp">
<u-input v-model="formData.whatsApp" type="text" maxlength="50"></u-input>
</u-form-item>
<u-form-item label="The products you need" prop="productNeed" class="product">
<u-textarea v-model="formData.productNeed" type="text" maxlength="70" count></u-textarea>
</u-form-item>
</u-form>
<view class="marketing-action" @click="handleSubmit()">Submit</view>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
image: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/sharefly-marketing-0',
list:[],
height: 0,
disabled:false,
tips:'获取验证码',
formData:{
name:''
},
rules: {
name: [{
type: 'string',
required: true,
message: 'Please enter your name',
trigger: ['change', 'blur']
}],
email: [{
type: 'email',
required: true,
len: 50,
message: 'Please enter your email',
trigger: ['change', 'blur']
},{
validator: (rule, value, callback) => {
return uni.$u.test.email(value);
},
message: "Please enter a valid email",
trigger: ["change", "blur"],
}],
// whatsApp: [{
// type: 'string',
// required: true,
// message: 'Please enter your whatsapp id',
// trigger: ['change', 'blur']
// }],
// productNeed: [{
// type: 'string',
// required: true,
// message: 'Please enter the product you need',
// trigger: ['change', 'blur']
// }],
}
}
},
mounted(){
this.list = new Array(4)
if(uni.getSystemInfoSync().screenWidth > 768){
this.height = 672
}else{
this.height = Math.floor(uni.getSystemInfoSync().screenWidth / 375 * 672)
}
},
methods:{
//提交数据
handleSubmit(){
// 如果有错误,会在catch中返回报错信息数组,校验通过则在then中返回true
this.$refs.uForm.validate().then(async val => {
// if(!uni.getStorageSync('clientInfo')){
let res = await this.$httpRequest({
url: this.$api.insertClientInfo,
method: 'POST',
data: this.formData
})
if(res && res.code == '200'){
// uni.setStorageSync('clientInfo',true)
this.$refs.uForm.resetFields()
this.formData = {
name:'',
email:'',
whatsApp:'',
productNeed:''
}
uni.pageScrollTo({
scrollTop: 0,
duration: 300
});
uni.showToast({
title: 'Thank you for your participation!',
icon: 'none'
})
}else{
uni.showToast({
title: 'Data submission failed',
icon: 'none'
})
}
// }else{
// uni.showToast({
// title: 'Do not submit multiple times!',
// icon: 'none'
// })
// }
}).catch(err => {
return
})
},
}
}
</script>
<style lang="scss" scoped>
page{
background-color: #041D5A;
}
@media screen and (min-width:768px) {
.marketing-wrap{
width: 375px !important;
}
}
.marketing-wrap{
position: relative;
min-height: 100vh;
height: auto;
width: 100%;
margin: 0 auto;
background-color: #fff;
.marketing-image{
width:100%;
margin-top: -8px;
}
.marketing-view{
position: relative;
width:100%;
margin-top: -8px;
padding-top: 258rpx;
box-sizing: border-box;
background: #3366FF;
.marketing-image-form{
position: absolute;
top: 0;
left: 0;
width:100%;
}
.marketing-form{
width:calc(100% - 200rpx);
height: auto;
margin: 0 auto;
}
.marketing-action{
position: relative;
width: 552rpx;
height: 86rpx;
margin: 0 auto;
background: #3366FF;
border-radius: 10rpx;
text-align: center;
line-height: 86rpx;
font-size: 30rpx;
font-weight: 500;
color: #FFFFFF;
margin-top: 12rpx;
}
.marketing-action:active{
transform: scale(0.96);
filter: brightness(0.96);
transition-duration: 168ms;
transition-timing-function: ease-in-out;
}
}
}
::v-deep{
.u-form-item__body__left__content__label{
font-size: 32rpx;
font-weight: 500;
color: #622C05;
line-height: 44rpx;
}
.u-form-item__body__left__content__required{
// right: 0;
}
.u-input__content__field-wrapper__field{
height: 60rpx;
border-radius: 10rpx;
border: 2rpx solid #622C05;
padding: 0 8rpx;
}
.u-textarea{
border: 2rpx solid #622C05;
padding: 4rpx 10rpx;
.u-textarea__field{
height: 92rpx !important;
}
}
.product{
.u-input__content__field-wrapper__field{
height: 92rpx;
}
}
.u-form-item__body__left__content__label{
margin-left:20rpx;
}
.u-form-item__body__left__content__required{
left: 0;
}
.u-input{
padding: 0 !important;
}
.u-form-item__body{
padding:10rpx 0 10rpx 0;
}
.u-form-item__body__right__message{
z-index: 1;
}
}
</style>
\ No newline at end of file
<template>
<view class="network-item-wrap">
<view class="network-item">
<view class="network-item-img">
<image
:src="networkItem.addressDescImg"
/>
</view>
<view class="network-item-content">
<view class="network-info-wrap">
<view class="network-info">
<view class="info-title">{{networkItem.address}}</view>
<view class="info-meta">{{networkItem.distance.toFixed(2)}}KM</view>
</view>
<!-- <view class="select-icon"> <image src="/page-home/static/image/select-icon.png" /> </view> -->
</view>
</view>
</view>
</view>
</template>
<script >
export default{
props:['networkItem']
}
</script>
<style lang="scss" scoped>
.network-item-wrap {
background-color: #fff;
height: 168rpx;
padding: 8rpx 16rpx;
.network-item {
display: flex;
border-bottom: 1rpx solid #e8e8e8;
&-img {
margin-right: 16rpx;
image {
width: 156rpx;
height: 156rpx;
}
}
&-content {
flex: 1;
.network-info-wrap {
display: flex;
align-items: center;
.network-info {
flex: 1;
.info-title {
font-size: 28rpx;
color: #1a1a1a;
line-height: 40rpx;
margin-bottom: 12rpx;
word-break: break-all;
}
.info-meta {
font-size: 24rpx;
color: #b3b3b3;
line-height: 34rpx;
word-break: break-all;
}
}
.select-icon {
margin: 0 54rpx 0 24rpx;
image {
width: 28rpx;
height: 24rpx;
vertical-align: bottom;
}
}
}
}
}
}
</style>
This source diff could not be displayed because it is too large. You can view the blob instead.
const { uniPostcssPlugin } = require('@dcloudio/uni-cli-shared')
module.exports = {
plugins: [uniPostcssPlugin(), require('autoprefixer')()]
}
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
onLaunch(() => {
// const res = await CommonAPI.BackEndLogin({
// accountNo: 'admin',
// passWord: 'mmc123456'
// })
// if (res && res.code === '200') {
// uni.setStorageSync('token', res.result.token)
// }
})
onShow(() => {
console.log('App Show')
})
onHide(() => {
console.log('App Hide')
})
</script>
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import 'uview-plus/theme.scss';
</style>
import CommonAPI from '@/api/modules/common'
const useApi = { CommonAPI }
export { CommonAPI }
export default useApi
// 分页通用接口
export interface PaginationProps {
pageSize: number
pageNo: number
}
// 通用返回接口(分页)
export interface ResponseListType<D> {
code: string
message: string
result: {
pageNo: number
pageSize: number
totalCount: number
totalPage: number
list: Array<D>
}
}
// 通用返回接口(分页了,但又没有分页)
export interface ResponseItemType<D> {
code: string
message: string
result: {
pageNo: number
pageSize: number
totalCount: number
totalPage: number
list: D
}
}
// 通用返回接口
export interface ResponseType<D> {
code: string
message: string
result: D
}
// 通用接口封装函数(分页) 建议用这个
export interface InterListFunction<D extends object, T> {
// eslint-disable-next-line no-unused-vars
(req: D & Partial<PaginationProps>): Promise<ResponseListType<T>>
}
// 通用接口封装函数(不分页) 建议用这个
export interface InterFunction<D extends object, T> {
// eslint-disable-next-line no-unused-vars
(req?: D): Promise<ResponseType<T>>
}
// 通用接口封装函数(分页了,但又没有分页) 建议用这个
export interface InterItemFunction<D extends object, T> {
// eslint-disable-next-line no-unused-vars
(req: D & Partial<PaginationProps>): Promise<ResponseItemType<T>>
}
// 返回类型封装
// eslint-disable-next-line no-unused-vars
export type InterDataType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: infer V }
? V
: never
// 返回列表类型封装
// eslint-disable-next-line no-unused-vars
export type InterListType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: { list: infer V } }
? V
: never
// 返回类型封装(分页了,但又没有分页)
// eslint-disable-next-line no-unused-vars
export type InterItemType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: infer V }
? V
: never
// 获取参数类型封装
// eslint-disable-next-line no-unused-vars
export type InterReqType<T extends (...args: any) => any> = Parameters<T>[0]
// 获取参数类型封装(分页)
// eslint-disable-next-line no-unused-vars
export type InterReqListType<T extends (...args: any) => any> = Omit<
Parameters<T>[0],
'pageSize' | 'pageNo'
>
import { InterFunction, InterListFunction } from '../interface'
// 用户登录
export type BackEndLoginType = InterFunction<
{ accountNo?: string; passWord?: string },
{
token: string
userAccountId: number
accountNo: string
portType: number
uid: string
phoneNum: string
userName: string
nickName: string
companyInfoVO: {
id: number
companyType: number
companyName: string
fullName: string
province: string
city: string
district: string
address: string
companyUserName: string
phoneNum: string
remark: string
}
roleInfo: {
id: number
roleName: string
roleNo: string
}
}
>
// 演示规范
export type getSecondDistrictInfo = InterFunction<
// 入参
{},
// 出参
{
id: number
name: string
level: number
pid: number
childInfo: Array<{
id: number
name: string
level: number
pid: number
childInfo: null
}>
}[]
>
// 服务商网点数据
export type cooperationServiceBitmap = InterListFunction<
{
lat: number
lon: number
pageNo: number
pageSize: number
type: number
},
{
address: string
name: string
lon: number
lat: number
distance: number
content: string
cooperationTagId: number
id: number
score: number
}
>
import {
BackEndLoginType,
cooperationServiceBitmap,
getSecondDistrictInfo
} from '@/api/interface/common'
import request from '../request'
export default class CommonAPI {
// 用户登录
static BackEndLogin: BackEndLoginType = (params) =>
request.post('/userapp/auth/backEndLogin', params)
// 地域
static getSecondDistrictInfo: getSecondDistrictInfo = (params) =>
request.get('/pms/webDevice/getSecondDistrictInfo', params)
// 服务商网点数据
static cooperationServiceBitmap: cooperationServiceBitmap = (params) =>
request.get('/userapp/cooperation/service/bitmap', params)
}
// /**
// * uni-request请求封装
// * 1. 统一配置接口地址
// * 2. 统一设置超时时间/报文格式/报文加密
// * 3. 统一身份认证
// * 4. 统一处理登录超时/接口异常提示
// * 5. 统一返回接口格式
// */
// import { Base64 } from 'js-base64'
import { Base64 } from 'js-base64'
export const baseURL = import.meta.env.VITE_REQUEST_BASE_URL // 测试接口
// 接口类型
interface responseType {
code: string
success: boolean
message: string
result: any
}
const request = (config: UniApp.RequestOptions) => {
return new Promise<responseType>((resolve, reject) => {
uni.request({
...config,
url: baseURL + config.url,
/** 统一设置超时时间 */
timeout: config.timeout || 60000,
header: {
...config.header,
/** 统一报文格式 */
'Content-Type': 'application/json;charset=UTF-8',
/** 统一身份认证 */
// Authorization: Token
token: uni.getStorageSync('token')
},
success(res) {
// 200状态码表示成功(系统状态)
if (res.statusCode === 200) {
const { data } = res as unknown as {
data: { code: string; message: string; result: any }
} & UniApp.RequestSuccessCallbackResult
// 如果不报错就直接返回数据(后台状态码)
if (data.code === '200') {
resolve(data as any)
return
}
// 重新登录?
if (['605', '603', '602', '4004', '607', '5098'].includes(data.code)) {
uni.showToast({ title: data.message, icon: 'none' })
uni.removeStorageSync('token')
setTimeout(() => {
// 重新加载小程序
uni.reLaunch({ url: '/pages/welcome/index' })
}, 1000)
// 阻止后续代码执行
reject(data)
return
}
// 文件/base64导出判断 || Base64.isValid(data)
if (Base64.isValid(data)) {
resolve(data as any)
return
}
// 如果还有其他报错那么就弹出报错信息(不需要对每个接口的报错做单独判断)
uni.showToast({ title: data.message || '啊呀,出错了', icon: 'none' })
reject(data)
return
}
if (res.statusCode === 500 || res.statusCode === 502) {
uni.showToast({
title: '服务器异常',
icon: 'none'
})
}
/**
* 这里可以做一些登录超时/接口异常提示等处理
*/
reject(res.data)
},
fail(result) {
reject(result)
}
})
})
}
export default {
/**
* get请求
* @param url 请求地址
* @param data 请求的参数
* @param options 其他请求配置
*/
get: (url: string, data?: UniApp.RequestOptions['data'], options?: UniApp.RequestOptions) => {
return request({
...options,
url,
data,
method: 'GET'
})
},
/**
* post请求
* @param url 请求地址
* @param data 请求的参数
* @param options 其他请求配置
*/
post: (url: string, data?: UniApp.RequestOptions['data'], options?: UniApp.RequestOptions) => {
return request({
...options,
url,
data,
method: 'POST'
})
}
}
<template>
<uni-rate :size="18" :value="5" />
<view>hello-world</view>
<u-button type="primary">主要按钮</u-button>
<u-button type="success">成功按钮</u-button>
<u-button type="info">信息按钮</u-button>
<u-button type="warning">警告按钮</u-button>
<!-- <u-button type="error" @click="goLogin">危险按钮</u-button>-->
<uni-popup ref="popup" type="bottom" background-color="#fff">
<image class="logo" src="@/static/logo.png" />
</uni-popup>
</template>
<script lang="ts">
import { defineComponent, reactive, ref } from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
name: 'HelloWorld',
setup() {
const store = useStore()
const city = ref('')
const laglnt = reactive({
lat: '',
lng: ''
})
const popup = ref()
console.log('useStore访问store', store.state.system.title)
return { city, laglnt, popup }
}
// mounted() {
// console.log('this访问store', this.$store.state.system.title)
// }
})
</script>
<!--function resolve(res: UniApp.LoginRes) { throw new Error('Function not implemented.') } function-->
<!--reject(err: any) { throw new Error('Function not implemented.') } function resolve(res:-->
<!--UniApp.LoginRes) { throw new Error('Function not implemented.') }-->
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
import { createSSRApp } from 'vue'
// @ts-ignore
import uView from 'uview-plus'
import App from './App.vue'
import store from './store'
// eslint-disable-next-line import/prefer-default-export
export function createApp() {
const app = createSSRApp(App).use(store)
// 使用 uView UI
app.use(uView)
return {
app
}
}
{
"name": "hello",
"appid": "__UNI__4DCD124",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
/* 5+App特有相关 */
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* 模块配置 */
"modules": {},
/* 应用发布信息 */
"distribute": {
/* android打包配置 */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios": {},
/* SDK配置 */
"sdkConfigs": {}
}
},
/* 快应用特有相关 */
"quickapp": {},
/* 小程序特有相关 */
"mp-weixin": {
"appid": "wx435a39e391de2067",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "3"
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path" : "pages/network/index",
"style" :
{
"navigationBarTitleText": "全国网点",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "全国网点"
// "enablePullDownRefresh": true
}
},
{
"path": "pages/marketing/index",
"style": {
"navigationBarTitleText": "20% Off at MMCUAV Store"
// "enablePullDownRefresh": true
}
}
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "全国网点"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom"
}
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "云享飞",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom"
},
"easycom": {
"autoscan": true,
"custom": {
"^u-(.*)": "uview-plus/components/u-$1/u-$1.vue"
}
}
}
<template>
<view class="network-footer">
<view class="footer-action" @click="toCooperation()">加入我们,成为云享飞服务商</view>
</view>
</template>
<script setup lang="ts">
import weChatSDK from 'z-weixin-ts'
const toCooperation = () => {
weChatSDK.miniProgram.navigateTo({
url: '/page-identity/identity-list/index'
})
}
</script>
<style scoped lang="scss">
.network-footer {
position: fixed;
height: 156rpx;
width: 100%;
bottom: 0;
left: 0;
background: #fff;
box-sizing: border-box;
padding: 32rpx 0;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
.footer-action {
width: 672rpx;
height: 84rpx;
line-height: 84rpx;
text-align: center;
background: linear-gradient(270deg, #ff2100 0%, #fe9d45 100%);
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
border-radius: 16rpx;
}
.footer-action:active {
filter: brightness(0.86);
}
}
</style>
<template>
<view class="network-list">
<scroll-view class="list-view" scroll-y>
<view v-for="(i, j) in list" :key="j" class="list-item" @click="handleSelect(j)">
<image class="item-image" :src="getNetworkLevel(0)"></image>
<view class="item-content">
<view class="content-title">{{ i.name }}</view>
<view class="content-price">
<u-icon
size="16"
name="https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/popup-network-price.png"
></u-icon>
<view class="text">已交保证金<span class="num">10000元</span></view>
</view>
</view>
<view class="item-action" @click="toCooperation">联系客服派单</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { onMounted, PropType } from 'vue'
import weChatSDK from 'z-weixin-ts'
import { InterListType } from '@/api/interface'
import { cooperationServiceBitmap } from '@/api/interface/common'
type ListType = InterListType<cooperationServiceBitmap>
// 传参
const props = defineProps({
list: {
type: Array as unknown as PropType<ListType>,
default: () => []
}
})
// 事件
const emits = defineEmits(['onSelect'])
// 网点等级
const networkLevelList = [
{
value: 0,
label: '金牌网点',
icon: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/%E9%87%91%E7%89%8C@2x.png'
},
{
value: 1,
label: '银牌网点',
icon: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/%E9%93%B6%E7%89%8C@2x.png'
},
{
value: 2,
label: '铜牌网点',
icon: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/%E9%93%9C%E7%89%8C@2x.png'
}
]
// 获取当前网点的等级
const getNetworkLevel = (level: number) => {
return networkLevelList.find((i) => i.value === level)?.icon || ''
}
// 网点点击事件
const handleSelect = (j: number) => {
emits('onSelect', props.list[j])
// console.log(props.list[j])
}
const toCooperation = () => {
weChatSDK.miniProgram.navigateTo({
url: '/page-mine/help-center/index'
})
}
// 组件挂载
onMounted(() => {
console.log(props.list)
})
</script>
<style scoped lang="scss">
.network-list {
.list-view {
position: relative;
width: 100%;
//height: calc(100vh - 156rpx - 110rpx - (100vh - 504rpx));
height: calc(100vh - 156rpx - 110rpx - (100vh - 704rpx));
// 屏幕高度 - 搜索 - 底部 - 地图
//background-color: lightpink;
background-color: #fff;
.list-item {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
height: 160rpx;
background: #ffffff;
.item-image {
width: 100rpx;
height: 100rpx;
transform: translateY(10rpx);
}
.item-content {
position: relative;
.content-title {
width: 498rpx;
height: 40rpx;
font-size: 28rpx;
font-weight: 600;
color: #000000;
line-height: 40rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 10rpx;
}
.content-price {
display: flex;
justify-content: flex-start;
align-items: center;
.text {
width: 300rpx;
font-size: 26rpx;
font-weight: 500;
color: #828282;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 10rpx;
.num {
color: #ff4900;
}
}
}
}
.item-action {
position: absolute;
bottom: 32rpx;
right: 30rpx;
width: 240rpx;
height: 56rpx;
background: #ffece7;
border-radius: 28rpx;
border: 1rpx solid #ffbaa7;
text-align: center;
line-height: 56rpx;
font-size: 26rpx;
font-weight: 400;
color: #ff5b2d;
}
.item-action:active {
filter: brightness(0.86);
}
}
}
}
</style>
<template>
<view class="network-select">
<view class="network-region">
<view class="text">深圳</view>
<u-icon name="arrow-down" size="8"></u-icon>
</view>
<view class="network-search">
<u-icon name="search" color="#B2B2B2" size="20"></u-icon>
<u--input placeholder="网点搜索" max-length="20"></u--input>
</view>
</view>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { CommonAPI } from '@/api'
// 获取地狱数据
const getSecondDistrictInfo = async () => {
const res = await CommonAPI.getSecondDistrictInfo()
if (res && res.code === '200') {
// regionList.value = res.result
// console.log(res)
}
}
// 组件挂载
onMounted(() => {
getSecondDistrictInfo()
})
</script>
<style scoped lang="scss">
.network-select {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 30rpx 0 16rpx 0;
.network-search {
width: 580rpx;
height: 64rpx;
background: #fdf1ed;
border-radius: 32rpx;
font-size: 28rpx;
font-weight: 400;
color: #b2b2b2;
display: flex;
justify-content: flex-start;
align-items: center;
box-sizing: border-box;
padding: 0 16rpx;
}
.network-region {
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 400;
color: #000000;
line-height: 40rpx;
margin-right: 20rpx;
.text {
margin-right: 8rpx;
}
}
}
</style>
// import 'vue' // 必须要引入vue,否则就成了覆盖
import { StateType } from '@/store/index.d'
import { InjectionKey } from 'vue'
import { Store } from 'vuex'
/**
* 这里为什么用vue,而不用@vue/runtime-core,是因为使用pnpm安装依赖是,node_modules中没有@vue/runtime-core,
* 会导致找不到模块而类型声明失败。
*/
// declare module '@vue/runtime-core' {
declare module 'vue' {
interface ComponentCustomProperties {
// 这里扩展this.$store,还可以在这里对this添加其他的声明
$store: Store<StateType>
}
}
// 扩展useStore声明
declare module 'vuex' {
export function useStore<S = StateType>(injectKey?: InjectionKey<Store<S>> | string): Store<S>
}
// 这个导出一个东西也可以,或者上面引入vue
export {}
import { rootStateType } from './index'
import { systemStateType } from './modules/system'
export interface StateType extends rootStateType {
system: systemStateType
}
import { createStore } from 'vuex'
import { StateType } from './index.d'
// 批量引入其他module,
const files = import.meta.globEager('./modules/*.ts') // vite的写法
const keys = Object.keys(files)
const modules: any = {}
keys.forEach((key) => {
if (Object.prototype.hasOwnProperty.call(files, key)) {
// 提取文件的名字作为模块名
modules[key.replace(/(\.\/modules\/|\.ts)/g, '')] = files[key].default
}
})
/** 全局的state,这个看自己的需求,如果有用到就在createStore中添加 */
export interface rootStateType {}
export default createStore<StateType>({
modules
})
import { Module } from 'vuex'
import { rootStateType } from '@/store'
export interface systemStateType {
title: string
}
const systemModule: Module<systemStateType, rootStateType> = {
namespaced: true,
state: () => ({
title: '你好,我是uni-app'
})
}
export default systemModule
......@@ -11,7 +11,8 @@
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
@import '@/uni_modules/uview-ui/theme.scss';
@import 'uview-plus/theme.scss';
/* 颜色变量 */
/* 行为相关颜色 */
......@@ -21,56 +22,56 @@ $uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color: #333; // 基本色
$uni-text-color-inverse: #fff; // 反色
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
$uni-bg-color: #fff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
$uni-bg-color-mask: rgb(0 0 0 / 40%); // 遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
$uni-font-size-sm: 24rpx;
$uni-font-size-base: 28rpx;
$uni-font-size-lg: 32rpx;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
$uni-img-size-sm: 40rpx;
$uni-img-size-base: 52rpx;
$uni-img-size-lg: 80rpx;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-sm: 4rpx;
$uni-border-radius-base: 6rpx;
$uni-border-radius-lg: 12rpx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20rpx;
$uni-spacing-row-lg: 30rpx;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
$uni-spacing-col-sm: 8rpx;
$uni-spacing-col-base: 16rpx;
$uni-spacing-col-lg: 24rpx;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
$uni-color-title: #2c405a; // 文章标题颜色
$uni-font-size-title: 40rpx;
$uni-color-subtitle: #555; // 二级标题颜色
$uni-font-size-subtitle: 36rpx;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 30rpx;
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
export default function MapLoader() {
window._AMapSecurityConfig = {
securityJsCode:'d78a13e2379db4234cae886709151ddf',
}
return new Promise((resolve, reject) => {
if (window.AMap) {
resolve(window.AMap);
} else {
var script = document.createElement('script');
script.type = "text/javascript";
script.async = true;
script.src =
"https://webapi.amap.com/maps?v=1.4.10&key=d78a13e2379db4234cae886709151ddf&plugin=AMap.Autocomplete,AMap.PlaceSearch,AMap.Geocoder,AMap.MarkerClusterer";
script.onerror = reject;
document.head.appendChild(script);
}
window.initAMap = () => {
resolve(window.AMap);
};
});
}
module.exports = {
extends: [
'stylelint-config-standard-scss',
'stylelint-config-recommended-vue',
'stylelint-config-recommended-vue/scss',
'stylelint-config-rational-order',
'stylelint-config-prettier'
],
rules: {
// 使用2格缩进
indentation: 2,
// 可以使用rpx单位
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }]
}
}
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom"
],
"types": [
"@dcloudio/types",
"miniprogram-api-typings",
"uview-plus",
"@ttou/uview-typings/v26",
"@ttou/uview-typings/refs"
],
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"env/index.d.ts"
]
}
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView 2.0</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues)
[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com)
[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases)
[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License)
## 说明
uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
## [官方文档:https://uviewui.com](https://uviewui.com)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
## 链接
- [官方文档](https://www.uviewui.com/)
- [更新日志](https://www.uviewui.com/components/changelog.html)
- [升级指南](https://www.uviewui.com/components/changeGuide.html)
- [关于我们](https://www.uviewui.com/cooperation/about.html)
## 交流反馈
欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html)
## 关于PR
> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。
> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢!
## 安装
#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593)
请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容
## 快速上手
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
```html
<template>
<u-button text="按钮"></u-button>
</template>
```
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。
<template>
<uvForm
ref="uForm"
:model="model"
:rules="rules"
:errorType="errorType"
:borderBottom="borderBottom"
:labelPosition="labelPosition"
:labelWidth="labelWidth"
:labelAlign="labelAlign"
:labelStyle="labelStyle"
:customStyle="customStyle"
>
<slot />
</uvForm>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件
* 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
*/
import uvForm from '../u-form/u-form.vue';
import props from '../u-form/props.js'
export default {
// #ifdef MP-WEIXIN
name: 'u-form',
// #endif
// #ifndef MP-WEIXIN
name: 'u--form',
// #endif
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvForm
},
created() {
this.children = []
},
methods: {
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
setRules(rules) {
this.$refs.uForm.setRules(rules)
},
validate() {
/**
* 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form
* 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的
* 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children
*/
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validate()
},
validateField(value, callback) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validateField(value, callback)
},
resetFields() {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.resetFields()
},
clearValidate(props) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.clearValidate(props)
},
setMpData() {
this.$refs.uForm.children = this.children
}
},
}
</script>
<template>
<uvImage
:src="src"
:mode="mode"
:width="width"
:height="height"
:shape="shape"
:radius="radius"
:lazyLoad="lazyLoad"
:showMenuByLongpress="showMenuByLongpress"
:loadingIcon="loadingIcon"
:errorIcon="errorIcon"
:showLoading="showLoading"
:showError="showError"
:fade="fade"
:webp="webp"
:duration="duration"
:bgColor="bgColor"
:customStyle="customStyle"
@click="$emit('click')"
@error="$emit('error')"
@load="$emit('load')"
>
<template v-slot:loading>
<slot name="loading"></slot>
</template>
<template v-slot:error>
<slot name="error"></slot>
</template>
</uvImage>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件
* 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
*/
import uvImage from '../u-image/u-image.vue';
import props from '../u-image/props.js';
export default {
name: 'u--image',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvImage
},
}
</script>
\ No newline at end of file
<template>
<uvInput
:value="value"
:type="type"
:fixed="fixed"
:disabled="disabled"
:disabledColor="disabledColor"
:clearable="clearable"
:password="password"
:maxlength="maxlength"
:placeholder="placeholder"
:placeholderClass="placeholderClass"
:placeholderStyle="placeholderStyle"
:showWordLimit="showWordLimit"
:confirmType="confirmType"
:confirmHold="confirmHold"
:holdKeyboard="holdKeyboard"
:focus="focus"
:autoBlur="autoBlur"
:disableDefaultPadding="disableDefaultPadding"
:cursor="cursor"
:cursorSpacing="cursorSpacing"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:inputAlign="inputAlign"
:fontSize="fontSize"
:color="color"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:suffixIconStyle="suffixIconStyle"
:prefixIconStyle="prefixIconStyle"
:border="border"
:readonly="readonly"
:shape="shape"
:customStyle="customStyle"
:formatter="formatter"
@focus="$emit('focus')"
@blur="e => $emit('blur', e)"
@keyboardheightchange="$emit('keyboardheightchange')"
@change="e => $emit('change', e)"
@input="e => $emit('input', e)"
@confirm="e => $emit('confirm', e)"
@clear="$emit('clear')"
@click="$emit('click')"
>
<!-- #ifdef MP -->
<slot name="prefix"></slot>
<slot name="suffix"></slot>
<!-- #endif -->
<!-- #ifndef MP -->
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
<!-- #endif -->
</uvInput>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
*/
import uvInput from '../u-input/u-input.vue';
import props from '../u-input/props.js'
export default {
name: 'u--input',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvInput
},
}
</script>
\ No newline at end of file
<template>
<uvText
:type="type"
:show="show"
:text="text"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:mode="mode"
:href="href"
:format="format"
:call="call"
:openType="openType"
:bold="bold"
:block="block"
:lines="lines"
:color="color"
:decoration="decoration"
:size="size"
:iconStyle="iconStyle"
:margin="margin"
:lineHeight="lineHeight"
:align="align"
:wordWrap="wordWrap"
:customStyle="customStyle"
@click="$emit('click')"
></uvText>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转
* 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
*/
import uvText from "../u-text/u-text.vue";
import props from "../u-text/props.js";
export default {
name: "u--text",
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvText,
},
};
</script>
<template>
<uvTextarea
:value="value"
:placeholder="placeholder"
:height="height"
:confirmType="confirmType"
:disabled="disabled"
:count="count"
:focus="focus"
:autoHeight="autoHeight"
:fixed="fixed"
:cursorSpacing="cursorSpacing"
:cursor="cursor"
:showConfirmBar="showConfirmBar"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:disableDefaultPadding="disableDefaultPadding"
:holdKeyboard="holdKeyboard"
:maxlength="maxlength"
:border="border"
:customStyle="customStyle"
:formatter="formatter"
@focus="e => $emit('focus')"
@blur="e => $emit('blur')"
@linechange="e => $emit('linechange', e)"
@confirm="e => $emit('confirm')"
@input="e => $emit('input', e)"
@keyboardheightchange="e => $emit('keyboardheightchange')"
></uvTextarea>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件
* 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
*/
import uvTextarea from '../u-textarea/u-textarea.vue';
import props from '../u-textarea/props.js'
export default {
name: 'u--textarea',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvTextarea
},
}
</script>
export default {
props: {
// 操作菜单是否展示 (默认false)
show: {
type: Boolean,
default: uni.$u.props.actionSheet.show
},
// 标题
title: {
type: String,
default: uni.$u.props.actionSheet.title
},
// 选项上方的描述信息
description: {
type: String,
default: uni.$u.props.actionSheet.description
},
// 数据
actions: {
type: Array,
default: uni.$u.props.actionSheet.actions
},
// 取消按钮的文字,不为空时显示按钮
cancelText: {
type: String,
default: uni.$u.props.actionSheet.cancelText
},
// 点击某个菜单项时是否关闭弹窗
closeOnClickAction: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickAction
},
// 处理底部安全区(默认true)
safeAreaInsetBottom: {
type: Boolean,
default: uni.$u.props.actionSheet.safeAreaInsetBottom
},
// 小程序的打开方式
openType: {
type: String,
default: uni.$u.props.actionSheet.openType
},
// 点击遮罩是否允许关闭 (默认true)
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickOverlay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.actionSheet.round
}
}
}
<template>
<u-popup
:show="show"
mode="bottom"
@close="closeHandler"
:safeAreaInsetBottom="safeAreaInsetBottom"
:round="round"
>
<view class="u-action-sheet">
<view
class="u-action-sheet__header"
v-if="title"
>
<text class="u-action-sheet__header__title u-line-1">{{title}}</text>
<view
class="u-action-sheet__header__icon-wrap"
@tap.stop="cancel"
>
<u-icon
name="close"
size="17"
color="#c8c9cc"
bold
></u-icon>
</view>
</view>
<text
class="u-action-sheet__description"
:style="[{
marginTop: `${title && description ? 0 : '18px'}`
}]"
v-if="description"
>{{description}}</text>
<slot>
<u-line v-if="description"></u-line>
<view class="u-action-sheet__item-wrap">
<template v-for="(item, index) in actions">
<!-- #ifdef MP -->
<button
:key="index"
class="u-reset-button"
:openType="item.openType"
@getuserinfo="onGetUserInfo"
@contact="onContact"
@getphonenumber="onGetPhoneNumber"
@error="onError"
@launchapp="onLaunchApp"
@opensetting="onOpenSetting"
:lang="lang"
:session-from="sessionFrom"
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
:app-parameter="appParameter"
@tap="selectHandler(index)"
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
>
<!-- #endif -->
<view
class="u-action-sheet__item-wrap__item"
@tap.stop="selectHandler(index)"
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
:hover-stay-time="150"
>
<template v-if="!item.loading">
<text
class="u-action-sheet__item-wrap__item__name"
:style="[itemStyle(index)]"
>{{ item.name }}</text>
<text
v-if="item.subname"
class="u-action-sheet__item-wrap__item__subname"
>{{ item.subname }}</text>
</template>
<u-loading-icon
v-else
custom-class="van-action-sheet__loading"
size="18"
mode="circle"
/>
</view>
<!-- #ifdef MP -->
</button>
<!-- #endif -->
<u-line v-if="index !== actions.length - 1"></u-line>
</template>
</view>
</slot>
<u-gap
bgColor="#eaeaec"
height="6"
v-if="cancelText"
></u-gap>
<view hover-class="u-action-sheet--hover">
<text
@touchmove.stop.prevent
:hover-stay-time="150"
v-if="cancelText"
class="u-action-sheet__cancel-text"
@tap="cancel"
>{{cancelText}}</text>
</view>
</view>
</u-popup>
</template>
<script>
import openType from '../../libs/mixin/openType'
import button from '../../libs/mixin/button'
import props from './props.js';
/**
* ActionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
* @tutorial https://www.uviewui.com/components/actionSheet.html
*
* @property {Boolean} show 操作菜单是否展示 (默认 false )
* @property {String} title 操作菜单标题
* @property {String} description 选项上方的描述信息
* @property {Array<Object>} actions 按钮的文字数组,见官方文档示例
* @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
* @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true )
* @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true )
* @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
* @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
* @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
* @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
* @property {String} sessionFrom 会话来源,openType="contact"时有效
* @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
* @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
* @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
* @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
*
* @event {Function} select 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
* @event {Function} contact 客服消息回调,openType="contact"时有效
* @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效
* @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效
* @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效
* @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效
* @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
// 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
mixins: [openType, button, uni.$u.mixin, props],
data() {
return {
}
},
computed: {
// 操作项目的样式
itemStyle() {
return (index) => {
let style = {};
if (this.actions[index].color) style.color = this.actions[index].color
if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize)
// 选项被禁用的样式
if (this.actions[index].disabled) style.color = '#c0c4cc'
return style;
}
},
},
methods: {
closeHandler() {
// 允许点击遮罩关闭时,才发出close事件
if(this.closeOnClickOverlay) {
this.$emit('close')
}
},
// 点击取消按钮
cancel() {
this.$emit('close')
},
selectHandler(index) {
const item = this.actions[index]
if (item && !item.disabled && !item.loading) {
this.$emit('select', item)
if (this.closeOnClickAction) {
this.$emit('close')
}
}
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-action-sheet-reset-button-width:100% !default;
$u-action-sheet-title-font-size: 16px !default;
$u-action-sheet-title-padding: 12px 30px !default;
$u-action-sheet-title-color: $u-main-color !default;
$u-action-sheet-header-icon-wrap-right:15px !default;
$u-action-sheet-header-icon-wrap-top:15px !default;
$u-action-sheet-description-font-size:13px !default;
$u-action-sheet-description-color:14px !default;
$u-action-sheet-description-margin: 18px 15px !default;
$u-action-sheet-item-wrap-item-padding:15px !default;
$u-action-sheet-item-wrap-name-font-size:16px !default;
$u-action-sheet-item-wrap-subname-font-size:13px !default;
$u-action-sheet-item-wrap-subname-color: #c0c4cc !default;
$u-action-sheet-item-wrap-subname-margin-top:10px !default;
$u-action-sheet-cancel-text-font-size:16px !default;
$u-action-sheet-cancel-text-color:$u-content-color !default;
$u-action-sheet-cancel-text-font-size:15px !default;
$u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
.u-reset-button {
width: $u-action-sheet-reset-button-width;
}
.u-action-sheet {
text-align: center;
&__header {
position: relative;
padding: $u-action-sheet-title-padding;
&__title {
font-size: $u-action-sheet-title-font-size;
color: $u-action-sheet-title-color;
font-weight: bold;
text-align: center;
}
&__icon-wrap {
position: absolute;
right: $u-action-sheet-header-icon-wrap-right;
top: $u-action-sheet-header-icon-wrap-top;
}
}
&__description {
font-size: $u-action-sheet-description-font-size;
color: $u-tips-color;
margin: $u-action-sheet-description-margin;
text-align: center;
}
&__item-wrap {
&__item {
padding: $u-action-sheet-item-wrap-item-padding;
@include flex;
align-items: center;
justify-content: center;
flex-direction: column;
&__name {
font-size: $u-action-sheet-item-wrap-name-font-size;
color: $u-main-color;
text-align: center;
}
&__subname {
font-size: $u-action-sheet-item-wrap-subname-font-size;
color: $u-action-sheet-item-wrap-subname-color;
margin-top: $u-action-sheet-item-wrap-subname-margin-top;
text-align: center;
}
}
}
&__cancel-text {
font-size: $u-action-sheet-cancel-text-font-size;
color: $u-action-sheet-cancel-text-color;
text-align: center;
padding: $u-action-sheet-cancel-text-font-size;
}
&--hover {
background-color: $u-action-sheet-cancel-text-hover-background-color;
}
}
</style>
export default {
props: {
// 图片地址,Array<String>|Array<Object>形式
urls: {
type: Array,
default: uni.$u.props.album.urls
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.album.keyName
},
// 单图时,图片长边的长度
singleSize: {
type: [String, Number],
default: uni.$u.props.album.singleSize
},
// 多图时,图片边长
multipleSize: {
type: [String, Number],
default: uni.$u.props.album.multipleSize
},
// 多图时,图片水平和垂直之间的间隔
space: {
type: [String, Number],
default: uni.$u.props.album.space
},
// 单图时,图片缩放裁剪的模式
singleMode: {
type: String,
default: uni.$u.props.album.singleMode
},
// 多图时,图片缩放裁剪的模式
multipleMode: {
type: String,
default: uni.$u.props.album.multipleMode
},
// 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
maxCount: {
type: [String, Number],
default: uni.$u.props.album.maxCount
},
// 是否可以预览图片
previewFullImage: {
type: Boolean,
default: uni.$u.props.album.previewFullImage
},
// 每行展示图片数量,如设置,singleSize和multipleSize将会无效
rowCount: {
type: [String, Number],
default: uni.$u.props.album.rowCount
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.album.showMore
}
}
}
export default {
props: {
// 显示文字
title: {
type: String,
default: uni.$u.props.alert.title
},
// 主题,success/warning/info/error
type: {
type: String,
default: uni.$u.props.alert.type
},
// 辅助性文字
description: {
type: String,
default: uni.$u.props.alert.description
},
// 是否可关闭
closable: {
type: Boolean,
default: uni.$u.props.alert.closable
},
// 是否显示图标
showIcon: {
type: Boolean,
default: uni.$u.props.alert.showIcon
},
// 浅或深色调,light-浅色,dark-深色
effect: {
type: String,
default: uni.$u.props.alert.effect
},
// 文字是否居中
center: {
type: Boolean,
default: uni.$u.props.alert.center
},
// 字体大小
fontSize: {
type: [String, Number],
default: uni.$u.props.alert.fontSize
}
}
}
<template>
<u-transition
mode="fade"
:show="show"
>
<view
class="u-alert"
:class="[`u-alert--${type}--${effect}`]"
@tap.stop="clickHandler"
:style="[$u.addStyle(customStyle)]"
>
<view
class="u-alert__icon"
v-if="showIcon"
>
<u-icon
:name="iconName"
size="18"
:color="iconColor"
></u-icon>
</view>
<view
class="u-alert__content"
:style="[{
paddingRight: closable ? '20px' : 0
}]"
>
<text
class="u-alert__content__title"
v-if="title"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ title }}</text>
<text
class="u-alert__content__desc"
v-if="description"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ description }}</text>
</view>
<view
class="u-alert__close"
v-if="closable"
@tap.stop="closeHandler"
>
<u-icon
name="close"
:color="iconColor"
size="15"
></u-icon>
</view>
</view>
</u-transition>
</template>
<script>
import props from './props.js';
/**
* Alert 警告提示
* @description 警告提示,展现需要关注的信息。
* @tutorial https://www.uviewui.com/components/alertTips.html
*
* @property {String} title 显示的文字
* @property {String} type 使用预设的颜色 (默认 'warning' )
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
* @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
* @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
* @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
* @property {Boolean} center 文字是否居中 (默认 false )
* @property {String | Number} fontSize 字体大小 (默认 14 )
* @property {Object} customStyle 定义需要用到的外部样式
* @event {Function} click 点击组件时触发
* @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert>
*/
export default {
name: 'u-alert',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
show: true
}
},
computed: {
iconColor() {
return this.effect === 'light' ? this.type : '#fff'
},
// 不同主题对应不同的图标
iconName() {
switch (this.type) {
case 'success':
return 'checkmark-circle-fill';
break;
case 'error':
return 'close-circle-fill';
break;
case 'warning':
return 'error-circle-fill';
break;
case 'info':
return 'info-circle-fill';
break;
case 'primary':
return 'more-circle-fill';
break;
default:
return 'error-circle-fill';
}
}
},
methods: {
// 点击内容
clickHandler() {
this.$emit('click')
},
// 点击关闭按钮
closeHandler() {
this.show = false
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-alert {
position: relative;
background-color: $u-primary;
padding: 8px 10px;
@include flex(row);
align-items: center;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
&--primary--dark {
background-color: $u-primary;
}
&--primary--light {
background-color: #ecf5ff;
}
&--error--dark {
background-color: $u-error;
}
&--error--light {
background-color: #FEF0F0;
}
&--success--dark {
background-color: $u-success;
}
&--success--light {
background-color: #f5fff0;
}
&--warning--dark {
background-color: $u-warning;
}
&--warning--light {
background-color: #FDF6EC;
}
&--info--dark {
background-color: $u-info;
}
&--info--light {
background-color: #f4f4f5;
}
&__icon {
margin-right: 5px;
}
&__content {
@include flex(column);
flex: 1;
&__title {
color: $u-main-color;
font-size: 14px;
font-weight: bold;
color: #fff;
margin-bottom: 2px;
}
&__desc {
color: $u-main-color;
font-size: 14px;
flex-wrap: wrap;
color: #fff;
}
}
&__title--dark,
&__desc--dark {
color: #FFFFFF;
}
&__text--primary--light,
&__text--primary--light {
color: $u-primary;
}
&__text--success--light,
&__text--success--light {
color: $u-success;
}
&__text--warning--light,
&__text--warning--light {
color: $u-warning;
}
&__text--error--light,
&__text--error--light {
color: $u-error;
}
&__text--info--light,
&__text--info--light {
color: $u-info;
}
&__close {
position: absolute;
top: 11px;
right: 10px;
}
}
</style>
export default {
props: {
// 头像图片组
urls: {
type: Array,
default: uni.$u.props.avatarGroup.urls
},
// 最多展示的头像数量
maxCount: {
type: [String, Number],
default: uni.$u.props.avatarGroup.maxCount
},
// 头像形状
shape: {
type: String,
default: uni.$u.props.avatarGroup.shape
},
// 图片裁剪模式
mode: {
type: String,
default: uni.$u.props.avatarGroup.mode
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.avatarGroup.showMore
},
// 头像大小
size: {
type: [String, Number],
default: uni.$u.props.avatarGroup.size
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.avatarGroup.keyName
},
// 头像之间的遮挡比例
gap: {
type: [String, Number],
validator(value) {
return value >= 0 && value <= 1
},
default: uni.$u.props.avatarGroup.gap
},
// 需额外显示的值
extraValue: {
type: [Number, String],
default: uni.$u.props.avatarGroup.extraValue
}
}
}
<template>
<view class="u-avatar-group">
<view
class="u-avatar-group__item"
v-for="(item, index) in showUrl"
:key="index"
:style="{
marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap)
}"
>
<u-avatar
:size="size"
:shape="shape"
:mode="mode"
:src="$u.test.object(item) ? keyName && item[keyName] || item.url : item"
></u-avatar>
<view
class="u-avatar-group__item__show-more"
v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
@tap="clickHandler"
>
<u--text
color="#ffffff"
:size="size * 0.4"
:text="`+${extraValue || urls.length - showUrl.length}`"
align="center"
customStyle="justify-content: center"
></u--text>
</view>
</view>
</view>
</template>
<script>
import props from './props.js';
/**
* AvatarGroup 头像组
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
* @tutorial https://www.uviewui.com/components/avatar.html
*
* @property {Array} urls 头像图片组 (默认 [] )
* @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
* @property {String} shape 头像形状( 'circle' (默认) | 'square' )
* @property {String} mode 图片裁剪模式(默认 'scaleToFill' )
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
* @property {String | Number} size 头像大小 (默认 40 )
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
* @property {String | Number} gap 头像之间的遮挡比例(0.4代表遮挡40%) (默认 0.5 )
* @property {String | Number} extraValue 需额外显示的值
* @event {Function} showMore 头像组更多点击
* @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
*/
export default {
name: 'u-avatar-group',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
}
},
computed: {
showUrl() {
return this.urls.slice(0, this.maxCount)
}
},
methods: {
clickHandler() {
this.$emit('showMore')
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-avatar-group {
@include flex;
&__item {
margin-left: -10px;
position: relative;
&--no-indent {
// 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
margin-left: 0;
}
&__show-more {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
@include flex;
align-items: center;
justify-content: center;
border-radius: 100px;
}
}
}
</style>
export default {
props: {
// 头像图片路径(不能为相对路径)
src: {
type: String,
default: uni.$u.props.avatar.src
},
// 头像形状,circle-圆形,square-方形
shape: {
type: String,
default: uni.$u.props.avatar.shape
},
// 头像尺寸
size: {
type: [String, Number],
default: uni.$u.props.avatar.size
},
// 裁剪模式
mode: {
type: String,
default: uni.$u.props.avatar.mode
},
// 显示的文字
text: {
type: String,
default: uni.$u.props.avatar.text
},
// 背景色
bgColor: {
type: String,
default: uni.$u.props.avatar.bgColor
},
// 文字颜色
color: {
type: String,
default: uni.$u.props.avatar.color
},
// 文字大小
fontSize: {
type: [String, Number],
default: uni.$u.props.avatar.fontSize
},
// 显示的图标
icon: {
type: String,
default: uni.$u.props.avatar.icon
},
// 显示小程序头像,只对百度,微信,QQ小程序有效
mpAvatar: {
type: Boolean,
default: uni.$u.props.avatar.mpAvatar
},
// 是否使用随机背景色
randomBgColor: {
type: Boolean,
default: uni.$u.props.avatar.randomBgColor
},
// 加载失败的默认头像(组件有内置默认图片)
defaultUrl: {
type: String,
default: uni.$u.props.avatar.defaultUrl
},
// 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
colorIndex: {
type: [String, Number],
// 校验参数规则,索引在0-19之间
validator(n) {
return uni.$u.test.range(n, [0, 19]) || n === ''
},
default: uni.$u.props.avatar.colorIndex
},
// 组件标识符
name: {
type: String,
default: uni.$u.props.avatar.name
}
}
}
<template>
<view
class="u-avatar"
:class="[`u-avatar--${shape}`]"
:style="[{
backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : $u.random(0, 19)] : bgColor) : 'transparent',
width: $u.addUnit(size),
height: $u.addUnit(size),
}, $u.addStyle(customStyle)]"
@tap="clickHandler"
>
<slot>
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
<open-data
v-if="mpAvatar && allowMp"
type="userAvatarUrl"
:style="[{
width: $u.addUnit(size),
height: $u.addUnit(size)
}]"
/>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU -->
<template v-if="mpAvatar && allowMp"></template>
<!-- #endif -->
<u-icon
v-else-if="icon"
:name="icon"
:size="fontSize"
:color="color"
></u-icon>
<u--text
v-else-if="text"
:text="text"
:size="fontSize"
:color="color"
align="center"
customStyle="justify-content: center"
></u--text>
<image
class="u-avatar__image"
v-else
:class="[`u-avatar__image--${shape}`]"
:src="avatarUrl || defaultUrl"
:mode="mode"
@error="errorHandler"
:style="[{
width: $u.addUnit(size),
height: $u.addUnit(size)
}]"
></image>
</slot>
</view>
</template>
<script>
import props from './props.js';
const base64Avatar =
"data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
/**
* Avatar 头像
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
* @tutorial https://www.uviewui.com/components/avatar.html
*
* @property {String} src 头像路径,如加载失败,将会显示默认头像(不能为相对路径)
* @property {String} shape 头像形状 ( circle (默认) | square)
* @property {String | Number} size 头像尺寸,可以为指定字符串(large, default, mini),或者数值 (默认 40 )
* @property {String} mode 头像图片的裁剪类型,与uni的image组件的mode参数一致,如效果达不到需求,可尝试传widthFix值 (默认 'scaleToFill' )
* @property {String} text 用文字替代图片,级别优先于src
* @property {String} bgColor 背景颜色,一般显示文字时用 (默认 '#c0c4cc' )
* @property {String} color 文字颜色 (默认 '#ffffff' )
* @property {String | Number} fontSize 文字大小 (默认 18 )
* @property {String} icon 显示的图标
* @property {Boolean} mpAvatar 显示小程序头像,只对百度,微信,QQ小程序有效 (默认 false )
* @property {Boolean} randomBgColor 是否使用随机背景色 (默认 false )
* @property {String} defaultUrl 加载失败的默认头像(组件有内置默认图片)
* @property {String | Number} colorIndex 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
* @property {String} name 组件标识符 (默认 'level' )
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function} click 点击组件时触发 index: 用户传递的标识符
* @example <u-avatar :src="src" mode="square"></u-avatar>
*/
export default {
name: 'u-avatar',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
// 如果配置randomBgColor参数为true,在图标或者文字的模式下,会随机从中取出一个颜色值当做背景色
colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2',
'#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee',
'#73d1f1',
'#80a7dc'
],
avatarUrl: this.src,
allowMp: false
}
},
watch: {
// 监听头像src的变化,赋值给内部的avatarUrl变量,因为图片加载失败时,需要修改图片的src为默认值
// 而组件内部不能直接修改props的值,所以需要一个中间变量
src: {
immediate: true,
handler(newVal) {
this.avatarUrl = newVal
// 如果没有传src,则主动触发error事件,用于显示默认的头像,否则src为''空字符等的时候,会无内容展示
if(!newVal) {
this.errorHandler()
}
}
}
},
computed: {
imageStyle() {
const style = {}
return style
}
},
created() {
this.init()
},
methods: {
init() {
// 目前只有这几个小程序平台具有open-data标签
// 其他平台可以通过uni.getUserInfo类似接口获取信息,但是需要弹窗授权(首次),不合符组件逻辑
// 故目前自动获取小程序头像只支持这几个平台
// #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU
this.allowMp = true
// #endif
},
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
isImg() {
return this.src.indexOf('/') !== -1
},
// 图片加载时失败时触发
errorHandler() {
this.avatarUrl = this.defaultUrl || base64Avatar
},
clickHandler() {
this.$emit('click', this.name)
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-avatar {
@include flex;
align-items: center;
justify-content: center;
&--circle {
border-radius: 100px;
}
&--square {
border-radius: 4px;
}
&__image {
&--circle {
border-radius: 100px;
}
&--square {
border-radius: 4px;
}
}
}
</style>
export default {
props: {
// 返回顶部的形状,circle-圆形,square-方形
mode: {
type: String,
default: uni.$u.props.backtop.mode
},
// 自定义图标
icon: {
type: String,
default: uni.$u.props.backtop.icon
},
// 提示文字
text: {
type: String,
default: uni.$u.props.backtop.text
},
// 返回顶部滚动时间
duration: {
type: [String, Number],
default: uni.$u.props.backtop.duration
},
// 滚动距离
scrollTop: {
type: [String, Number],
default: uni.$u.props.backtop.scrollTop
},
// 距离顶部多少距离显示,单位px
top: {
type: [String, Number],
default: uni.$u.props.backtop.top
},
// 返回顶部按钮到底部的距离,单位px
bottom: {
type: [String, Number],
default: uni.$u.props.backtop.bottom
},
// 返回顶部按钮到右边的距离,单位px
right: {
type: [String, Number],
default: uni.$u.props.backtop.right
},
// 层级
zIndex: {
type: [String, Number],
default: uni.$u.props.backtop.zIndex
},
// 图标的样式,对象形式
iconStyle: {
type: Object,
default: uni.$u.props.backtop.iconStyle
}
}
}
<template>
<u-transition
mode="fade"
:customStyle="backTopStyle"
:show="show"
>
<view
class="u-back-top"
:style="[contentStyle]"
v-if="!$slots.default && !$slots.$default"
@click="backToTop"
>
<u-icon
:name="icon"
:custom-style="iconStyle"
></u-icon>
<text
v-if="text"
class="u-back-top__text"
>{{text}}</text>
</view>
<slot v-else />
</u-transition>
</template>
<script>
import props from './props.js';
// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif
/**
* backTop 返回顶部
* @description 本组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
* @tutorial https://uviewui.com/components/backTop.html
*
* @property {String} mode 返回顶部的形状,circle-圆形,square-方形 (默认 'circle' )
* @property {String} icon 自定义图标 (默认 'arrow-upward' ) 见官方文档示例
* @property {String} text 提示文字
* @property {String | Number} duration 返回顶部滚动时间 (默认 100)
* @property {String | Number} scrollTop 滚动距离 (默认 0 )
* @property {String | Number} top 距离顶部多少距离显示,单位px (默认 400 )
* @property {String | Number} bottom 返回顶部按钮到底部的距离,单位px (默认 100 )
* @property {String | Number} right 返回顶部按钮到右边的距离,单位px (默认 20 )
* @property {String | Number} zIndex 层级 (默认 9 )
* @property {Object<Object>} iconStyle 图标的样式,对象形式 (默认 {color: '#909399',fontSize: '19px'})
* @property {Object} customStyle 定义需要用到的外部样式
*
* @example <u-back-top :scrollTop="scrollTop"></u-back-top>
*/
export default {
name: 'u-back-top',
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
computed: {
backTopStyle() {
// 动画组件样式
const style = {
bottom: uni.$u.addUnit(this.bottom),
right: uni.$u.addUnit(this.right),
width: '40px',
height: '40px',
position: 'fixed',
zIndex: 10,
}
return style
},
show() {
return uni.$u.getPx(this.scrollTop) > uni.$u.getPx(this.top)
},
contentStyle() {
const style = {}
let radius = 0
// 是否圆形
if(this.mode === 'circle') {
radius = '100px'
} else {
radius = '4px'
}
// 为了兼容安卓nvue,只能这么分开写
style.borderTopLeftRadius = radius
style.borderTopRightRadius = radius
style.borderBottomLeftRadius = radius
style.borderBottomRightRadius = radius
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
}
},
methods: {
backToTop() {
// #ifdef APP-NVUE
if (!this.$parent.$refs['u-back-top']) {
uni.$u.error(`nvue页面需要给页面最外层元素设置"ref='u-back-top'`)
}
dom.scrollToElement(this.$parent.$refs['u-back-top'], {
offset: 0
})
// #endif
// #ifndef APP-NVUE
uni.pageScrollTo({
scrollTop: 0,
duration: this.duration
});
// #endif
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/components.scss';
$u-back-top-flex:1 !default;
$u-back-top-height:100% !default;
$u-back-top-background-color:#E1E1E1 !default;
$u-back-top-tips-font-size:12px !default;
.u-back-top {
@include flex;
flex-direction: column;
align-items: center;
flex:$u-back-top-flex;
height: $u-back-top-height;
justify-content: center;
background-color: $u-back-top-background-color;
&__tips {
font-size:$u-back-top-tips-font-size;
transform: scale(0.8);
}
}
</style>
export default {
props: {
// 是否显示圆点
isDot: {
type: Boolean,
default: uni.$u.props.badge.isDot
},
// 显示的内容
value: {
type: [Number, String],
default: uni.$u.props.badge.value
},
// 是否显示
show: {
type: Boolean,
default: uni.$u.props.badge.show
},
// 最大值,超过最大值会显示 '{max}+'
max: {
type: [Number, String],
default: uni.$u.props.badge.max
},
// 主题类型,error|warning|success|primary
type: {
type: String,
default: uni.$u.props.badge.type
},
// 当数值为 0 时,是否展示 Badge
showZero: {
type: Boolean,
default: uni.$u.props.badge.showZero
},
// 背景颜色,优先级比type高,如设置,type参数会失效
bgColor: {
type: [String, null],
default: uni.$u.props.badge.bgColor
},
// 字体颜色
color: {
type: [String, null],
default: uni.$u.props.badge.color
},
// 徽标形状,circle-四角均为圆角,horn-左下角为直角
shape: {
type: String,
default: uni.$u.props.badge.shape
},
// 设置数字的显示方式,overflow|ellipsis|limit
// overflow会根据max字段判断,超出显示`${max}+`
// ellipsis会根据max判断,超出显示`${max}...`
// limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
numberType: {
type: String,
default: uni.$u.props.badge.numberType
},
// 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
offset: {
type: Array,
default: uni.$u.props.badge.offset
},
// 是否反转背景和字体颜色
inverted: {
type: Boolean,
default: uni.$u.props.badge.inverted
},
// 是否绝对定位
absolute: {
type: Boolean,
default: uni.$u.props.badge.absolute
}
}
}
<template>
<text
v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
:class="[isDot ? 'u-badge--dot' : 'u-badge--not-dot', inverted && 'u-badge--inverted', shape === 'horn' && 'u-badge--horn', `u-badge--${type}${inverted ? '--inverted' : ''}`]"
:style="[$u.addStyle(customStyle), badgeStyle]"
class="u-badge"
>{{ isDot ? '' :showValue }}</text>
</template>
<script>
import props from './props.js';
/**
* badge 徽标数
* @description 该组件一般用于图标右上角显示未读的消息数量,提示用户点击,有圆点和圆包含文字两种形式。
* @tutorial https://uviewui.com/components/badge.html
*
* @property {Boolean} isDot 是否显示圆点 (默认 false )
* @property {String | Number} value 显示的内容
* @property {Boolean} show 是否显示 (默认 true )
* @property {String | Number} max 最大值,超过最大值会显示 '{max}+' (默认999)
* @property {String} type 主题类型,error|warning|success|primary (默认 'error' )
* @property {Boolean} showZero 当数值为 0 时,是否展示 Badge (默认 false )
* @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效
* @property {String} color 字体颜色 (默认 '#ffffff' )
* @property {String} shape 徽标形状,circle-四角均为圆角,horn-左下角为直角 (默认 'circle' )
* @property {String} numberType 设置数字的显示方式,overflow|ellipsis|limit (默认 'overflow' )
* @property {Array}} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
* @property {Boolean} inverted 是否反转背景和字体颜色(默认 false )
* @property {Boolean} absolute 是否绝对定位(默认 false )
* @property {Object} customStyle 定义需要用到的外部样式
* @example <u-badge :type="type" :count="count"></u-badge>
*/
export default {
name: 'u-badge',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
computed: {
// 是否将badge中心与父组件右上角重合
boxStyle() {
let style = {};
return style;
},
// 整个组件的样式
badgeStyle() {
const style = {}
if(this.color) {
style.color = this.color
}
if (this.bgColor && !this.inverted) {
style.backgroundColor = this.bgColor
}
if (this.absolute) {
style.position = 'absolute'
// 如果有设置offset参数
if(this.offset.length) {
// top和right分为为offset的第一个和第二个值,如果没有第二个值,则right等于top
const top = this.offset[0]
const right = this.offset[1] || top
style.top = uni.$u.addUnit(top)
style.right = uni.$u.addUnit(right)
}
}
return style
},
showValue() {
switch (this.numberType) {
case "overflow":
return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
break;
case "ellipsis":
return Number(this.value) > Number(this.max) ? "..." : this.value
break;
case "limit":
return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
1e3 * 100) / 100 + "k" : this.value
break;
default:
return Number(this.value)
}
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-badge-primary: $u-primary !default;
$u-badge-error: $u-error !default;
$u-badge-success: $u-success !default;
$u-badge-info: $u-info !default;
$u-badge-warning: $u-warning !default;
$u-badge-dot-radius: 100px !default;
$u-badge-dot-size: 8px !default;
$u-badge-dot-right: 4px !default;
$u-badge-dot-top: 0 !default;
$u-badge-text-font-size: 11px !default;
$u-badge-text-right: 10px !default;
$u-badge-text-padding: 2px 5px !default;
$u-badge-text-align: center !default;
$u-badge-text-color: #FFFFFF !default;
.u-badge {
border-top-right-radius: $u-badge-dot-radius;
border-top-left-radius: $u-badge-dot-radius;
border-bottom-left-radius: $u-badge-dot-radius;
border-bottom-right-radius: $u-badge-dot-radius;
@include flex;
line-height: $u-badge-text-font-size;
text-align: $u-badge-text-align;
font-size: $u-badge-text-font-size;
color: $u-badge-text-color;
&--dot {
height: $u-badge-dot-size;
width: $u-badge-dot-size;
}
&--inverted {
font-size: 13px;
}
&--not-dot {
padding: $u-badge-text-padding;
}
&--horn {
border-bottom-left-radius: 0;
}
&--primary {
background-color: $u-badge-primary;
}
&--primary--inverted {
color: $u-badge-primary;
}
&--error {
background-color: $u-badge-error;
}
&--error--inverted {
color: $u-badge-error;
}
&--success {
background-color: $u-badge-success;
}
&--success--inverted {
color: $u-badge-success;
}
&--info {
background-color: $u-badge-info;
}
&--info--inverted {
color: $u-badge-info;
}
&--warning {
background-color: $u-badge-warning;
}
&--warning--inverted {
color: $u-badge-warning;
}
}
</style>
$u-button-active-opacity:0.75 !default;
$u-button-loading-text-margin-left:4px !default;
$u-button-text-color: #FFFFFF !default;
$u-button-text-plain-error-color:$u-error !default;
$u-button-text-plain-warning-color:$u-warning !default;
$u-button-text-plain-success-color:$u-success !default;
$u-button-text-plain-info-color:$u-info !default;
$u-button-text-plain-primary-color:$u-primary !default;
.u-button {
&--active {
opacity: $u-button-active-opacity;
}
&--active--plain {
background-color: rgb(217, 217, 217);
}
&__loading-text {
margin-left:$u-button-loading-text-margin-left;
}
&__text,
&__loading-text {
color:$u-button-text-color;
}
&__text--plain--error {
color:$u-button-text-plain-error-color;
}
&__text--plain--warning {
color:$u-button-text-plain-warning-color;
}
&__text--plain--success{
color:$u-button-text-plain-success-color;
}
&__text--plain--info {
color:$u-button-text-plain-info-color;
}
&__text--plain--primary {
color:$u-button-text-plain-primary-color;
}
}
\ No newline at end of file
/*
* @Author : LQ
* @Description :
* @version : 1.0
* @Date : 2021-08-16 10:04:04
* @LastAuthor : LQ
* @lastTime : 2021-08-16 10:04:24
* @FilePath : /u-view2.0/uview-ui/components/u-button/props.js
*/
export default {
props: {
// 是否细边框
hairline: {
type: Boolean,
default: uni.$u.props.button.hairline
},
// 按钮的预置样式,info,primary,error,warning,success
type: {
type: String,
default: uni.$u.props.button.type
},
// 按钮尺寸,large,normal,small,mini
size: {
type: String,
default: uni.$u.props.button.size
},
// 按钮形状,circle(两边为半圆),square(带圆角)
shape: {
type: String,
default: uni.$u.props.button.shape
},
// 按钮是否镂空
plain: {
type: Boolean,
default: uni.$u.props.button.plain
},
// 是否禁止状态
disabled: {
type: Boolean,
default: uni.$u.props.button.disabled
},
// 是否加载中
loading: {
type: Boolean,
default: uni.$u.props.button.loading
},
// 加载中提示文字
loadingText: {
type: [String, Number],
default: uni.$u.props.button.loadingText
},
// 加载状态图标类型
loadingMode: {
type: String,
default: uni.$u.props.button.loadingMode
},
// 加载图标大小
loadingSize: {
type: [String, Number],
default: uni.$u.props.button.loadingSize
},
// 开放能力,具体请看uniapp稳定关于button组件部分说明
// https://uniapp.dcloud.io/component/button
openType: {
type: String,
default: uni.$u.props.button.openType
},
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
// 取值为submit(提交表单),reset(重置表单)
formType: {
type: String,
default: uni.$u.props.button.formType
},
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
// 只微信小程序、QQ小程序有效
appParameter: {
type: String,
default: uni.$u.props.button.appParameter
},
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
hoverStopPropagation: {
type: Boolean,
default: uni.$u.props.button.hoverStopPropagation
},
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
lang: {
type: String,
default: uni.$u.props.button.lang
},
// 会话来源,open-type="contact"时有效。只微信小程序有效
sessionFrom: {
type: String,
default: uni.$u.props.button.sessionFrom
},
// 会话内消息卡片标题,open-type="contact"时有效
// 默认当前标题,只微信小程序有效
sendMessageTitle: {
type: String,
default: uni.$u.props.button.sendMessageTitle
},
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
// 默认当前分享路径,只微信小程序有效
sendMessagePath: {
type: String,
default: uni.$u.props.button.sendMessagePath
},
// 会话内消息卡片图片,open-type="contact"时有效
// 默认当前页面截图,只微信小程序有效
sendMessageImg: {
type: String,
default: uni.$u.props.button.sendMessageImg
},
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效
showMessageCard: {
type: Boolean,
default: uni.$u.props.button.showMessageCard
},
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
dataName: {
type: String,
default: uni.$u.props.button.dataName
},
// 节流,一定时间内只能触发一次
throttleTime: {
type: [String, Number],
default: uni.$u.props.button.throttleTime
},
// 按住后多久出现点击态,单位毫秒
hoverStartTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStartTime
},
// 手指松开后点击态保留时间,单位毫秒
hoverStayTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStayTime
},
// 按钮文字,之所以通过props传入,是因为slot传入的话
// nvue中无法控制文字的样式
text: {
type: [String, Number],
default: uni.$u.props.button.text
},
// 按钮图标
icon: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮图标
iconColor: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮颜色,支持传入linear-gradient渐变色
color: {
type: String,
default: uni.$u.props.button.color
}
}
}
// nvue下hover-class无效
$u-button-before-top:50% !default;
$u-button-before-left:50% !default;
$u-button-before-width:100% !default;
$u-button-before-height:100% !default;
$u-button-before-transform:translate(-50%, -50%) !default;
$u-button-before-opacity:0 !default;
$u-button-before-background-color:#000 !default;
$u-button-before-border-color:#000 !default;
$u-button-active-before-opacity:.15 !default;
$u-button-icon-margin-left:4px !default;
$u-button-plain-u-button-info-color:$u-info;
$u-button-plain-u-button-success-color:$u-success;
$u-button-plain-u-button-error-color:$u-error;
$u-button-plain-u-button-warning-color:$u-error;
.u-button {
width: 100%;
&__text {
white-space: nowrap;
line-height: 1;
}
&:before {
position: absolute;
top:$u-button-before-top;
left:$u-button-before-left;
width:$u-button-before-width;
height:$u-button-before-height;
border: inherit;
border-radius: inherit;
transform:$u-button-before-transform;
opacity:$u-button-before-opacity;
content: " ";
background-color:$u-button-before-background-color;
border-color:$u-button-before-border-color;
}
&--active {
&:before {
opacity: .15
}
}
&__icon+&__text:not(:empty),
&__loading-text {
margin-left:$u-button-icon-margin-left;
}
&--plain {
&.u-button--primary {
color: $u-primary;
}
}
&--plain {
&.u-button--info {
color:$u-button-plain-u-button-info-color;
}
}
&--plain {
&.u-button--success {
color:$u-button-plain-u-button-success-color;
}
}
&--plain {
&.u-button--error {
color:$u-button-plain-u-button-error-color;
}
}
&--plain {
&.u-button--warning {
color:$u-button-plain-u-button-warning-color;
}
}
}
<template>
<view class="u-calendar-header u-border-bottom">
<text
class="u-calendar-header__title"
v-if="showTitle"
>{{ title }}</text>
<text
class="u-calendar-header__subtitle"
v-if="showSubtitle"
>{{ subtitle }}</text>
<view class="u-calendar-header__weekdays">
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
</view>
</view>
</template>
<script>
export default {
name: 'u-calendar-header',
mixins: [uni.$u.mpMixin, uni.$u.mixin],
props: {
// 标题
title: {
type: String,
default: ''
},
// 副标题
subtitle: {
type: String,
default: ''
},
// 是否显示标题
showTitle: {
type: Boolean,
default: true
},
// 是否显示副标题
showSubtitle: {
type: Boolean,
default: true
},
},
data() {
return {
}
},
methods: {
name() {
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-calendar-header {
padding-bottom: 4px;
&__title {
font-size: 16px;
color: $u-main-color;
text-align: center;
height: 42px;
line-height: 42px;
font-weight: bold;
}
&__subtitle {
font-size: 14px;
color: $u-main-color;
height: 40px;
text-align: center;
line-height: 40px;
font-weight: bold;
}
&__weekdays {
@include flex;
justify-content: space-between;
&__weekday {
font-size: 13px;
color: $u-main-color;
line-height: 30px;
flex: 1;
text-align: center;
}
}
}
</style>
export default {
props: {
// 日历顶部标题
title: {
type: String,
default: uni.$u.props.calendar.title
},
// 是否显示标题
showTitle: {
type: Boolean,
default: uni.$u.props.calendar.showTitle
},
// 是否显示副标题
showSubtitle: {
type: Boolean,
default: uni.$u.props.calendar.showSubtitle
},
// 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围
mode: {
type: String,
default: uni.$u.props.calendar.mode
},
// mode=range时,第一个日期底部的提示文字
startText: {
type: String,
default: uni.$u.props.calendar.startText
},
// mode=range时,最后一个日期底部的提示文字
endText: {
type: String,
default: uni.$u.props.calendar.endText
},
// 自定义列表
customList: {
type: Array,
default: uni.$u.props.calendar.customList
},
// 主题色,对底部按钮和选中日期有效
color: {
type: String,
default: uni.$u.props.calendar.color
},
// 最小的可选日期
minDate: {
type: [String, Number],
default: uni.$u.props.calendar.minDate
},
// 最大可选日期
maxDate: {
type: [String, Number],
default: uni.$u.props.calendar.maxDate
},
// 默认选中的日期,mode为multiple或range是必须为数组格式
defaultDate: {
type: [Array, String, Date, null],
default: uni.$u.props.calendar.defaultDate
},
// mode=multiple时,最多可选多少个日期
maxCount: {
type: [String, Number],
default: uni.$u.props.calendar.maxCount
},
// 日期行高
rowHeight: {
type: [String, Number],
default: uni.$u.props.calendar.rowHeight
},
// 日期格式化函数
formatter: {
type: [Function, null],
default: uni.$u.props.calendar.formatter
},
// 是否显示农历
showLunar: {
type: Boolean,
default: uni.$u.props.calendar.showLunar
},
// 是否显示月份背景色
showMark: {
type: Boolean,
default: uni.$u.props.calendar.showMark
},
// 确定按钮的文字
confirmText: {
type: String,
default: uni.$u.props.calendar.confirmText
},
// 确认按钮处于禁用状态时的文字
confirmDisabledText: {
type: String,
default: uni.$u.props.calendar.confirmDisabledText
},
// 是否显示日历弹窗
show: {
type: Boolean,
default: uni.$u.props.calendar.show
},
// 是否允许点击遮罩关闭日历
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.calendar.closeOnClickOverlay
},
// 是否为只读状态,只读状态下禁止选择日期
readonly: {
type: Boolean,
default: uni.$u.props.calendar.readonly
},
// 是否展示确认按钮
showConfirm: {
type: Boolean,
default: uni.$u.props.calendar.showConfirm
},
// 日期区间最多可选天数,默认无限制,mode = range时有效
maxRange: {
type: [Number, String],
default: uni.$u.props.calendar.maxRange
},
// 范围选择超过最多可选天数时的提示文案,mode = range时有效
rangePrompt: {
type: String,
default: uni.$u.props.calendar.rangePrompt
},
// 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
showRangePrompt: {
type: Boolean,
default: uni.$u.props.calendar.showRangePrompt
},
// 是否允许日期范围的起止时间为同一天,mode = range时有效
allowSameDay: {
type: Boolean,
default: uni.$u.props.calendar.allowSameDay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.calendar.round
},
// 最多展示月份数量
monthNum: {
type: [Number, String],
default: 3
}
}
}
export default {
methods: {
// 设置月份数据
setMonth() {
// 月初是周几
const day = dayjs(this.date).date(1).day()
const start = day == 0 ? 6 : day - 1
// 本月天数
const days = dayjs(this.date).endOf('month').format('D')
// 上个月天数
const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
// 日期数据
const arr = []
// 清空表格
this.month = []
// 添加上月数据
arr.push(
...new Array(start).fill(1).map((e, i) => {
const day = prevDays - start + i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 添加本月数据
arr.push(
...new Array(days - 0).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
date: dayjs(this.date).date(day).format('YYYY-MM-DD')
}
})
)
// 添加下个月
arr.push(
...new Array(42 - days - start).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 分割数组
for (let n = 0; n < arr.length; n += 7) {
this.month.push(
arr.slice(n, n + 7).map((e, i) => {
e.index = i + n
// 自定义信息
const custom = this.customList.find((c) => c.date == e.date)
// 农历
if (this.lunar) {
const {
IDayCn,
IMonthCn
} = this.getLunar(e.date)
e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
}
return {
...e,
...custom
}
})
)
}
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论