提交 5dcb1631 作者: ZhangLingKun

修复:正式服发布

上级 2aeb0f92
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/
\ No newline at end of file
# 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
pnpm-lock.yaml*
yarn-lock.yaml*
package-lock.yaml*
package-lock.json*
#yarn.lock*
# 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>
FROM node:alpine as builder
ARG PROFILES_ACTIVE
ENV PROFILES_ACTIVE=$PROFILES_ACTIVE
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
else echo "Lockfile not found." && exit 1; \
fi
COPY . .
RUN \
if [ "${PROFILES_ACTIVE}" = "development" ]; then echo "env PROFILES_ACTIVE=development. exec yarn run build:h5:dev" && yarn run build:h5:dev; \
else echo "env PROFILES_ACTIVE !=development. exec yarn run build:h5" && yarn run build:h5; \
fi
# RUN yarn run build:h5
# nginx
FROM nginx:alpine
FROM nginx:alpine as production
VOLUME ["/var/log/nginx/"]
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
# Set working directory to nginx asset directory
WORKDIR /var/www/html/h5/
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY static/ static/
COPY index.html index.html
COPY nginx.conf /etc/nginx/nginx.conf
WORKDIR /var/www/html/h5/
COPY --from=builder /app/dist/build/h5/ ./
WORKDIR /var/www/html/wechat
COPY ItnIxOQr0x.txt ItnIxOQr0x.txt
#
EXPOSE 80
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
\ No newline at end of file
ENTRYPOINT ["nginx", "-g", "daemon off;"]
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://iuav.mmcuav.cn'
// 正式服
// const baseURL = "https://csfapi.mmcuav.cn/"
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://www.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.83fe04ae.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
......@@ -4,7 +4,7 @@ metadata:
name: h5-deployment
namespace: default
spec:
minReadySeconds: 250
minReadySeconds: 5
revisionHistoryLimit: 2
replicas: 1
selector:
......@@ -18,9 +18,16 @@ spec:
containers:
- name: h5
image: REGISTRY/NAMESPACE/IMAGE:TAG
volumeMounts:
- name: log-of-nginx
mountPath: /var/log/nginx
resources:
limits:
memory: 256Mi
cpu: 100m
ports:
- containerPort: 80
\ No newline at end of file
- containerPort: 80
volumes:
- name: log-of-nginx
hostPath:
path: /var/log/nginx
......@@ -3,9 +3,9 @@ kind: Deployment
metadata:
name: h5-deployment
spec:
replicas: 2
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
maxUnavailable: 0
......@@ -13,4 +13,4 @@ patches:
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly-dev/h5
newTag: 67fa6ff2a43ef393bda2b6acdde157af799c55ac
newTag: 8e56771ed5b17a545929c21f73e6d777b7ea0dc9
......@@ -3,9 +3,9 @@ kind: Deployment
metadata:
name: h5-deployment
spec:
replicas: 2
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
maxUnavailable: 0
......@@ -9,8 +9,8 @@ commonLabels:
commonAnnotations:
note: This is prod!
patches:
- path: ./increase_replicas.yaml
- path: ./increase_replicas.yaml
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly/h5
newTag: cad821b35a85bac3936745f2c12396327a2ddedf
newTag: ca5b5fb500aed10456aa5f6578a27c31557c711b
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": "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:dev": "uni build --mode development",
"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>
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" : "map-h5",
"appid" : "__UNI__E0F71DB",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"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
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* 模块配置 */
"modules" : {},
"modules": {},
/* 应用发布信息 */
"distribute" : {
"distribute": {
/* android打包配置 */
"android" : {
"permissions" : [
"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\"/>",
......@@ -41,43 +41,38 @@
]
},
/* ios打包配置 */
"ios" : {},
"ios": {},
/* SDK配置 */
"sdkConfigs" : {}
"sdkConfigs": {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
"quickapp": {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
"mp-weixin": {
"appid": "wx435a39e391de2067",
"setting": {
"urlCheck": false
},
"usingComponents" : true
"usingComponents": true
},
"mp-alipay" : {
"usingComponents" : true
"mp-alipay": {
"usingComponents": true
},
"mp-baidu" : {
"usingComponents" : true
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao" : {
"usingComponents" : true
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics" : {
"enable" : false
"uniStatistics": {
"enable": false
},
"vueVersion" : "2",
"h5" : {
"template" : "",
"router" : {
"base" : "/network/",
"mode" : "hash"
},
"title" : "MMC-云享飞",
"devServer" : {
"https" : true
}
}
"vueVersion": "3",
"h5" : {
"router" : {
"mode" : "hash",
"base" : "/network/"
}
}
}
{
"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: fixed;
top: calc(100vh - 704rpx + 110rpx);
left: 0;
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: fixed;
top: calc(100vh - 704rpx);
left: 0;
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.
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.
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.
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.
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>
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论