commit message
|
@ -0,0 +1,10 @@
|
|||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
#Intellij idea
|
||||
.idea/
|
||||
/idea/
|
||||
.vscode/
|
||||
/unpackage/
|
||||
.hbuilderx/launch.json
|
|
@ -0,0 +1,11 @@
|
|||
{ // 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": [{
|
||||
"type": "uniCloud",
|
||||
"default": {
|
||||
"launchtype": "remote"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
|
||||
<script>
|
||||
/**
|
||||
* vuex管理登录状态,具体可以参考官方登录模板示例
|
||||
*/
|
||||
import { mapMutations } from "vuex";
|
||||
import APPUpdate from "@/plugins/APPUpdate";
|
||||
// 悬浮球
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
...mapMutations(["login"]),
|
||||
},
|
||||
onLaunch: function () {
|
||||
// #ifdef APP-PLUS
|
||||
this.checkArguments(); // 检测启动参数
|
||||
// 重点是以下: 一定要监听后台恢复 !一定要
|
||||
plus.globalEvent.addEventListener("newintent", (e) => {
|
||||
this.checkArguments(); // 检测启动参数
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 开屏广告
|
||||
launch() {
|
||||
try {
|
||||
// 获取本地存储中launchFlag标识 开屏广告
|
||||
const value = uni.getStorageSync("launchFlag");
|
||||
if (!value) {
|
||||
this.$u.route("/pages/index/agreement");
|
||||
} else {
|
||||
//app启动时打开启动广告页
|
||||
var w = plus.webview.open(
|
||||
"/hybrid/html/advertise/advertise.html",
|
||||
"本地地址",
|
||||
{
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
zindex: 999,
|
||||
},
|
||||
"fade-in",
|
||||
500
|
||||
);
|
||||
//设置定时器,4s后关闭启动广告页
|
||||
setTimeout(function () {
|
||||
plus.webview.close(w);
|
||||
APPUpdate();
|
||||
}, 3000);
|
||||
}
|
||||
} catch (e) {
|
||||
// error
|
||||
uni.setStorage({
|
||||
key: "launchFlag",
|
||||
data: true,
|
||||
success: function () {
|
||||
console.log("error时存储launchFlag");
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// 获取h5跳转app的链接并跳转
|
||||
checkArguments() {
|
||||
// #ifdef APP-PLUS
|
||||
setTimeout(() => {
|
||||
const args = plus.runtime.arguments;
|
||||
if (args) {
|
||||
const argsStr = decodeURIComponent(args);
|
||||
console.log(argsStr);
|
||||
const path = argsStr.split("//")[1];
|
||||
if (path.indexOf("tabbar")) {
|
||||
uni.switchTab({
|
||||
url: `/${path}`,
|
||||
});
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: `/${path}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "uview-ui/index.scss";
|
||||
@import "./static/font/iconfont/iconfont.css";
|
||||
// -------适配底部安全区 苹果x系列刘海屏
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
.mp-iphonex-bottom {
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
box-sizing: content-box;
|
||||
height: auto !important;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
// #endif
|
||||
|
||||
body {
|
||||
background-color: $bg-color;
|
||||
}
|
||||
/************************ */
|
||||
.w200 {
|
||||
width: 200rpx !important;
|
||||
}
|
||||
.flex1 {
|
||||
flex: 1; //必须父级设置flex
|
||||
}
|
||||
</style>
|
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="ipad12_9" orientation="portrait" layout="fullscreen" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment version="4096" identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" tag="1" contentMode="scaleAspectFit" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1024" height="1366"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LILI商城 享你所购" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="9" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aap-f2-ctd">
|
||||
<rect key="frame" x="417.5" y="1291" width="189" height="65"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="189" id="IEH-DH-MSh"/>
|
||||
<constraint firstAttribute="height" constant="65" id="Owl-Zu-11N"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="65" id="pa9-7L-Yn2"/>
|
||||
<constraint firstAttribute="width" constant="189" id="xdI-XG-GYE"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="23"/>
|
||||
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="highlightedColor" systemColor="secondarySystemGroupedBackgroundColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="1.png" highlightedImage="1.png" translatesAutoresizingMaskIntoConstraints="NO" id="tDb-oz-ZqQ" userLabel="logo.png">
|
||||
<rect key="frame" x="437" y="1126" width="150" height="150"/>
|
||||
<color key="tintColor" systemColor="systemGray6Color"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="150" id="2Pc-RJ-7fL"/>
|
||||
<constraint firstAttribute="width" secondItem="tDb-oz-ZqQ" secondAttribute="height" multiplier="1:1" id="K9U-1h-yR6"/>
|
||||
<constraint firstAttribute="height" constant="150" id="Ocb-HD-CX3"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="IW3-oA-Ytg"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="IW3-oA-Ytg" firstAttribute="bottom" secondItem="aap-f2-ctd" secondAttribute="bottom" constant="10" id="AaD-Ch-YkJ"/>
|
||||
<constraint firstItem="aap-f2-ctd" firstAttribute="top" secondItem="tDb-oz-ZqQ" secondAttribute="bottom" constant="15" id="TSj-WP-wlO"/>
|
||||
<constraint firstItem="tDb-oz-ZqQ" firstAttribute="centerX" secondItem="IW3-oA-Ytg" secondAttribute="centerX" id="XFM-cQ-LjU"/>
|
||||
<constraint firstItem="tDb-oz-ZqQ" firstAttribute="centerX" secondItem="aap-f2-ctd" secondAttribute="centerX" id="gTF-LF-cb1"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</variation>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="50.390625" y="373.35285505124449"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="1.png" width="86" height="57"/>
|
||||
<systemColor name="secondarySystemGroupedBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemGray6Color">
|
||||
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1 @@
|
|||
qSyvBPhDsPdxvOhC
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* 收货地址相关API
|
||||
*/
|
||||
|
||||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
import api from "@/config/api.js";
|
||||
|
||||
/**
|
||||
* 获取收货地址列表
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getAddressList(pageNumber, pageSize) {
|
||||
return http.request({
|
||||
url: "/memberAddress",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params: { pageNumber, pageSize },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取物流公司
|
||||
*/
|
||||
export function getLogistics() {
|
||||
return http.request({
|
||||
url: "/logistics",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params: { pageNumber: 1, pageSize: 200, disabled: "OPEN" },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过cityCode获取地区代码
|
||||
*/
|
||||
export function getAddressCode(cityCode, townName) {
|
||||
return http.request({
|
||||
url: api.common + "/region/region",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params: { cityCode, townName },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加收货地址
|
||||
* @param params 地址参数
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function addAddress(data) {
|
||||
return http.request({
|
||||
url: "/memberAddress",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑地址
|
||||
* @param id 地址ID
|
||||
* @param params 地址参数
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function editAddress(params) {
|
||||
return http.request({
|
||||
url: `/memberAddress`,
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除收货地址
|
||||
* @param id
|
||||
*/
|
||||
export function deleteAddress(id) {
|
||||
return http.request({
|
||||
url: `/memberAddress/delById/${id}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据ID获取会员收件地址
|
||||
* @param id
|
||||
*/
|
||||
export function getAddressDetail(id) {
|
||||
return http.request({
|
||||
url: `/memberAddress/get/${id}`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function getAddressDefault() {
|
||||
return http.request({
|
||||
url: `/memberAddress/get/default`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/**
|
||||
* 申请售后相关API
|
||||
*/
|
||||
|
||||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取售后列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getAfterSale(params) {
|
||||
return http.request({
|
||||
url: "after-sales/refunds",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/******************* 以下为新方法 ***********************/
|
||||
/**
|
||||
* 申请取消订单
|
||||
* @param params
|
||||
*/
|
||||
export function applyCancelOrder(params) {
|
||||
return http.request({
|
||||
url: "after-sales/apply/cancel/order",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商家售后收件地址
|
||||
*/
|
||||
export function getstoreAfterSaleAddress(sn) {
|
||||
return http.request({
|
||||
url: `/afterSale/getStoreAfterSaleAddress/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取售后服务记录相关数据
|
||||
* @param params 参数
|
||||
*/
|
||||
export function getAfterSaleList(params) {
|
||||
return http.request({
|
||||
url: `/afterSale/page`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看售后服务详情
|
||||
* @param sn 售后服务单编号
|
||||
*/
|
||||
export function getServiceDetail(sn) {
|
||||
return http.request({
|
||||
url: `/afterSale/get/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加投诉
|
||||
*/
|
||||
export function addComplain(params) {
|
||||
return http.request({
|
||||
url: `/complain`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消投诉
|
||||
*/
|
||||
export function clearComplain(id, params) {
|
||||
return http.request({
|
||||
url: `/complain/status/${id}`,
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消投诉
|
||||
*/
|
||||
export function getAfterSaleLog(sn) {
|
||||
return http.request({
|
||||
url: `/afterSale/get/getAfterSaleLog/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 投诉列表
|
||||
*/
|
||||
export function getComplain(params) {
|
||||
return http.request({
|
||||
url: `/complain`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取申请原因
|
||||
*/
|
||||
export function getAfterSaleReason(serviceType) {
|
||||
return http.request({
|
||||
url: `/afterSale/get/afterSaleReason/${serviceType}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取取消原因
|
||||
*/
|
||||
export function getClearReason() {
|
||||
return http.request({
|
||||
url: `/afterSale/get/afterSaleReason/CANCEL`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取投诉原因
|
||||
*/
|
||||
export function getComplainReason() {
|
||||
return http.request({
|
||||
url: `/afterSale/get/afterSaleReason/COMPLAIN`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取投诉详情
|
||||
*/
|
||||
export function getComplainDetail(id) {
|
||||
return http.request({
|
||||
url: `/complain/${id}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取申请售后页面信息
|
||||
*/
|
||||
export function getAfterSaleInfo(sn) {
|
||||
return http.request({
|
||||
url: `/afterSale/applyAfterSaleInfo/${sn}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退货服务
|
||||
* @param params
|
||||
*/
|
||||
export function applyReturn(orderItemSn, params) {
|
||||
return http.request({
|
||||
url: `/afterSale/save/${orderItemSn}`,
|
||||
method: Method.POST,
|
||||
header: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充物流信息
|
||||
* @param afterSaleSn 售后服务单号
|
||||
* @param params 参数信息
|
||||
*/
|
||||
export function fillShipInfo(afterSaleSn, params) {
|
||||
return http.request({
|
||||
url: `/afterSale/delivery/${afterSaleSn}`,
|
||||
method: Method.POST,
|
||||
header: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: params,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 文章相关API
|
||||
*/
|
||||
|
||||
import {http,Method} from '@/utils/request.js';
|
||||
import api from '@/config/api.js';
|
||||
|
||||
/**
|
||||
* 获取某个分类的文章列表
|
||||
* @param category_type
|
||||
*/
|
||||
export function getArticleCategory(category_type) {
|
||||
return http.request({
|
||||
url: `${api.base}/pages/article-categories`,
|
||||
method: Method.GET,
|
||||
params: {category_type},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章详情
|
||||
* @param type
|
||||
*/
|
||||
export function getArticleDetail(type) {
|
||||
return http.request({
|
||||
url: `/article/type/${type}`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* 公共API
|
||||
*/
|
||||
import storage from "@/utils/storage.js"
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
import api from '@/config/api.js';
|
||||
|
||||
/**
|
||||
* 获取图片验证码URL
|
||||
* @param type
|
||||
* @param uuid
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getValidateCodeUrl(type, uuid) {
|
||||
if (!type) {
|
||||
return '';
|
||||
}
|
||||
if (!uuid) {
|
||||
uuid = storage.getUuid()
|
||||
}
|
||||
return `${api.base}/captchas/${uuid}/${type}?r=${new Date().getTime()}`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取地区数据
|
||||
* @param id
|
||||
*/
|
||||
export function getRegionsById(id = 0) {
|
||||
return http.request({
|
||||
url: `${api.common}/region/item/${id}`,
|
||||
method: Method.GET,
|
||||
message: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @type {string}
|
||||
*/
|
||||
export const upload =api.common+'/upload/file';
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* 信任登录相关API
|
||||
*/
|
||||
|
||||
import {
|
||||
http,
|
||||
Method
|
||||
} from '@/utils/request.js';
|
||||
const request = http.request;
|
||||
|
||||
|
||||
/**
|
||||
* web 第三方登录
|
||||
* @param {Object} code
|
||||
*/
|
||||
export function webConnect(code) {
|
||||
return http.request({
|
||||
url: `connect/login/web/${code}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
header: {
|
||||
"clientType": "H5"
|
||||
}
|
||||
});
|
||||
}
|
||||
export function openIdLogin(params, clientType) {
|
||||
return http.request({
|
||||
url: `connect/app/login`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
data: params,
|
||||
header: {
|
||||
"clientType": clientType
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方登录成功 回调接口
|
||||
*/
|
||||
export function loginCallback(state) {
|
||||
return http.request({
|
||||
url: `connect/result?state=${state}`,
|
||||
method: Method.GET,
|
||||
needToken: false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 小程序自动登录
|
||||
* @param params
|
||||
*/
|
||||
export function mpAutoLogin(params) {
|
||||
return http.request({
|
||||
url: 'mini-program/auto-login',
|
||||
method: Method.GET,
|
||||
params
|
||||
});
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
* 商品相关API
|
||||
*/
|
||||
|
||||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 从ES中获取相关商品品牌名称,分类名称及属性
|
||||
*/
|
||||
export function getGoodsMessage(goodsId) {
|
||||
return http.request({
|
||||
url: `/goods/get/${goodsId}`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ES中获取相关商品品牌名称,分类名称及属性
|
||||
*/
|
||||
export function getGoodsRelated(params) {
|
||||
return http.request({
|
||||
url: `/goods/es/related`,
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品详情
|
||||
* @param skuId 商品ID
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getGoods(skuId, goodsId, distributionId) {
|
||||
return http.request({
|
||||
url: `/goods/sku/${goodsId}/${skuId}${distributionId ? '?distributionId='+distributionId : ''}`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getGoodsList(params) {
|
||||
return http.request({
|
||||
url: "/goods/es",
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上新商品列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getGoodsListUplog(params) {
|
||||
return http.request({
|
||||
url: "goods/search/uplog",
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取标签商品
|
||||
* @param storeId 卖家id
|
||||
* @param mark 标签 hot:热卖 new:新品 recommend:推荐
|
||||
* @param num 获取个数
|
||||
*/
|
||||
export function getTagGoods(storeId, mark = "hot", num = 5) {
|
||||
return http.request({
|
||||
url: `goods/tags/${mark}/goods`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
params: {
|
||||
storeId,
|
||||
mark,
|
||||
num,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取标签商品
|
||||
*/
|
||||
export function getPlateformTagGoods(tag_id) {
|
||||
return http.request({
|
||||
url: `goods/tags/byid/${tag_id}`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页商品分类 左侧列表
|
||||
* @param parent_id
|
||||
*/
|
||||
export function getCategoryList(id) {
|
||||
return http.request({
|
||||
url: `/category/get/${id}`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品分类
|
||||
* @param parent_id
|
||||
*/
|
||||
export function getCategory(parent_id = 0) {
|
||||
return http.request({
|
||||
url: `goods/categories/${parent_id}/children`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前会员的分销商信息 可根据分销商信息查询待提现金额以及冻结金额等信息
|
||||
*/
|
||||
export function distribution() {
|
||||
return http.request({
|
||||
url: `/distribution`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请分销商
|
||||
*/
|
||||
export function applyDistribution(params) {
|
||||
return http.request({
|
||||
url: `/distribution`,
|
||||
method: Method.POST,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销商提现
|
||||
*/
|
||||
export function cash(params) {
|
||||
return http.request({
|
||||
url: `/distribution/cash`,
|
||||
method: Method.POST,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销商提现历史
|
||||
*/
|
||||
export function cashLog() {
|
||||
return http.request({
|
||||
url: `/distribution/cash`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销商分页订单列表
|
||||
*/
|
||||
export function distributionOrderList() {
|
||||
return http.request({
|
||||
url: `/distribution/distributionOrder`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销商商品列表
|
||||
*/
|
||||
export function distributionGoods(params) {
|
||||
return http.request({
|
||||
url: `/distributionGoods`,
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 选择分销商品 分销商品id
|
||||
*/
|
||||
export function checkedDistributionGoods(id) {
|
||||
return http.request({
|
||||
url: `/distributionGoods/checked/${id}`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 小程序码
|
||||
*/
|
||||
export function getMpCode(params){
|
||||
return http.request({
|
||||
url:`/mini-program/mp/unlimited`,
|
||||
method:Method.GET,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据shortlink 获取页面参数
|
||||
*/
|
||||
export function getMpScene(id){
|
||||
return http.request({
|
||||
url:`/mini-program/mp/unlimited/scene?id=${id}`,
|
||||
method:Method.GET,
|
||||
|
||||
})
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取广告图
|
||||
*/
|
||||
export function getAdvertisement() {
|
||||
return http.request({
|
||||
url: "/advertisement",
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取首页商品分类
|
||||
* @param parent_id
|
||||
*/
|
||||
export function getCategory(parent_id = 0) {
|
||||
return http.request({
|
||||
url: `goods/categories/${parent_id}/children`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取热门关键词
|
||||
* @param num
|
||||
*/
|
||||
export function getHotKeywords(start = 0, end = 10) {
|
||||
return http.request({
|
||||
url: "/goods/hot-words",
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
params: { start, end },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取楼层数据
|
||||
* @param client_type
|
||||
* @param page_type
|
||||
*/
|
||||
export function getFloorData() {
|
||||
return http.request({
|
||||
url: `/pageData/getIndex?clientType=H5`,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取获取首页分类数据
|
||||
*/
|
||||
export function getCategoryIndexData(parentId = 0) {
|
||||
return http.request({
|
||||
url: `/category/get/${parentId}`,
|
||||
method: "get",
|
||||
});
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import {
|
||||
http
|
||||
} from "@/utils/request.js";
|
||||
|
||||
|
||||
import api from '@/config/api.js'
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通过短信重置密码
|
||||
* @param mobile
|
||||
*/
|
||||
export function resetByMobile(params) {
|
||||
return http.request({
|
||||
url: `/members/resetByMobile`,
|
||||
method: "POST",
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
* @param mobile
|
||||
*/
|
||||
export function sendMobile(mobile) {
|
||||
return http.request({
|
||||
url: `${api.common}/sms/LOGIN/${mobile}`,
|
||||
method: "GET",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信登录
|
||||
* @param mobile
|
||||
* @param smsCode
|
||||
*/
|
||||
export function smsLogin(params, clientType) {
|
||||
return http.request({
|
||||
url: `/members/smsLogin`,
|
||||
method: "POST",
|
||||
data: params,
|
||||
header: {
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
"clientType": clientType
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param newPassword
|
||||
* @param password
|
||||
*/
|
||||
|
||||
export function modifyPass(params) {
|
||||
return http.request({
|
||||
url: `/members/modifyPass`,
|
||||
method: "PUT",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*/
|
||||
export function refreshTokenFn(refresh_token) {
|
||||
console.log(refresh_token)
|
||||
return http.request({
|
||||
url: `/members/refresh/${refresh_token}`,
|
||||
method: "GET",
|
||||
});
|
||||
}
|
|
@ -0,0 +1,438 @@
|
|||
import storage from "@/utils/storage"
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 意见反馈
|
||||
*/
|
||||
export function feedBack(params) {
|
||||
return http.request({
|
||||
url: '/feedback',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 分页获取预存款充值记录
|
||||
* @param params
|
||||
*/
|
||||
export function getUserRecharge(params) {
|
||||
return http.request({
|
||||
url: "/member/recharge",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取预存款充值记录
|
||||
* @param params
|
||||
*/
|
||||
export function getWalletLog(params) {
|
||||
return http.request({
|
||||
url: "/wallet/log",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取优惠券列表
|
||||
* @param params
|
||||
*/
|
||||
export function getCoupons(params) {
|
||||
return http.request({
|
||||
url: '/promotion/coupon/getCoupons',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取优惠券
|
||||
* @param couponId
|
||||
*/
|
||||
export function receiveCoupons(couponId) {
|
||||
return http.request({
|
||||
url: `/promotion/coupon/receive/${couponId}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会员积分
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export function getPoints() {
|
||||
return http.request({
|
||||
url: 'members/points/current',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分明细数据
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getPointsData(params) {
|
||||
return http.request({
|
||||
url: 'member/memberPointsHistory/getByPage',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分明细数据 按月分组
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getPointsDataDetail(params) {
|
||||
return http.request({
|
||||
url: 'members/points/total',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取我的评论列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getComments(params) {
|
||||
return http.request({
|
||||
url: '/memberEvaluation',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会员的浏览数量是多少
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getFootprintNum(params) {
|
||||
return http.request({
|
||||
url: '/footprint/getFootprintNum',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 订单评论
|
||||
* @param params
|
||||
*/
|
||||
export function commentsMemberOrder(params) {
|
||||
return http.request({
|
||||
url: '/memberEvaluation',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加评论
|
||||
* @param params
|
||||
*/
|
||||
export function AppendCommentsOrder(params) {
|
||||
return http.request({
|
||||
url: 'members/comments/additional',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 商品咨询
|
||||
* @param goods_id
|
||||
* @param ask_content
|
||||
*/
|
||||
export function consultating(goods_id, ask_content,anonymous) {
|
||||
return http.request({
|
||||
url: 'members/asks',
|
||||
method: Method.POST,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
needToken: true,
|
||||
data: {
|
||||
goods_id,
|
||||
ask_content,
|
||||
anonymous
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品收藏
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getGoodsCollection(params,type) {
|
||||
return http.request({
|
||||
url: `/member/collection/${type}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
message: false,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 收藏商品
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function collectionGoods(id,type) {
|
||||
return http.request({
|
||||
url: `/member/collection/add/${type}/${id}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 删除商品收藏
|
||||
* @param ids 收藏ID【集合或单个商品ID】
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function deleteGoodsCollection(ids) {
|
||||
if (Array.isArray(ids)) {
|
||||
ids = ids.join(',');
|
||||
}
|
||||
return http.request({
|
||||
url: `/member/collection/delete/GOODS/${ids}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品是否被收藏
|
||||
* @param good_id
|
||||
*/
|
||||
export function getGoodsIsCollect(good_id,type) {
|
||||
return http.request({
|
||||
url: `/member/collection/isCollection/${type}/${good_id}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 收藏店铺
|
||||
* @param store_id 店铺ID
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function collectionStore(store_id) {
|
||||
return http.request({
|
||||
url: 'members/collection/store',
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
method: Method.POST,
|
||||
data: {store_id},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除店铺收藏
|
||||
* @param store_id
|
||||
*/
|
||||
export function deleteStoreCollection(store_id) {
|
||||
return http.request({
|
||||
url: `members/collection/store/${store_id}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户信息
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getUserInfo() {
|
||||
return http.request({
|
||||
url: '/members',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的预存款
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getUserWallet() {
|
||||
return http.request({
|
||||
url: '/members/wallet',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存用户信息
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function saveUserInfo(params) {
|
||||
return http.request({
|
||||
url: '/members/editOwn',
|
||||
method: Method.PUT,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
needToken: true,
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加发票
|
||||
* @param params
|
||||
*/
|
||||
export function addReceipt(params) {
|
||||
return http.request({
|
||||
url: '/trade/receipt',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取商品评论列表
|
||||
* @param goodsId
|
||||
* @param params
|
||||
*/
|
||||
export function getGoodsComments(goodsId, params) {
|
||||
return http.request({
|
||||
url: `/memberEvaluation/${goodsId}/goodsEvaluation`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品评论数量统计
|
||||
* @param goodsId
|
||||
*/
|
||||
export function getGoodsCommentsCount(goodsId) {
|
||||
return http.request({
|
||||
url: `/memberEvaluation/${goodsId}/evaluationNumber`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取未读消息数量信息
|
||||
*/
|
||||
export function getNoReadMessageNum() {
|
||||
return http.request({
|
||||
url: `members/member-nocice-logs/number`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的足迹列表
|
||||
* @param pageNumber pageSize
|
||||
*
|
||||
*/
|
||||
export function myTrackList(params) {
|
||||
return http.request({
|
||||
url: `/footprint`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id删除会员足迹
|
||||
* @param id
|
||||
*/
|
||||
export function deleteHistoryListId(ids) {
|
||||
return http.request({
|
||||
url: `/footprint/delByIds/${ids}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会员优惠券列表
|
||||
* @param
|
||||
*/
|
||||
export function getMemberCoupons(data) {
|
||||
return http.request({
|
||||
url: `/promotion/coupon/getCoupons`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params:data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会员可使用的优惠券数量
|
||||
*
|
||||
*/
|
||||
export function getCouponsNum() {
|
||||
return http.request({
|
||||
url: `/promotion/coupon/getCouponsNum`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员积分VO
|
||||
* @param
|
||||
*/
|
||||
export function getMemberPointSum() {
|
||||
return http.request({
|
||||
url: `member/memberPointsHistory/getMemberPointsHistoryVO`,
|
||||
method: Method.GET
|
||||
})
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* 站内消息相关API
|
||||
*/
|
||||
|
||||
import {http,Method} from '@/utils/request.js';
|
||||
const request = http.request
|
||||
|
||||
|
||||
/**
|
||||
* 获取微信消息订阅
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getWeChatMpMessage() {
|
||||
return http.request({
|
||||
url: 'mini-program/subscribeMessage',
|
||||
method: Method.GET
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消息列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getMessages(params) {
|
||||
params = params || {};
|
||||
params.pageSize = params.pageSize || 5;
|
||||
return http.request({
|
||||
url: 'members/member-nocice-logs',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 标记消息为已读
|
||||
* @param ids
|
||||
*/
|
||||
export function messageMarkAsRead(ids) {
|
||||
return http.request({
|
||||
url: `members/member-nocice-logs/${ids}/read`,
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取物流消息列表
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getLogisticsMessages(params) {
|
||||
params = params || {};
|
||||
params.pageSize = params.pageSize || 5;
|
||||
return http.request({
|
||||
url: 'trade/logistics/message',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取版本更新信息
|
||||
* @param params
|
||||
* @returns {AxiosPromise}
|
||||
*/
|
||||
export function getAppVersionList(params) {
|
||||
params = params || {};
|
||||
params.pageSize = params.pageSize || 5;
|
||||
return http.request({
|
||||
url: 'members/app/version',
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* 订单相关API
|
||||
*/
|
||||
|
||||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 选择发票
|
||||
* @param params
|
||||
*/
|
||||
export function getReceipt(params) {
|
||||
return http.request({
|
||||
url: "/trade/carts/select/receipt",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择发票
|
||||
* @param id
|
||||
*/
|
||||
export function getReceiptDetail(id) {
|
||||
return http.request({
|
||||
url: `/trade/receipt/${id}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择配送方式
|
||||
* @param params
|
||||
*/
|
||||
export function selectedShipMethod(params) {
|
||||
return http.request({
|
||||
url: "/trade/carts/shippingMethod",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表
|
||||
* @param params
|
||||
*/
|
||||
export function getOrderList(params) {
|
||||
return http.request({
|
||||
url: "/orders",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单详情
|
||||
* @param orderSn 订单编号
|
||||
*/
|
||||
export function getOrderDetail(orderSn) {
|
||||
return http.request({
|
||||
url: `/orders/${orderSn}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* @param orderSn 订单编号
|
||||
* @param reason 取消原因
|
||||
*/
|
||||
export function cancelOrder(orderSn, reason) {
|
||||
return http.request({
|
||||
url: `/orders/${orderSn}/cancel`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data: reason,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货
|
||||
* @param orderSn 订单编号
|
||||
*/
|
||||
export function confirmReceipt(orderSn) {
|
||||
return http.request({
|
||||
url: `/orders/${orderSn}/receiving`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前拼团订单的拼团分享信息
|
||||
* @param {*} parentOrderSn
|
||||
* @param {*} skuId
|
||||
*/
|
||||
export function getPinTuanShare(parentOrderSn,skuId) {
|
||||
return http.request({
|
||||
url: `promotion/pintuan/share`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params:{parentOrderSn,skuId}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Created by Andste on 2018/5/2.
|
||||
* 用户认证相关API
|
||||
*/
|
||||
import storage from '@/utils/storage.js';
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
import { md5 } from '@/utils/md5.js';
|
||||
|
||||
/**
|
||||
* 普通登录
|
||||
* @param username
|
||||
* @param password
|
||||
* @param captcha
|
||||
*/
|
||||
export function login(username, password, captcha) {
|
||||
return http.request({
|
||||
url: 'passport/login',
|
||||
method: Method.POST,
|
||||
params: {
|
||||
username,
|
||||
password: md5(password),
|
||||
captcha,
|
||||
uuid: storage.getUuid(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 验证账户信息
|
||||
* @param captcha
|
||||
* @param account
|
||||
*/
|
||||
export function validAccount(captcha, account) {
|
||||
return http.request({
|
||||
url: 'passport/find-pwd',
|
||||
method: Method.GET,
|
||||
params: {
|
||||
uuid: storage.getUuid(),
|
||||
captcha,
|
||||
account,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送找回密码短信
|
||||
* @param uuid
|
||||
* @param captcha
|
||||
*/
|
||||
export function sendFindPasswordSms(uuid,captcha) {
|
||||
return http.request({
|
||||
url: 'passport/find-pwd/send',
|
||||
method: Method.POST,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: {
|
||||
uuid:uuid,
|
||||
captcha,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验找回密码验证码
|
||||
* @param uuid
|
||||
* @param sms_code
|
||||
*/
|
||||
export function validFindPasswordSms(uuid, sms_code) {
|
||||
return http.request({
|
||||
url: 'passport/find-pwd/valid',
|
||||
method: Method.GET,
|
||||
params: {
|
||||
uuid,
|
||||
sms_code,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码【找回密码用】
|
||||
* @param password
|
||||
* @param uuid
|
||||
*/
|
||||
export function changePassword(password, uuid) {
|
||||
if (!uuid) {
|
||||
uuid = storage.getUuid();
|
||||
}
|
||||
return http.request({
|
||||
url: 'passport/find-pwd/update-password',
|
||||
method: Method.PUT,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: {
|
||||
uuid,
|
||||
password: md5(password),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 保存生物认证登录
|
||||
export function setBiolofy(params) {
|
||||
return http.request({
|
||||
url: `passport/login/save/biology`,
|
||||
method: 'POST',
|
||||
params
|
||||
})
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
|
||||
/**
|
||||
* 签到
|
||||
* @param params
|
||||
*/
|
||||
export function sign() {
|
||||
return http.request({
|
||||
url: '/members/sign',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 签到时间获取
|
||||
* @param params
|
||||
*/
|
||||
export function signTime(time) {
|
||||
return http.request({
|
||||
url: '/members/sign?time='+time,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 促销相关API
|
||||
*/
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前拼团活动的未成团的会员
|
||||
*/
|
||||
export function getPromotionGroupMember(pintuanId) {
|
||||
return http.request({
|
||||
url: `promotion/pintuan/${pintuanId}/members`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** 获取拼团列表 */
|
||||
export function getAssembleList(params) {
|
||||
return http.request({
|
||||
url: 'promotion/pintuan',
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取积分商城分类
|
||||
*/
|
||||
export function getPointsCategory() {
|
||||
return http.request({
|
||||
url: '/promotion/pointsGoods/category',
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分商城商品
|
||||
* @param params
|
||||
*/
|
||||
export function getPointsGoods(params) {
|
||||
return http.request({
|
||||
url: '/promotion/pointsGoods',
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取限时抢购时间线 当天限时抢购信息
|
||||
*/
|
||||
export function getSeckillTimeLine() {
|
||||
return http.request({
|
||||
url: 'promotion/seckill',
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取限时抢购商品 获取某个时刻的限时抢购商品信息
|
||||
* @param params
|
||||
*/
|
||||
export function getSeckillTimeGoods(timeline) {
|
||||
return http.request({
|
||||
url: `promotion/seckill/${timeline}`,
|
||||
method: Method.GET,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部优惠券
|
||||
* @param params
|
||||
*/
|
||||
export function getAllCoupons(params) {
|
||||
return http.request({
|
||||
url: '/promotion/coupon',
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* 安全相关API
|
||||
*/
|
||||
|
||||
import {http,Method} from '@/utils/request.js';
|
||||
import storage from "@/utils/storage.js"
|
||||
import { md5 } from '@/utils/md5.js'
|
||||
|
||||
/**
|
||||
* 发送绑定手机验证码
|
||||
* @param mobile
|
||||
* @param captcha
|
||||
*/
|
||||
export function sendBindMobileSms(mobile, captcha) {
|
||||
return http.request({
|
||||
url: `members/security/bind/send/${mobile}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: {
|
||||
uuid: storage.getUuid(),
|
||||
captcha,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定手机号
|
||||
* @param mobile
|
||||
* @param sms_code
|
||||
*/
|
||||
export function bindMobile(mobile, sms_code) {
|
||||
return http.request({
|
||||
url: `members/security/bind/${mobile}`,
|
||||
method: Method.PUT,
|
||||
needToken: true,
|
||||
data: {sms_code},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送手机验证码
|
||||
* 在修改手机号和更改密码时通用
|
||||
* @param captcha
|
||||
*/
|
||||
export function sendMobileSms(captcha) {
|
||||
return http.request({
|
||||
url: 'members/security/send',
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: {
|
||||
uuid: storage.getUuid(),
|
||||
captcha,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证更换手机号短信
|
||||
* @param sms_code
|
||||
*/
|
||||
export function validChangeMobileSms(sms_code) {
|
||||
return http.request({
|
||||
url: 'members/security/exchange-bind',
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params: {sms_code},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更换手机号
|
||||
* @param mobile
|
||||
* @param sms_code
|
||||
*/
|
||||
export function changeMobile(mobile, sms_code) {
|
||||
return http.request({
|
||||
url: `members/security/exchange-bind/${mobile}`,
|
||||
method: Method.PUT,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
needToken: true,
|
||||
data: {sms_code},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更改密码
|
||||
* @param captcha
|
||||
* @param password
|
||||
*/
|
||||
export function changePassword(captcha, password) {
|
||||
return http.request({
|
||||
url: 'members/security/password',
|
||||
method: Method.PUT,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
needToken: true,
|
||||
data: {
|
||||
uuid: storage.getUuid(),
|
||||
captcha,
|
||||
password: md5(password),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实名认证进度
|
||||
* @param email
|
||||
* @param email_code
|
||||
*/
|
||||
export function contractStep() {
|
||||
return http.request({
|
||||
url: `members/contract/step`,
|
||||
method: Method.GET,
|
||||
needToken: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 实名认证
|
||||
* @param email
|
||||
* @param email_code
|
||||
*/
|
||||
export function authentication(params) {
|
||||
return http.request({
|
||||
url: `members/contract/authentication`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header:{'content-type':"application/x-www-form-urlencoded"},
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 店铺相关API
|
||||
*/
|
||||
|
||||
import {http, Method} from '@/utils/request.js';
|
||||
|
||||
/**
|
||||
* 获取店铺列表
|
||||
* @param params
|
||||
*/
|
||||
export function getstoreList(params) {
|
||||
return http.request({
|
||||
url: '/store',
|
||||
method: Method.GET,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺基本信息
|
||||
* @param storeId
|
||||
*/
|
||||
export function getstoreBaseInfo(storeId) {
|
||||
return http.request({
|
||||
url: `/store/get/detail/${storeId}`,
|
||||
method: Method.GET,
|
||||
loading: false,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/**
|
||||
* 交♂易相关API
|
||||
*/
|
||||
|
||||
import { http, Method } from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取购物车列表
|
||||
* @param show_type 要显示的类型 all:全部 checked:已选中的
|
||||
*/
|
||||
export function getCarts() {
|
||||
return http.request({
|
||||
url: `/trade/carts/all`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取购物车总数
|
||||
* @param show_type 要显示的类型 all:全部 checked:已选中的
|
||||
*/
|
||||
export function getCartNum() {
|
||||
return http.request({
|
||||
url: `/trade/carts/count`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取购物车可用优惠券数量
|
||||
* @param way 购物车购买:CART/立即购买:BUY_NOW/拼团购买:PINTUAN / 积分购买:POINT
|
||||
*/
|
||||
export function getCartCouponNum(way) {
|
||||
return http.request({
|
||||
url: `/trade/carts/coupon/num?way=${way}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加货品到购物车
|
||||
* @param skuId 产品ID
|
||||
* @param num 产品的购买数量
|
||||
* @param cartType 购物车类型,默认加入购物车
|
||||
*/
|
||||
export function addToCart(data) {
|
||||
return http.request({
|
||||
url: "/trade/carts",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 更新购物车商品数量
|
||||
* @param skuId
|
||||
* @param num
|
||||
*/
|
||||
export function updateSkuNum(skuId, num = 1) {
|
||||
return http.request({
|
||||
url: `/trade/carts/sku/num/${skuId}`,
|
||||
method: Method.POST,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
needToken: true,
|
||||
data: { num },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新购物车货品选中状态
|
||||
* @param skuId
|
||||
* @param checked
|
||||
*/
|
||||
export function updateSkuChecked(skuId, checked) {
|
||||
return http.request({
|
||||
url: `/trade/carts/sku/checked/${skuId}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data: { checked },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除多个货品项
|
||||
* @param skuIds
|
||||
*/
|
||||
export function deleteSkuItem(skuIds) {
|
||||
return http.request({
|
||||
url: `/trade/carts/sku/remove?skuIds=${skuIds}`,
|
||||
method: Method.DELETE,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置全部货品为选中或不选中
|
||||
* @param checked
|
||||
*/
|
||||
export function checkAll(checked) {
|
||||
return http.request({
|
||||
url: "/trade/carts/sku/checked",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
params: { checked },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置店铺内全部货品选中状态
|
||||
* @param storeId
|
||||
* @param checked
|
||||
*/
|
||||
export function checkStore(storeId, checked) {
|
||||
return http.request({
|
||||
url: `/trade/carts/store/${storeId}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
data: { checked },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结算参数
|
||||
*/
|
||||
export function getCheckoutParams(way) {
|
||||
return http.request({
|
||||
url: "/trade/carts/checked?way=" + way,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置收货地址ID
|
||||
* @param addressId
|
||||
*/
|
||||
export function setAddressId(addressId,way) {
|
||||
return http.request({
|
||||
url: `/trade/carts/shippingAddress?shippingAddressId=${addressId}&way=${way}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建交易
|
||||
*/
|
||||
export function createTrade(params) {
|
||||
return http.request({
|
||||
url: "/trade/carts/create/trade",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
message: false,
|
||||
data:params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据交易编号或订单编号查询收银台数据
|
||||
* @param params
|
||||
*/
|
||||
export function getCashierData(params) {
|
||||
return http.request({
|
||||
url: "cashier/tradeDetail",
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发起支付
|
||||
* @param paymentMethod
|
||||
* @param paymentClient
|
||||
* @param params
|
||||
* @returns {*|*}
|
||||
*/
|
||||
export function initiatePay(paymentMethod, paymentClient, params) {
|
||||
return http.request({
|
||||
url: `cashier/pay/${paymentMethod}/${paymentClient}`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询物流
|
||||
* @param orderSn
|
||||
|
||||
*/
|
||||
export function getExpress(orderSn) {
|
||||
return http.request({
|
||||
url: `/orders/getTraces/${orderSn}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前会员的对于当前商品可使用的优惠券列表
|
||||
*/
|
||||
export function getMemberCanUse(data) {
|
||||
return http.request({
|
||||
url: `/promotion/coupon/canUse`,
|
||||
method: Method.GET,
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前会员的优惠券列表
|
||||
*/
|
||||
export function getMemberCouponList(data) {
|
||||
return http.request({
|
||||
url: `/promotion/coupon/getCoupons`,
|
||||
method: Method.GET,
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用优惠券
|
||||
|
||||
*/
|
||||
export function useCoupon(params) {
|
||||
return http.request({
|
||||
url: `/trade/carts/select/coupon`,
|
||||
method: Method.GET,
|
||||
needToken: true,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更换参与活动
|
||||
* @param params
|
||||
*/
|
||||
export function changeActivity(params) {
|
||||
return http.request({
|
||||
url: "trade/promotion",
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
data: params,
|
||||
|
||||
header: { "content-type": "application/x-www-form-urlencoded" },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据交易单号查询订单列表
|
||||
* @param trade_sn
|
||||
*/
|
||||
export function reBuy(sn) {
|
||||
return http.request({
|
||||
url: `trade/carts/rebuy/${sn}`,
|
||||
method: Method.POST,
|
||||
needToken: true,
|
||||
});
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<view class="default-page">
|
||||
<view class="default-wrap">
|
||||
|
||||
<text>{{title}}</text>
|
||||
<view v-if="isBtn" class="btn" @click="toHome">
|
||||
去逛逛
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
// 购物车 cart 消息 msg 订单 order 查询 search
|
||||
type: {
|
||||
type: String,
|
||||
default: 'search'
|
||||
},
|
||||
isBtn:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title:{
|
||||
type: String,
|
||||
default: '没有相关内容'
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
src:''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.src ='/static/default/default_'+ this.type + '.png';
|
||||
},
|
||||
methods: {
|
||||
toHome() {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/home'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.default-page{
|
||||
background: #FFFFFF;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
.default-wrap{
|
||||
position: absolute;
|
||||
top: calc(50vh - 320rpx);
|
||||
left: calc(50% - 120rpx);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
>image{
|
||||
width: 260rpx;
|
||||
height: 240rpx;
|
||||
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
text{
|
||||
font-size: 32rpx;
|
||||
color: #828385;
|
||||
}
|
||||
.btn{
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
border: 2rpx solid #3180F6;
|
||||
border-radius: 6rpx;
|
||||
text-align: center;
|
||||
line-height: 56rpx;
|
||||
margin-top: 32rpx;
|
||||
font-size: 24rpx;
|
||||
color: #3180F6;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<view>
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="wrapper" v-if="!weChat" @click="openApp()">
|
||||
<!-- 左侧图标 -->
|
||||
<image class="img" :src="logo"></image>
|
||||
<view class="open">
|
||||
打开{{config.name}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/config/config";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
config,
|
||||
weChat: false,
|
||||
logo: require("@/icon.png"),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef H5
|
||||
// 判断是否是微信浏览器
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
var isWeixin = ua.indexOf("micromessenger") != -1;
|
||||
if (isWeixin) {
|
||||
this.weChat = true;
|
||||
} else {
|
||||
this.weChat = false;
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
downloadApp() {
|
||||
setTimeout(function () {
|
||||
window.location.href = config.downloadLink;
|
||||
}, 2000);
|
||||
},
|
||||
/**
|
||||
* 打开app 仅在h5生效 使用ifream唤醒app
|
||||
*/
|
||||
openApp() {
|
||||
let src;
|
||||
if (location.href) {
|
||||
src = location.href.split("/pages")[1];
|
||||
}
|
||||
let t = `${config.schemeLink}pages${src}`;
|
||||
|
||||
try {
|
||||
var e = navigator.userAgent.toLowerCase(),
|
||||
n = e.match(/cpu iphone os (.*?) like mac os/);
|
||||
if (
|
||||
((n = null !== n ? n[1].replace(/_/g, ".") : 0), parseInt(n) >= 9)
|
||||
) {
|
||||
window.location.href = t;
|
||||
|
||||
this.downloadApp();
|
||||
} else {
|
||||
var r = document.createElement("iframe");
|
||||
(r.src = t), (r.style.display = "none"), document.body.appendChild(r);
|
||||
|
||||
this.downloadApp();
|
||||
}
|
||||
} catch (e) {
|
||||
window.location.href = t;
|
||||
this.downloadApp();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.img {
|
||||
margin: 0 4rpx;
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 50%;
|
||||
border: 5rpx solid #fff;
|
||||
}
|
||||
|
||||
.open {
|
||||
margin: 0 10rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.wrapper:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
.wrapper {
|
||||
transform: translateX(160rpx);
|
||||
transition: 0.35s;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
border-top-left-radius: 20px;
|
||||
border-bottom-left-radius: 20px;
|
||||
color: #fff;
|
||||
// width: 220rpx;
|
||||
background: $light-color;
|
||||
position: fixed;
|
||||
top: 25%;
|
||||
right: 0;
|
||||
height: 60rpx;
|
||||
z-index: 9;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
### 说明 https://ext.dcloud.net.cn/plugin?id=3237
|
|
@ -0,0 +1,212 @@
|
|||
<template>
|
||||
|
||||
<div class="index">
|
||||
<u-modal v-model="show" :show-title="false" :show-confirm-button="false" mask-close-able>
|
||||
<view class="slot-content">
|
||||
|
||||
<image @click="downLoad()" class="img" :src="imgUrl" />
|
||||
<div class="canvas-hide">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<canvas id="canvas" type="2d" style="width: 600px; height: 960px" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<canvas canvas-id="canvas" id="canvas" style="width: 600px; height: 960px" />
|
||||
<!-- #endif -->
|
||||
</div>
|
||||
</view>
|
||||
</u-modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DrawPoster from "@/js_sdk/u-draw-poster";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
imgUrl: "",
|
||||
width: "",
|
||||
height: "",
|
||||
show: false,
|
||||
dp: {},
|
||||
logo: require("@/pages/passport/static/logo-title.png"),
|
||||
}),
|
||||
|
||||
props: {
|
||||
/**
|
||||
* 封装组件
|
||||
*/
|
||||
res: {
|
||||
type: null,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
onUnload() {},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 解决微信小程序中图片模糊问题
|
||||
*/
|
||||
// #ifdef MP-WEIXIN
|
||||
st2: (size) => size * 2,
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
st2: (size) => size,
|
||||
// #endif
|
||||
|
||||
downLoad() {
|
||||
console.log(this.imgUrl);
|
||||
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: this.imgUrl,
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: "保存成功!",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
fail: function () {
|
||||
uni.showToast({
|
||||
title: "保存失败,请稍后重试!",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建canvas
|
||||
*/
|
||||
async init() {
|
||||
this.show = true;
|
||||
this.dp = await DrawPoster.build({
|
||||
selector: "canvas",
|
||||
componentThis: this,
|
||||
loading: true,
|
||||
debugging: true,
|
||||
});
|
||||
let dp = this.dp;
|
||||
// #ifdef MP-WEIXIN
|
||||
// 用于微信小程序中画布错乱问题
|
||||
dp.canvas.width = this.st2(600);
|
||||
dp.canvas.height = this.st2(960);
|
||||
// #endif
|
||||
this.draw(dp);
|
||||
},
|
||||
|
||||
async draw(dp) {
|
||||
const { width, height, background, title } = this.res.container;
|
||||
const { code, img, price } = this.res.bottom;
|
||||
|
||||
// /** 绘制背景 */
|
||||
await dp.draw((ctx) => {
|
||||
ctx.fillStyle = background;
|
||||
ctx.fillRoundRect(
|
||||
this.st2(0),
|
||||
this.st2(0),
|
||||
this.st2(width),
|
||||
this.st2(height),
|
||||
this.st2(12)
|
||||
);
|
||||
ctx.clip();
|
||||
});
|
||||
/** 绘制图片 */
|
||||
dp.draw(async (ctx) => {
|
||||
await Promise.all([
|
||||
// 绘制Logo
|
||||
ctx.drawImage(
|
||||
this.logo,
|
||||
this.st2(175),
|
||||
this.st2(0),
|
||||
this.st2(256),
|
||||
this.st2(144)
|
||||
),
|
||||
// 中间图片
|
||||
ctx.drawImage(
|
||||
img,
|
||||
this.st2(100),
|
||||
this.st2(150),
|
||||
this.st2(400),
|
||||
this.st2(400)
|
||||
),
|
||||
// 二维码
|
||||
ctx.drawImage(
|
||||
code,
|
||||
this.st2(39),
|
||||
this.st2(750),
|
||||
this.st2(150),
|
||||
this.st2(150)
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
/** 绘制中间文字*/
|
||||
await dp.draw((ctx) => {
|
||||
ctx.fillStyle = "#333";
|
||||
ctx.font = `bold ${this.st2(24)}px PingFang SC`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillWarpText({
|
||||
text: title,
|
||||
maxWidth: this.st2(500),
|
||||
x: this.st2(300),
|
||||
y: this.st2(600),
|
||||
layer: 1,
|
||||
});
|
||||
|
||||
ctx.fillStyle = "#ff3c2a";
|
||||
ctx.font = `${this.st2(38)}px PingFang SC`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(price, this.st2(300), this.st2(680));
|
||||
});
|
||||
|
||||
// /** 绘制底部文字 */
|
||||
await dp.draw((ctx) => {
|
||||
ctx.fillStyle = "#666";
|
||||
ctx.font = `${this.st2(24)}px PingFang SC`;
|
||||
ctx.fillText("长按图片,识别二维码", this.st2(200), this.st2(866));
|
||||
ctx.fillStyle = "#666";
|
||||
ctx.font = `${this.st2(24)}px PingFang SC`;
|
||||
ctx.fillText("查看商品详情", this.st2(200), this.st2(900));
|
||||
});
|
||||
|
||||
this.imgUrl = await dp.createImagePath();
|
||||
|
||||
// console.log(posterImgUrl)
|
||||
},
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page,
|
||||
.index {
|
||||
height: 100%;
|
||||
}
|
||||
.canvas-hide {
|
||||
/* 1 */
|
||||
position: fixed;
|
||||
right: 100vw;
|
||||
bottom: 100vh;
|
||||
/* 2 */
|
||||
z-index: -9999;
|
||||
/* 3 */
|
||||
opacity: 0;
|
||||
}
|
||||
.index {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
background: rgba($color: grey, $alpha: 0.2);
|
||||
}
|
||||
|
||||
image {
|
||||
display: block;
|
||||
}
|
||||
.img {
|
||||
width: 600rpx;
|
||||
height: 960rpx;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,365 @@
|
|||
<template>
|
||||
<view>
|
||||
<view
|
||||
class="mask"
|
||||
:class="{ maskShow: showPicker }"
|
||||
@click="hide"
|
||||
@click.stop.prevent
|
||||
@touchmove.stop.prevent
|
||||
catchtouchmove="true"
|
||||
></view>
|
||||
<view class="cpicker-content" :class="{ cpickerShow: showPicker }">
|
||||
<view
|
||||
class="city-head"
|
||||
@click.stop.prevent
|
||||
@touchmove.stop.prevent
|
||||
catchtouchmove="true"
|
||||
>
|
||||
<view class="city-head-title">{{ headTitle }}</view>
|
||||
<icon
|
||||
type="clear"
|
||||
v-if="rightIcon"
|
||||
class="rightIcon"
|
||||
size="20"
|
||||
color="#cccccc"
|
||||
@click="hide"
|
||||
></icon>
|
||||
</view>
|
||||
<scroll-view
|
||||
id="nav-bar"
|
||||
class="nav-bar"
|
||||
scroll-x="true"
|
||||
scroll-with-animation="true"
|
||||
:scroll-left="scrollLeft"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in tabbars"
|
||||
class="nav-item"
|
||||
:key="index"
|
||||
:id="'tab' + index"
|
||||
@click="changeTab(index)"
|
||||
:class="{ current: index === tabCurrentIndex }"
|
||||
><text class="nav-bar-title">{{ item.localName }}</text></view
|
||||
>
|
||||
</scroll-view>
|
||||
<view class="city_content">
|
||||
<scroll-view
|
||||
class="panel-scroll-box"
|
||||
:scroll-y="enableScroll"
|
||||
:cscrollTop="scrollTop"
|
||||
:current="tabCurrentIndex"
|
||||
:scroll-top="scrollTop"
|
||||
>
|
||||
<block
|
||||
v-for="(item, index) in tabbars[tabCurrentIndex].children"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
class="flex-row-c-c"
|
||||
@click="changCity(tabCurrentIndex, item)"
|
||||
>
|
||||
<text
|
||||
class="city-text"
|
||||
:class="{ color: tabbars[tabCurrentIndex].id == item.id }"
|
||||
>{{ item.name }}</text
|
||||
>
|
||||
<icon
|
||||
type="success_no_circle"
|
||||
v-if="tabbars[tabCurrentIndex].id == item.id"
|
||||
:id="'show' + tabCurrentIndex"
|
||||
class="ischeck"
|
||||
size="14"
|
||||
:color="$lightColor"
|
||||
></icon>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let windowWidth = 0
|
||||
import { getRegionsById } from "@/api/common.js";
|
||||
export default {
|
||||
name: "UniCityNvue",
|
||||
props: {
|
||||
headTitle: {
|
||||
//标题
|
||||
type: String,
|
||||
default: "区域选择",
|
||||
},
|
||||
pickerSize: {
|
||||
// 使用多少个tab
|
||||
type: [String, String],
|
||||
default: "1",
|
||||
},
|
||||
provinceData: {
|
||||
// 默认的省市区id,如果不使用id的情况下则为[];
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rightIcon: true,
|
||||
scrollLeft: 500, //顶部选项卡左滑距离
|
||||
scrollTop: 0,
|
||||
enableScroll: true,
|
||||
tabCurrentIndex: 0, //当前选项卡索引
|
||||
tabbars: this.provinceData,
|
||||
pickersize: this.pickerSize,
|
||||
showPicker: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.showPicker = true;
|
||||
if (this.tabbars[0].children.length == 0) {
|
||||
getRegionsById(0).then((res) => {
|
||||
this.tabbars[0].children = res.data.result;
|
||||
});
|
||||
}
|
||||
|
||||
windowWidth = uni.getSystemInfoSync().windowWidth;
|
||||
},
|
||||
hide() {
|
||||
this.showPicker = false;
|
||||
},
|
||||
//tab切换
|
||||
changeTab(e) {
|
||||
let index = e;
|
||||
this.setScroll(index);
|
||||
//延迟300ms,等待swiper动画结束再修改tabbar
|
||||
this.tabCurrentIndex = index;
|
||||
setTimeout(() => {
|
||||
this.getScroll("show" + index);
|
||||
}, 10);
|
||||
},
|
||||
//获得元素的size
|
||||
getElSize(id) {
|
||||
return new Promise((res, rej) => {
|
||||
let el = uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select("#" + id);
|
||||
el.fields(
|
||||
{
|
||||
size: true,
|
||||
scrollOffset: true,
|
||||
rect: true,
|
||||
},
|
||||
(data) => {
|
||||
res(data);
|
||||
}
|
||||
).exec();
|
||||
});
|
||||
},
|
||||
async changCity(index, item) {
|
||||
if (this.tabbars[index].id != item.id) {
|
||||
this.tabbars[index].localName = item.name;
|
||||
this.tabbars[index].id = item.id;
|
||||
if (index < this.tabbars.length - 1) {
|
||||
this.tabbars.splice(index + 1, this.tabbars.length - index - 1);
|
||||
}
|
||||
|
||||
if (this.tabbars.length < this.pickersize) {
|
||||
console.log(item.id);
|
||||
|
||||
let data = await getRegionsById(item.id);
|
||||
|
||||
if (data.data.result.length == 0) {
|
||||
this.$emit("funcValue", this.tabbars);
|
||||
this.hide();
|
||||
} else {
|
||||
var current = {
|
||||
localName: "请选择",
|
||||
id: "",
|
||||
children: data.data.result,
|
||||
};
|
||||
this.tabbars.push(current);
|
||||
this.tabCurrentIndex++;
|
||||
|
||||
this.scrollTop = 0;
|
||||
}
|
||||
} else {
|
||||
this.$emit("funcValue", this.tabbars);
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
async setScroll(index) {
|
||||
let width = 0;
|
||||
let nowWidth = 0;
|
||||
for (let i = 0; i <= index; i++) {
|
||||
let result = await this.getElSize("tab" + i);
|
||||
width += result.width;
|
||||
if (i === index) {
|
||||
nowWidth = result.width;
|
||||
}
|
||||
}
|
||||
if (width + nowWidth > windowWidth) {
|
||||
this.scrollLeft = width + nowWidth;
|
||||
} else {
|
||||
this.scrollLeft = 0;
|
||||
}
|
||||
},
|
||||
getScroll(id) {
|
||||
uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(".panel-scroll-box")
|
||||
.boundingClientRect((data) => {
|
||||
uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select("#" + id)
|
||||
.boundingClientRect((res) => {
|
||||
if (res != undefined && res != null && res != "") {
|
||||
this.scrollTop = res.top - data.top;
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
})
|
||||
.exec();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 优惠券面板 */
|
||||
.mask {
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.maskShow {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.cpicker-content {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.3s ease;
|
||||
transform: translateY(100%);
|
||||
z-index: 3000;
|
||||
}
|
||||
.cpickerShow {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.city-head {
|
||||
width: 750rpx;
|
||||
height: 88rpx;
|
||||
flex-direction: column;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #f4f4f4;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
.city-head-title {
|
||||
font-size: 15px;
|
||||
line-height: 88rpx;
|
||||
align-items: center;
|
||||
/* #ifndef APP-NVUE */
|
||||
text-align: center;
|
||||
/* #endif */
|
||||
}
|
||||
.rightIcon {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 12px;
|
||||
font-size: 10px;
|
||||
color: #bebebe;
|
||||
}
|
||||
.nav-bar {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
height: 90rpx;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex !important;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex-direction: row !important;
|
||||
/* #endif */
|
||||
width: 170rpx;
|
||||
padding: 7px 0px;
|
||||
line-height: 26px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #303133;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.nav-bar-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
.current {
|
||||
color: $aider-light-color;
|
||||
border-color: $aider-light-color;
|
||||
border-bottom-width: 4rpx;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
.current:after {
|
||||
width: 50%;
|
||||
}
|
||||
.panel-scroll-box {
|
||||
height: 516rpx;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.flex-row-c-c {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex-direction: row;
|
||||
/* #endif */
|
||||
padding-left: 25px;
|
||||
}
|
||||
.city-text {
|
||||
/* #ifdef APP-NVUE */
|
||||
flex-direction: row;
|
||||
/* #endif */
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.hide {
|
||||
opacity: 0;
|
||||
}
|
||||
.ischeck {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex !important;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.color {
|
||||
color: $light-color;
|
||||
}
|
||||
icon {
|
||||
margin-left: 40rpx;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,327 @@
|
|||
<template>
|
||||
<view class="serach">
|
||||
<view class="left-box" @tap="onClickLeft">
|
||||
<uni-icons style="line-height:70rpx" :color="color" type="back" size="24" />
|
||||
</view>
|
||||
<view class="content" :style="{ 'border-radius': radius + 'px' }">
|
||||
<!-- HM修改 增加进入输入状态的点击范围 -->
|
||||
<view class="content-box" :class="{ center: mode === 2 }">
|
||||
<u-icon name="search" size="32" style="padding:0 15rpx;"></u-icon>
|
||||
<!-- HM修改 增加placeholder input confirm-type confirm-->
|
||||
<input style="width:100%; " :placeholder="placeholder" placeholder-class="placeholder-color" @input="inputChange" confirm-type="search" @confirm="triggerConfirm" class="input"
|
||||
:class="{ center: !active && mode === 2 }" :focus="isFocus" v-model="inputVal" @focus="focus" @blur="blur" />
|
||||
<!-- <view v-if="!active && mode === 2" class="input sub" @click="getFocus">请输入搜索内容</view> -->
|
||||
<!-- HM修改 @click换成@click.stop阻止冒泡 -->
|
||||
<text v-if="isDelShow" class="icon icon-del" @click.stop="clear"></text>
|
||||
</view>
|
||||
<view v-show="(active && show && button === 'inside') || (isDelShow && button === 'inside')" class="serachBtn" @click="search">搜索</view>
|
||||
</view>
|
||||
<view v-if="button === 'outside'" class="button" :class="{ active: show || active }">
|
||||
<!-- @click="search" -->
|
||||
<view v-if="isShowSeachGoods !=true" class="button-item">
|
||||
<div @click="out()">取消</div>
|
||||
</view>
|
||||
|
||||
<view v-else class="button-item">
|
||||
<!-- {{ !show ? searchName : '搜索' }} -->
|
||||
<u-icon name="grid-fill" size="50" @click="handelListClass()" v-if="!isListClass"></u-icon>
|
||||
<u-icon v-else @click="handelListClass()" name="list-dot" size="50"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
|
||||
import uniIcons from "../uni-icons/uni-icons.vue";
|
||||
|
||||
export default {
|
||||
watch: {},
|
||||
mounted() {},
|
||||
|
||||
components: {
|
||||
uniStatusBar,
|
||||
uniIcons,
|
||||
},
|
||||
props: {
|
||||
mode: {
|
||||
value: Number,
|
||||
default: 1,
|
||||
},
|
||||
//HM修改 定义默认搜索关键词(水印文字)
|
||||
placeholder: {
|
||||
value: String,
|
||||
default: "请输入搜索内容",
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
button: {
|
||||
value: String,
|
||||
default: "outside",
|
||||
},
|
||||
show: {
|
||||
value: Boolean,
|
||||
default: true,
|
||||
},
|
||||
leftText: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
},
|
||||
statusBar: {
|
||||
type: [Boolean, String],
|
||||
default: false,
|
||||
},
|
||||
rightText: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
leftIcon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
rightIcon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
radius: {
|
||||
value: String,
|
||||
default: 60,
|
||||
},
|
||||
isFocusVal: {
|
||||
value: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowSeachGoods: false,
|
||||
// 点击左侧按钮
|
||||
nums: 0,
|
||||
iconParams: false,
|
||||
active: false,
|
||||
inputVal: "",
|
||||
searchName: "取消",
|
||||
isDelShow: false,
|
||||
isFocus: false,
|
||||
isListClass: true,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
console.log("this.isFocusVal", this.isFocusVal);
|
||||
this.isFocus = this.isFocusVal;
|
||||
},
|
||||
methods: {
|
||||
ddType() {
|
||||
this.isShowSeachGoods = true;
|
||||
},
|
||||
|
||||
out() {
|
||||
uni.reLaunch({
|
||||
url: "/pages/tabbar/home/index"
|
||||
});
|
||||
},
|
||||
// 切换排列顺序
|
||||
handelListClass() {
|
||||
this.isListClass = !this.isListClass;
|
||||
this.$emit("SwitchType");
|
||||
},
|
||||
//HM修改 触发组件confirm事件
|
||||
triggerConfirm() {
|
||||
this.nums++;
|
||||
this.$emit("confirm", false);
|
||||
uni.hideKeyboard();
|
||||
this.isShowSeachGoods = true;
|
||||
},
|
||||
//HM修改 触发组件input事件
|
||||
inputChange(event) {
|
||||
this.nums++;
|
||||
var keyword = event.detail.value;
|
||||
this.$emit("input", keyword);
|
||||
if (this.inputVal) {
|
||||
this.isDelShow = true;
|
||||
}
|
||||
},
|
||||
focus() {
|
||||
this.active = true;
|
||||
//HM修改 增加获取焦点判断
|
||||
if (this.inputVal) {
|
||||
this.isDelShow = true;
|
||||
}
|
||||
},
|
||||
blur() {
|
||||
this.isFocus = false;
|
||||
if (!this.inputVal) {
|
||||
this.active = false;
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
//HM修改 收起键盘
|
||||
uni.hideKeyboard();
|
||||
this.isFocus = false;
|
||||
this.inputVal = "";
|
||||
this.active = false;
|
||||
//HM修改 清空内容时候触发组件input
|
||||
this.$emit("input", "");
|
||||
//this.$emit('search', '');//HM修改 清空内容时候不进行搜索
|
||||
},
|
||||
getFocus() {
|
||||
if (!this.isFocus) {
|
||||
this.isFocus = true;
|
||||
}
|
||||
},
|
||||
onClickLeft() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
search() {
|
||||
this.nums++;
|
||||
//HM修改 增加点击取消时候退出输入状态,内容为空时,输入默认关键字
|
||||
if (!this.inputVal) {
|
||||
if (!this.show && this.searchName == "取消") {
|
||||
uni.hideKeyboard();
|
||||
this.isFocus = false;
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.$emit("search", this.inputVal ? this.inputVal : this.placeholder);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
inputVal(newVal) {
|
||||
if (newVal) {
|
||||
this.searchName = "搜索";
|
||||
//this.isDelShow = true; //HM修改 直接点击页面预设关键字样式异常,注销
|
||||
} else {
|
||||
this.searchName = "取消";
|
||||
this.isDelShow = false;
|
||||
}
|
||||
},
|
||||
//HM修改 双向绑定
|
||||
value(val) {
|
||||
this.inputVal = val;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.serach {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
//border-bottom: 1px #f5f5f5 solid; //HM修改 去掉边框
|
||||
box-sizing: border-box;
|
||||
font-size: $uni-font-size-base;
|
||||
|
||||
.left-box {
|
||||
width: 15%;
|
||||
/* #ifndef APP-NVUE */
|
||||
text-align: center;
|
||||
// display: flex;
|
||||
// /* #endif */
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
color: #999;
|
||||
background: #eee;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s linear;
|
||||
|
||||
// border-radius: 30px;
|
||||
|
||||
.content-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
padding: 0 15rpx;
|
||||
|
||||
&.icon-del {
|
||||
font-size: 38rpx;
|
||||
|
||||
&:before {
|
||||
content: "\e644";
|
||||
}
|
||||
}
|
||||
|
||||
&.icon-serach:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
line-height: 60rpx;
|
||||
height: 60rpx;
|
||||
transition: all 0.2s linear;
|
||||
|
||||
&.center {
|
||||
width: 200rpx;
|
||||
}
|
||||
|
||||
&.sub {
|
||||
// position: absolute;
|
||||
width: auto;
|
||||
color: grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.serachBtn {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
padding: 0 30rpx;
|
||||
//HM修改 按钮背景色
|
||||
background: linear-gradient(to right, grey, grey);
|
||||
//background: $uni-color-success;
|
||||
line-height: 60rpx;
|
||||
color: #eee;
|
||||
//border-left: 1px #ccc solid; //HM修改 去掉边框
|
||||
transition: all 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 0;
|
||||
transition: all 0.2s linear;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
&.active {
|
||||
padding-left: 15rpx;
|
||||
width: 100rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-family: iconfont;
|
||||
font-size: 32rpx;
|
||||
font-style: normal;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.placeholder-color {
|
||||
color: #999;
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,186 @@
|
|||
<template>
|
||||
<!-- 遮罩层 -->
|
||||
<u-popup @close="close" v-model="show" mode="bottom" border-radius="30" height="260rpx">
|
||||
|
||||
<view class="share-title">
|
||||
<span>分享至</span>
|
||||
</view>
|
||||
<view class="share-list">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="share-item">
|
||||
<button class="share-btn" open-type="share">
|
||||
<u-icon color="#04BE02" size="80" name="weixin-fill"></u-icon>微信好友
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="share-item" @click="handleShare(item)" v-for="(item, index) in list" :key="index">
|
||||
<u-icon :color="item.color" size="80" :name="item.icon"></u-icon>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="share-item" @click="copyLink()">
|
||||
<u-icon color="#b4aee8" size="80" name="share-fill"></u-icon>
|
||||
<view>{{ '复制链接' }}</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
<script>
|
||||
import h5Copy from "@/js_sdk/h5-copy/h5-copy.js";
|
||||
import configs from "@/config/config";
|
||||
import mpShare from "uview-ui/libs/mixin/mpShare.js";
|
||||
|
||||
export default {
|
||||
mixins: [mpShare],
|
||||
data() {
|
||||
return {
|
||||
configs,
|
||||
show: true,
|
||||
list: [
|
||||
{
|
||||
color: "#04BE02",
|
||||
title: "微信好友",
|
||||
icon: "weixin-fill",
|
||||
type: 0,
|
||||
},
|
||||
{
|
||||
color: "#04BE02",
|
||||
title: "朋友圈",
|
||||
icon: "weixin-circle-fill",
|
||||
type: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
// 图片缩略图、 商品名称 、 type(goods,shop,pintuan) 拼团商品分享以及店铺分享
|
||||
|
||||
props: [
|
||||
"thumbnail",
|
||||
"goodsName",
|
||||
"type",
|
||||
"goodsId",
|
||||
"link",
|
||||
],
|
||||
// #ifdef MP-WEIXIN
|
||||
onShareAppMessage(res) {
|
||||
return {
|
||||
imageUrl: this.thumbnail || require("@/static/logo.png"),
|
||||
};
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit("close");
|
||||
},
|
||||
// h5复制链接
|
||||
// #ifdef H5
|
||||
copyLink() {
|
||||
let content =
|
||||
this.configs.downloadLink +
|
||||
getCurrentPages()[getCurrentPages().length - 1].__page__.fullPath;
|
||||
|
||||
if (content === null || content === undefined) {
|
||||
content = "";
|
||||
} else content = content + "";
|
||||
const result = h5Copy(content);
|
||||
if (result === false) {
|
||||
uni.showToast({
|
||||
title: "不支持",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "复制成功",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
handleShare(val) {
|
||||
if (val.type <= 1) {
|
||||
let shareTitle;
|
||||
|
||||
|
||||
if (this.type == "goods") {
|
||||
shareTitle = `我发现了一个${this.goodsName}商品快来跟我一起看看吧`;
|
||||
} else if (this.type == "shops") {
|
||||
shareTitle = `我发现了一个${this.goodsName}店铺快来跟我一起看看吧`;
|
||||
} else if (this.type == "pintuan") {
|
||||
shareTitle = `我拼了一个${this.goodsName}快来跟我一起抢购吧!`;
|
||||
}
|
||||
|
||||
|
||||
let scene; // "WXSenceTimeline 朋友圈 WXSceneSession 微信好友"
|
||||
val.type == 1
|
||||
? (scene = "WXSenceTimeline")
|
||||
: (scene = "WXSceneSession");
|
||||
uni.share({
|
||||
provider: "weixin",
|
||||
scene: scene,
|
||||
href: configs.downloadLink + this.link,
|
||||
imageUrl: this.thumbnail,
|
||||
type: 0,
|
||||
summary: this.goodsName,
|
||||
title: shareTitle,
|
||||
success: function (res) {
|
||||
// console.log("success:" + JSON.stringify(res));
|
||||
uni.showToast({
|
||||
title: "分享成功!",
|
||||
duration: 2000,
|
||||
icon: "none",
|
||||
});
|
||||
this.$emit("close");
|
||||
},
|
||||
fail: function (err) {
|
||||
uni.showToast({
|
||||
title: "分享失败!",
|
||||
duration: 2000,
|
||||
icon: "none",
|
||||
});
|
||||
this.$emit("close");
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "./mp-share.scss";
|
||||
.share-title {
|
||||
position: relative;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
line-height: 90rpx;
|
||||
text-align: center;
|
||||
> .share-close {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 20rpx;
|
||||
top: 30rpx;
|
||||
}
|
||||
}
|
||||
button:after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.share-list {
|
||||
padding: 0 32rpx;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
> .share-item {
|
||||
width: 25%;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
> * {
|
||||
margin: 8rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,8 @@
|
|||
.share-btn {
|
||||
background: none;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
<template>
|
||||
<div class="dropdown-item">
|
||||
<!-- selected -->
|
||||
<view class="dropdown-item__selected" @click="changePopup">
|
||||
<slot name="title" v-if="$slots.title"></slot>
|
||||
<block v-else>
|
||||
<view class="selected__name">
|
||||
{{title ? title : selectItem.text}}
|
||||
</view>
|
||||
<!-- <view class="selected__icon"
|
||||
:class="showClass === 'show'? 'up' : 'down'"
|
||||
>
|
||||
<span class="iconfont"></span>
|
||||
</view> -->
|
||||
</block>
|
||||
</view>
|
||||
<view class="dropdown-item__content" :style="{top: contentTop + 'px'}" v-if="showList">
|
||||
<!-- dropdown -->
|
||||
<view :class="['list', showClass]">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<block v-else>
|
||||
<view class="list__option" v-for="(item, index) in list" :key="index" @click="choose(item)">
|
||||
<view>{{item.text}}</view>
|
||||
<icon v-if="item.value === value" type="success_no_circle" size="26" />
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<!-- dropdown-mask -->
|
||||
|
||||
<!-- @touchmove 禁止滑动 -->
|
||||
<view @touchmove.stop.prevent="moveHandle" :class="['dropdown-mask', showClass]" v-if="showList" @click="closePopup"></view>
|
||||
</view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {},
|
||||
props: {
|
||||
value: [Number, String, Object],
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
title: [Number, String],
|
||||
contentTopReduse: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showList: "",
|
||||
showClass: '',
|
||||
selectItem: {},
|
||||
contentTop: 0
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
mounted() {
|
||||
this.showList = this.active;
|
||||
this.selectItem = this.list[this.value];
|
||||
// document.addEventListener('click', e => {
|
||||
// //this.$el 可以获取当前组件的容器节点
|
||||
// if (!this.$el.contains(e.target)) {
|
||||
// console.log('change');
|
||||
// this.close()
|
||||
// }
|
||||
// });
|
||||
},
|
||||
methods: {
|
||||
// 禁止滑动
|
||||
moveHandle() {},
|
||||
choose(item) {
|
||||
this.selectItem = item
|
||||
this.$emit('input', item.value)
|
||||
this.closePopup()
|
||||
},
|
||||
changePopup() {
|
||||
if (this.showList) {
|
||||
this.closePopup()
|
||||
} else {
|
||||
this.openPopup()
|
||||
}
|
||||
},
|
||||
openPopup() {
|
||||
// this.$parent -> dropdown-menu
|
||||
this.$parent.$emit('close')
|
||||
this.showList = true
|
||||
this.$nextTick(() => {
|
||||
this.getElementData('.dropdown-item__selected', (data) => {
|
||||
this.contentTop = data[0].bottom - this.contentTopReduse;
|
||||
this.showClass = 'show'
|
||||
})
|
||||
})
|
||||
},
|
||||
closePopup() {
|
||||
this.showClass = ''
|
||||
setTimeout(() => {
|
||||
this.showList = false
|
||||
}, 300)
|
||||
},
|
||||
close() {
|
||||
this.showClass = ''
|
||||
this.showList = false
|
||||
},
|
||||
getElementData(el, callback) {
|
||||
uni.createSelectorQuery().in(this).selectAll(el).boundingClientRect().exec((data) => {
|
||||
callback(data[0]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
/* project id 1564327 */
|
||||
src: url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.eot');
|
||||
src: url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.eot?#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.woff2') format('woff2'),
|
||||
url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.woff') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.ttf') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_1564327_fcszez4n5i.svg#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 28rpx;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-stroke-width: 0.2px;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.line {
|
||||
position: absolute;
|
||||
height: 3px;
|
||||
width: 100px;
|
||||
background: #1abc9c;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
position: relative;
|
||||
|
||||
&__selected {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
// padding: 10rpx;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
|
||||
.selected__name {
|
||||
font-size: 32rpx;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.selected__icon {
|
||||
margin-left: 8rpx;
|
||||
|
||||
&.down {
|
||||
transition: transform .3s;
|
||||
transform: rotateZ(0);
|
||||
}
|
||||
|
||||
&.up {
|
||||
transition: transform .3s;
|
||||
transform: rotateZ(-180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
|
||||
.list {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 3;
|
||||
background: #fff;
|
||||
transform: translateY(-100%);
|
||||
transition: all .3s;
|
||||
|
||||
&.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
&__option {
|
||||
font-size: 32rpx;
|
||||
padding: 26rpx 28rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1rpx solid #DDDDDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transition: all .3s;
|
||||
z-index: 2;
|
||||
|
||||
&.show {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:last-child):after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
width: 2rpx;
|
||||
top: 36rpx;
|
||||
bottom: 36rpx;
|
||||
right: 0;
|
||||
background: $uni-border-color;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<div class="dropdown-menu">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$on('close', this.closeDropdown)
|
||||
},
|
||||
methods: {
|
||||
closeDropdown() {
|
||||
this.$children.forEach(item =>{
|
||||
item.close();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdown-menu {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
dropdown-item {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,151 @@
|
|||
<template>
|
||||
<text v-if="text" :class="inverted ? 'uni-badge--' + type + ' uni-badge--' + size + ' uni-badge--' + type + '-inverted' : 'uni-badge--' + type + ' uni-badge--' + size"
|
||||
:style="badgeStyle" class="uni-badge" @click="onClick()">{{ text }}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Badge 数字角标
|
||||
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
|
||||
* @property {String} text 角标内容
|
||||
* @property {String} type = [default|primary|success|warning|error] 颜色类型
|
||||
* @value default 灰色
|
||||
* @value primary 蓝色
|
||||
* @value success 绿色
|
||||
* @value warning 黄色
|
||||
* @value error 红色
|
||||
* @property {String} size = [normal|small] Badge 大小
|
||||
* @value normal 一般尺寸
|
||||
* @value small 小尺寸
|
||||
* @property {String} inverted = [true|false] 是否无需背景颜色
|
||||
* @event {Function} click 点击 Badge 触发事件
|
||||
* @example <uni-badge text="1"></uni-badge>
|
||||
*/
|
||||
export default {
|
||||
name: 'UniBadge',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
inverted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
badgeStyle: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
text() {
|
||||
this.setStyle()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setStyle()
|
||||
},
|
||||
methods: {
|
||||
setStyle() {
|
||||
this.badgeStyle = `width: ${String(this.text).length * 8 + 12}px`
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bage-size: 12px;
|
||||
$bage-small: scale(0.8);
|
||||
$bage-height: 20px;
|
||||
|
||||
.uni-badge {
|
||||
/* #ifndef APP-PLUS */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
height: $bage-height;
|
||||
line-height: $bage-height;
|
||||
color: $uni-text-color;
|
||||
border-radius: 100px;
|
||||
background-color: $uni-bg-color-hover;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: $bage-size;
|
||||
padding: 0px 6px;
|
||||
}
|
||||
|
||||
.uni-badge--inverted {
|
||||
padding: 0 5px 0 0;
|
||||
color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default {
|
||||
color: $uni-text-color;
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default-inverted {
|
||||
color: $uni-text-color-grey;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--primary {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-badge--primary-inverted {
|
||||
color: $uni-color-primary;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--success {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-success;
|
||||
}
|
||||
|
||||
.uni-badge--success-inverted {
|
||||
color: $uni-color-success;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--warning {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.uni-badge--warning-inverted {
|
||||
color: $uni-color-warning;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--error {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-badge--error-inverted {
|
||||
color: $uni-color-error;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--small {
|
||||
transform: $bage-small;
|
||||
transform-origin: center center;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,170 @@
|
|||
<template>
|
||||
<view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
|
||||
<view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
|
||||
<view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Drawer 抽屉
|
||||
* @description 抽屉侧滑菜单
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=26
|
||||
* @property {Boolean} mask = [true | false] 是否显示遮罩
|
||||
* @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭
|
||||
* @property {Boolean} mode = [left | right] Drawer 滑出位置
|
||||
* @value left 从左侧滑出
|
||||
* @value right 从右侧侧滑出
|
||||
* @property {Number} width 抽屉的宽度 ,仅 vue 页面生效
|
||||
* @event {Function} close 组件关闭时触发事件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniDrawer',
|
||||
props: {
|
||||
/**
|
||||
* 显示模式(左、右),只在初始化生效
|
||||
*/
|
||||
mode: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 蒙层显示状态
|
||||
*/
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 遮罩是否可点击关闭
|
||||
*/
|
||||
maskClick:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 抽屉宽度
|
||||
*/
|
||||
width: {
|
||||
type: Number,
|
||||
default: 220
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibleSync: false,
|
||||
showDrawer: false,
|
||||
rightMode: false,
|
||||
watchTimer: null,
|
||||
drawerWidth: 220
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// #ifndef APP-NVUE
|
||||
this.drawerWidth = this.width
|
||||
// #endif
|
||||
this.rightMode = this.mode === 'right'
|
||||
},
|
||||
methods: {
|
||||
clear(){},
|
||||
close(type) {
|
||||
// fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑
|
||||
if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
|
||||
this._change('showDrawer', 'visibleSync', false)
|
||||
},
|
||||
open() {
|
||||
// fixed by mehaotian 处理重复点击打开的事件
|
||||
if(this.visibleSync) return
|
||||
this._change('visibleSync', 'showDrawer', true)
|
||||
},
|
||||
_change(param1, param2, status) {
|
||||
this[param1] = status
|
||||
if (this.watchTimer) {
|
||||
clearTimeout(this.watchTimer)
|
||||
}
|
||||
this.watchTimer = setTimeout(() => {
|
||||
this[param2] = status
|
||||
this.$emit('change',status)
|
||||
}, status ? 50 : 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 抽屉宽度
|
||||
$drawer-width: 220px;
|
||||
|
||||
.uni-drawer {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.uni-drawer__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: $drawer-width;
|
||||
bottom: 0;
|
||||
background-color: $uni-bg-color;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.uni-drawer--left {
|
||||
left: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
transform: translateX(-$drawer-width);
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
transform: translateX(-100%);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-drawer--right {
|
||||
right: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
transform: translateX($drawer-width);
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
transform: translateX(100%);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-drawer__content--visible {
|
||||
transform: translateX(0px);
|
||||
}
|
||||
|
||||
|
||||
.uni-drawer__mask {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: $uni-bg-color-mask;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.uni-drawer__mask--visible {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,132 @@
|
|||
export default {
|
||||
"pulldown": "\ue588",
|
||||
"refreshempty": "\ue461",
|
||||
"back": "\ue471",
|
||||
"forward": "\ue470",
|
||||
"more": "\ue507",
|
||||
"more-filled": "\ue537",
|
||||
"scan": "\ue612",
|
||||
"qq": "\ue264",
|
||||
"weibo": "\ue260",
|
||||
"weixin": "\ue261",
|
||||
"pengyouquan": "\ue262",
|
||||
"loop": "\ue565",
|
||||
"refresh": "\ue407",
|
||||
"refresh-filled": "\ue437",
|
||||
"arrowthindown": "\ue585",
|
||||
"arrowthinleft": "\ue586",
|
||||
"arrowthinright": "\ue587",
|
||||
"arrowthinup": "\ue584",
|
||||
"undo-filled": "\ue7d6",
|
||||
"undo": "\ue406",
|
||||
"redo": "\ue405",
|
||||
"redo-filled": "\ue7d9",
|
||||
"bars": "\ue563",
|
||||
"chatboxes": "\ue203",
|
||||
"camera": "\ue301",
|
||||
"chatboxes-filled": "\ue233",
|
||||
"camera-filled": "\ue7ef",
|
||||
"cart-filled": "\ue7f4",
|
||||
"cart": "\ue7f5",
|
||||
"checkbox-filled": "\ue442",
|
||||
"checkbox": "\ue7fa",
|
||||
"arrowleft": "\ue582",
|
||||
"arrowdown": "\ue581",
|
||||
"arrowright": "\ue583",
|
||||
"smallcircle-filled": "\ue801",
|
||||
"arrowup": "\ue580",
|
||||
"circle": "\ue411",
|
||||
"eye-filled": "\ue568",
|
||||
"eye-slash-filled": "\ue822",
|
||||
"eye-slash": "\ue823",
|
||||
"eye": "\ue824",
|
||||
"flag-filled": "\ue825",
|
||||
"flag": "\ue508",
|
||||
"gear-filled": "\ue532",
|
||||
"reload": "\ue462",
|
||||
"gear": "\ue502",
|
||||
"hand-thumbsdown-filled": "\ue83b",
|
||||
"hand-thumbsdown": "\ue83c",
|
||||
"hand-thumbsup-filled": "\ue83d",
|
||||
"heart-filled": "\ue83e",
|
||||
"hand-thumbsup": "\ue83f",
|
||||
"heart": "\ue840",
|
||||
"home": "\ue500",
|
||||
"info": "\ue504",
|
||||
"home-filled": "\ue530",
|
||||
"info-filled": "\ue534",
|
||||
"circle-filled": "\ue441",
|
||||
"chat-filled": "\ue847",
|
||||
"chat": "\ue263",
|
||||
"mail-open-filled": "\ue84d",
|
||||
"email-filled": "\ue231",
|
||||
"mail-open": "\ue84e",
|
||||
"email": "\ue201",
|
||||
"checkmarkempty": "\ue472",
|
||||
"list": "\ue562",
|
||||
"locked-filled": "\ue856",
|
||||
"locked": "\ue506",
|
||||
"map-filled": "\ue85c",
|
||||
"map-pin": "\ue85e",
|
||||
"map-pin-ellipse": "\ue864",
|
||||
"map": "\ue364",
|
||||
"minus-filled": "\ue440",
|
||||
"mic-filled": "\ue332",
|
||||
"minus": "\ue410",
|
||||
"micoff": "\ue360",
|
||||
"mic": "\ue302",
|
||||
"clear": "\ue434",
|
||||
"smallcircle": "\ue868",
|
||||
"close": "\ue404",
|
||||
"closeempty": "\ue460",
|
||||
"paperclip": "\ue567",
|
||||
"paperplane": "\ue503",
|
||||
"paperplane-filled": "\ue86e",
|
||||
"person-filled": "\ue131",
|
||||
"contact-filled": "\ue130",
|
||||
"person": "\ue101",
|
||||
"contact": "\ue100",
|
||||
"images-filled": "\ue87a",
|
||||
"phone": "\ue200",
|
||||
"images": "\ue87b",
|
||||
"image": "\ue363",
|
||||
"image-filled": "\ue877",
|
||||
"location-filled": "\ue333",
|
||||
"location": "\ue303",
|
||||
"plus-filled": "\ue439",
|
||||
"plus": "\ue409",
|
||||
"plusempty": "\ue468",
|
||||
"help-filled": "\ue535",
|
||||
"help": "\ue505",
|
||||
"navigate-filled": "\ue884",
|
||||
"navigate": "\ue501",
|
||||
"mic-slash-filled": "\ue892",
|
||||
"search": "\ue466",
|
||||
"settings": "\ue560",
|
||||
"sound": "\ue590",
|
||||
"sound-filled": "\ue8a1",
|
||||
"spinner-cycle": "\ue465",
|
||||
"download-filled": "\ue8a4",
|
||||
"personadd-filled": "\ue132",
|
||||
"videocam-filled": "\ue8af",
|
||||
"personadd": "\ue102",
|
||||
"upload": "\ue402",
|
||||
"upload-filled": "\ue8b1",
|
||||
"starhalf": "\ue463",
|
||||
"star-filled": "\ue438",
|
||||
"star": "\ue408",
|
||||
"trash": "\ue401",
|
||||
"phone-filled": "\ue230",
|
||||
"compose": "\ue400",
|
||||
"videocam": "\ue300",
|
||||
"trash-filled": "\ue8dc",
|
||||
"download": "\ue403",
|
||||
"chatbubble-filled": "\ue232",
|
||||
"chatbubble": "\ue202",
|
||||
"cloud-download": "\ue8e4",
|
||||
"cloud-upload-filled": "\ue8e5",
|
||||
"cloud-upload": "\ue8e6",
|
||||
"cloud-download-filled": "\ue8e9",
|
||||
"headphones":"\ue8bf",
|
||||
"store":"\ue609"
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<cell>
|
||||
<!-- #endif -->
|
||||
<view :class="disabled ? 'uni-list-item--disabled' : ''" :hover-class="disabled || showSwitch ? '' : 'uni-list-item--hover'" class="uni-list-item" @click="onClick">
|
||||
<view class="uni-list-item__container" :class="{ 'uni-list-item--first': isFirstChild }">
|
||||
<view v-if="thumb" class="uni-list-item__icon"><image :src="thumb" class="uni-list-item__icon-img" /></view>
|
||||
<view v-else-if="showExtraIcon" class="uni-list-item__icon">
|
||||
<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" class="uni-icon-wrapper" />
|
||||
</view>
|
||||
<view class="uni-list-item__content">
|
||||
<slot name="left"></slot>
|
||||
<text class="uni-list-item__content-title">{{ title }}</text>
|
||||
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
|
||||
</view>
|
||||
<view class="uni-list-item__extra">
|
||||
<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
|
||||
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" />
|
||||
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked" @change="onSwitchChange" />
|
||||
<slot name="right"></slot>
|
||||
<uni-icons v-if="showArrow" :size="20" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</cell>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '../uni-icons/uni-icons.vue';
|
||||
import uniBadge from '../uni-badge/uni-badge.vue';
|
||||
|
||||
/**
|
||||
* ListItem 列表子组件
|
||||
* @description 列表子组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
* @property {String} title 标题
|
||||
* @property {String} note 描述
|
||||
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标
|
||||
* @property {String} badgeText 数字角标内容
|
||||
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
|
||||
* @property {String} rightText 右侧文字内容
|
||||
* @property {Boolean} disabled = [true|false]是否禁用
|
||||
* @property {Boolean} showArrow = [true|false] 是否显示箭头图标
|
||||
* @property {Boolean} showBadge = [true|false] 是否显示数字角标
|
||||
* @property {Boolean} showSwitch = [true|false] 是否显示Switch
|
||||
* @property {Boolean} switchChecked = [true|false] Switch是否被选中
|
||||
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
|
||||
* @property {Boolean} scrollY = [true|false] 允许纵向滚动,需要显式的设置其宽高
|
||||
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
|
||||
* @event {Function} click 点击 uniListItem 触发事件
|
||||
* @event {Function} switchChange 点击切换 Switch 时触发
|
||||
*/
|
||||
export default {
|
||||
name: 'UniListItem',
|
||||
components: {
|
||||
uniIcons,
|
||||
uniBadge
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}, // 列表标题
|
||||
note: {
|
||||
type: String,
|
||||
default: ''
|
||||
}, // 列表描述
|
||||
disabled: {
|
||||
// 是否禁用
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showArrow: {
|
||||
// 是否显示箭头
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
showBadge: {
|
||||
// 是否显示数字角标
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showSwitch: {
|
||||
// 是否显示Switch
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
switchChecked: {
|
||||
// Switch是否被选中
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
badgeText: {
|
||||
// badge内容
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
badgeType: {
|
||||
// badge类型
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
rightText: {
|
||||
// 右侧文字内容
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
thumb: {
|
||||
// 缩略图
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showExtraIcon: {
|
||||
// 是否显示扩展图标
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
extraIcon: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
type: 'contact',
|
||||
color: '#000000',
|
||||
size: 20
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
inject: ['list'],
|
||||
data() {
|
||||
return {
|
||||
isFirstChild: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
if (!this.list.firstChildAppend) {
|
||||
this.list.firstChildAppend = true;
|
||||
this.isFirstChild = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click');
|
||||
},
|
||||
onSwitchChange(e) {
|
||||
this.$emit('switchChange', e.detail);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
|
||||
|
||||
.uni-list-item {
|
||||
font-size: $uni-font-size-lg;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.uni-list-item--disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.uni-list-item--hover {
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-list-item__container {
|
||||
line-height: 48rpx;
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: $list-item-pd;
|
||||
padding-left: 0;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
/* #ifdef APP-PLUS */
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 0.5px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-list-item--first {
|
||||
border-top-width: 0px;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list-item__container:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: $uni-border-color;
|
||||
}
|
||||
|
||||
.uni-list-item--first:after {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-list-item__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
color: #3b4144;
|
||||
}
|
||||
|
||||
.uni-list-item__content-title {
|
||||
font-size: $uni-font-size-base;
|
||||
color: #3b4144;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__content-note {
|
||||
margin-top: 6rpx;
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__extra {
|
||||
// width: 25%;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__icon {
|
||||
display: flex;
|
||||
margin-right: 18rpx;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.uni-list-item__icon-img {
|
||||
// height: $uni-img-size-base;
|
||||
// width: $uni-img-size-base;
|
||||
height: 38rpx;
|
||||
width: 38rpx;
|
||||
}
|
||||
|
||||
.uni-list-item__extra-text {
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="uni-list">
|
||||
<slot />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<list class="uni-list" :enableBackToTop="enableBackToTop" loadmoreoffset="15" :scroll-y="scrollY" @loadmore="loadMore">
|
||||
<slot />
|
||||
</list>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* List 列表
|
||||
* @description 列表组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
*/
|
||||
export default {
|
||||
name: 'UniList',
|
||||
'mp-weixin': {
|
||||
options: {
|
||||
multipleSlots: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
enableBackToTop: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollY: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
list: this
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.firstChildAppend = false
|
||||
},
|
||||
methods: {
|
||||
loadMore(e) {
|
||||
this.$emit("scrolltolower");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-list {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
background-color: $uni-bg-color;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
// border-bottom-color: $uni-border-color;
|
||||
// border-bottom-style: solid;
|
||||
// border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list:before {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.uni-list:after {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
|
||||
<slot />
|
||||
</refresh>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view ref="uni-refresh" class="uni-refresh" v-show="isShow">
|
||||
<slot />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniRefresh',
|
||||
props: {
|
||||
display: {
|
||||
type: [String],
|
||||
default: "hide"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pulling: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isShow() {
|
||||
if (this.display === "show" || this.pulling === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
onchange(value) {
|
||||
this.pulling = value;
|
||||
},
|
||||
onrefresh(e) {
|
||||
this.$emit("refresh", e);
|
||||
},
|
||||
onpullingdown(e) {
|
||||
// #ifdef APP-NVUE
|
||||
this.$emit("pullingdown", e);
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
var detail = {
|
||||
viewHeight: 90,
|
||||
pullingDistance: e.height
|
||||
}
|
||||
this.$emit("pullingdown", detail);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-refresh {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,87 @@
|
|||
var pullDown = {
|
||||
threshold: 95,
|
||||
maxHeight: 200,
|
||||
callRefresh: 'onrefresh',
|
||||
callPullingDown: 'onpullingdown',
|
||||
refreshSelector: '.uni-refresh'
|
||||
};
|
||||
|
||||
function ready(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
state.canPullDown = newValue;
|
||||
// console.log(newValue);
|
||||
}
|
||||
|
||||
function touchStart(e, instance) {
|
||||
var state = instance.getState();
|
||||
state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
|
||||
state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
// console.log("touchStart");
|
||||
|
||||
state.height = 0;
|
||||
state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||
state.refreshInstance.setStyle({
|
||||
'height': 0
|
||||
});
|
||||
state.refreshInstance.callMethod("onchange", true);
|
||||
}
|
||||
|
||||
function touchMove(e, ownerInstance) {
|
||||
var instance = e.instance;
|
||||
var state = instance.getState();
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
var oldHeight = state.height;
|
||||
var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||
var height = endY - state.touchStartY;
|
||||
if (height > pullDown.maxHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
var refreshInstance = state.refreshInstance;
|
||||
refreshInstance.setStyle({
|
||||
'height': height + 'px'
|
||||
});
|
||||
|
||||
height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
|
||||
state.height = height;
|
||||
refreshInstance.callMethod(pullDown.callPullingDown, {
|
||||
height: height
|
||||
});
|
||||
}
|
||||
|
||||
function touchEnd(e, ownerInstance) {
|
||||
var state = e.instance.getState();
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
state.refreshInstance.callMethod("onchange", false);
|
||||
|
||||
var refreshInstance = state.refreshInstance;
|
||||
if (state.height > pullDown.threshold) {
|
||||
refreshInstance.callMethod(pullDown.callRefresh);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshInstance.setStyle({
|
||||
'height': 0
|
||||
});
|
||||
}
|
||||
|
||||
function propObserver(newValue, oldValue, instance) {
|
||||
pullDown = newValue;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchmove: touchMove,
|
||||
touchstart: touchStart,
|
||||
touchend: touchEnd,
|
||||
propObserver: propObserver
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<template>
|
||||
<view class="uni-load-more">
|
||||
<view class="uni-load-more__img" v-show="status === 'loading' && showIcon">
|
||||
<view class="load1">
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
</view>
|
||||
<view class="load2">
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
</view>
|
||||
<view class="load3">
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
<view :style="{ background: color }"></view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="uni-load-more__text" :style="{ color: color }" v-if="showText">
|
||||
{{ status === 'more' ? contentText.contentdown : status === 'loading' ? contentText.contentrefresh : contentText.contentnomore }}
|
||||
</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'uni-load-more',
|
||||
props: {
|
||||
status: {
|
||||
//上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
|
||||
type: String,
|
||||
default: 'more'
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showText: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#777777'
|
||||
},
|
||||
contentText: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
contentdown: '上拉显示更多',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了'
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@charset "UTF-8";
|
||||
|
||||
.uni-load-more {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 80rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-load-more__text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.uni-load-more__img {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view view {
|
||||
width: 6px;
|
||||
height: 2px;
|
||||
border-top-left-radius: 1px;
|
||||
border-bottom-left-radius: 1px;
|
||||
background: #999;
|
||||
position: absolute;
|
||||
opacity: 0.2;
|
||||
transform-origin: 50%;
|
||||
animation: load 1.56s ease infinite;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view view:nth-child(1) {
|
||||
transform: rotate(90deg);
|
||||
top: 2px;
|
||||
left: 9px;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view view:nth-child(2) {
|
||||
transform: rotate(180deg);
|
||||
top: 11px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view view:nth-child(3) {
|
||||
transform: rotate(270deg);
|
||||
bottom: 2px;
|
||||
left: 9px;
|
||||
}
|
||||
|
||||
.uni-load-more__img > view view:nth-child(4) {
|
||||
top: 11px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.load1,
|
||||
.load2,
|
||||
.load3 {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.load2 {
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
.load3 {
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
|
||||
.load1 view:nth-child(1) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.load2 view:nth-child(1) {
|
||||
animation-delay: 0.13s;
|
||||
}
|
||||
|
||||
.load3 view:nth-child(1) {
|
||||
animation-delay: 0.26s;
|
||||
}
|
||||
|
||||
.load1 view:nth-child(2) {
|
||||
animation-delay: 0.39s;
|
||||
}
|
||||
|
||||
.load2 view:nth-child(2) {
|
||||
animation-delay: 0.52s;
|
||||
}
|
||||
|
||||
.load3 view:nth-child(2) {
|
||||
animation-delay: 0.65s;
|
||||
}
|
||||
|
||||
.load1 view:nth-child(3) {
|
||||
animation-delay: 0.78s;
|
||||
}
|
||||
|
||||
.load2 view:nth-child(3) {
|
||||
animation-delay: 0.91s;
|
||||
}
|
||||
|
||||
.load3 view:nth-child(3) {
|
||||
animation-delay: 1.04s;
|
||||
}
|
||||
|
||||
.load1 view:nth-child(4) {
|
||||
animation-delay: 1.17s;
|
||||
}
|
||||
|
||||
.load2 view:nth-child(4) {
|
||||
animation-delay: 1.3s;
|
||||
}
|
||||
|
||||
.load3 view:nth-child(4) {
|
||||
animation-delay: 1.43s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes load {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,395 @@
|
|||
<template>
|
||||
<view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" @click="close">
|
||||
<uni-icons type="closeempty" :color="color" size="12" />
|
||||
</view>
|
||||
<view v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon">
|
||||
<uni-icons type="sound" :color="color" size="14" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<uni-icons v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" type="closeempty" :color="color"
|
||||
size="12" @click="close" />
|
||||
<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound" :color="color"
|
||||
size="14" />
|
||||
<!-- #endif -->
|
||||
<view ref="textBox" class="uni-noticebar__content-wrapper" :class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
|
||||
<view :id="elIdBox" class="uni-noticebar__content" :class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
|
||||
<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" :class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}"
|
||||
:style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more" @click="clickMore">
|
||||
<text v-if="moreText" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
|
||||
<uni-icons type="arrowright" :color="moreColor" size="14" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '../uni-icons/uni-icons.vue'
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom');
|
||||
const animation = weex.requireModule('animation');
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* NoticeBar 自定义导航栏
|
||||
* @description 通告栏组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=30
|
||||
* @property {Number} speed 文字滚动的速度,默认100px/秒
|
||||
* @property {String} text 显示文字
|
||||
* @property {String} backgroundColor 背景颜色
|
||||
* @property {String} color 文字颜色
|
||||
* @property {String} moreColor 查看更多文字的颜色
|
||||
* @property {String} moreText 设置“查看更多”的文本
|
||||
* @property {Boolean} single = [true|false] 是否单行
|
||||
* @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
|
||||
* @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
|
||||
* @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
|
||||
* @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
|
||||
* @event {Function} click 点击 NoticeBar 触发事件
|
||||
* @event {Function} close 关闭 NoticeBar 触发事件
|
||||
* @event {Function} getmore 点击”查看更多“时触发事件
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniNoticeBar',
|
||||
components: {
|
||||
uniIcons
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
moreText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#fffbe8'
|
||||
},
|
||||
speed: {
|
||||
// 默认1s滚动100px
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#de8c17'
|
||||
},
|
||||
moreColor: {
|
||||
type: String,
|
||||
default: '#999999'
|
||||
},
|
||||
single: {
|
||||
// 是否单行
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollable: {
|
||||
// 是否滚动,添加后控制单行效果取消
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
// 是否显示左侧icon
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showGetMore: {
|
||||
// 是否显示右侧查看更多
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showClose: {
|
||||
// 是否显示左侧关闭按钮
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
return {
|
||||
textWidth: 0,
|
||||
boxWidth: 0,
|
||||
wrapWidth: '',
|
||||
webviewHide: false,
|
||||
// #ifdef APP-NVUE
|
||||
stopAnimation: false,
|
||||
// #endif
|
||||
elId: elId,
|
||||
elIdBox: elIdBox,
|
||||
show: true,
|
||||
animationDuration: 'none',
|
||||
animationPlayState: 'paused',
|
||||
animationDelay: '0s'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
var pages = getCurrentPages();
|
||||
var page = pages[pages.length - 1];
|
||||
var currentWebview = page.$getAppWebview();
|
||||
currentWebview.addEventListener('hide',()=>{
|
||||
this.webviewHide = true
|
||||
})
|
||||
currentWebview.addEventListener('show',()=>{
|
||||
this.webviewHide = false
|
||||
})
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this.initSize()
|
||||
})
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
beforeDestroy() {
|
||||
this.stopAnimation = true
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
initSize() {
|
||||
if (this.scrollable) {
|
||||
// #ifndef APP-NVUE
|
||||
let query = [],
|
||||
boxWidth = 0,
|
||||
textWidth = 0;
|
||||
let textQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elId}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.textWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
let boxQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elIdBox}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.boxWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
query.push(textQuery)
|
||||
query.push(boxQuery)
|
||||
Promise.all(query).then(() => {
|
||||
this.animationDuration = `${this.textWidth / this.speed}s`
|
||||
this.animationDelay = `-${this.boxWidth / this.speed}s`
|
||||
setTimeout(() => {
|
||||
this.animationPlayState = 'running'
|
||||
}, 1000)
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['animationEle'], (res) => {
|
||||
let winWidth = uni.getSystemInfoSync().windowWidth
|
||||
this.textWidth = res.size.width
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateY(-${winWidth}px)`
|
||||
},
|
||||
duration: 0,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateY(-${this.textWidth}px)`
|
||||
},
|
||||
timingFunction: 'linear',
|
||||
duration: (this.textWidth - winWidth) / this.speed * 1000,
|
||||
delay: 1000
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.scrollable && (this.single || this.moreText)) {
|
||||
dom.getComponentRect(this.$refs['textBox'], (res) => {
|
||||
this.wrapWidth = res.size.width
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
loopAnimation() {
|
||||
// #ifdef APP-NVUE
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateY(0px)`
|
||||
},
|
||||
duration: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateY(-${this.textWidth}px)`
|
||||
},
|
||||
duration: this.textWidth / this.speed * 1000,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
clickMore() {
|
||||
this.$emit('getmore')
|
||||
},
|
||||
close() {
|
||||
this.show = false;
|
||||
this.$emit('close')
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.uni-noticebar {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.uni-noticebar-close {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: 18px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single,
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
position: relative;
|
||||
height: 18px;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.uni-noticebar__content--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 0;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
flex: 1;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex: none;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
/* #ifndef APP-NVUE */
|
||||
word-break: break-all;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--single {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
padding-left: 750rpx;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
padding-left: 100%;
|
||||
animation: notice 10s 0s linear infinite both;
|
||||
animation-play-state: paused;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__more {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__more-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes notice {
|
||||
100% {
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
export default {
|
||||
created() {
|
||||
if (this.type === 'message') {
|
||||
// 获取自组件对象
|
||||
this.maskShow = false
|
||||
this.children = null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.type === 'message') {
|
||||
// 不显示遮罩
|
||||
this.maskShow = false
|
||||
// 获取子组件对象
|
||||
this.childrenMsg = null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
customOpen() {
|
||||
if (this.childrenMsg) {
|
||||
this.childrenMsg.open()
|
||||
}
|
||||
},
|
||||
customClose() {
|
||||
if (this.childrenMsg) {
|
||||
this.childrenMsg.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import message from './message.js';
|
||||
// 定义 type 类型:弹出类型:top/bottom/center
|
||||
const config = {
|
||||
// 顶部弹出
|
||||
top:'top',
|
||||
// 底部弹出
|
||||
bottom:'bottom',
|
||||
// 居中弹出
|
||||
center:'center',
|
||||
// 消息提示
|
||||
message:'top',
|
||||
// 对话框
|
||||
dialog:'center',
|
||||
// 分享
|
||||
share:'bottom',
|
||||
}
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
config:config
|
||||
}
|
||||
},
|
||||
mixins: [message],
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
<template>
|
||||
<view class="uni-popup-dialog">
|
||||
<view class="uni-dialog-title">
|
||||
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{title}}</text>
|
||||
</view>
|
||||
<view class="uni-dialog-content">
|
||||
<text class="uni-dialog-content-text" v-if="mode === 'base'">{{content}}</text>
|
||||
<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" >
|
||||
</view>
|
||||
<view class="uni-dialog-button-group">
|
||||
<view class="uni-dialog-button" @click="close">
|
||||
<text class="uni-dialog-button-text">取消</text>
|
||||
</view>
|
||||
<view class="uni-dialog-button uni-border-left" @click="onOk">
|
||||
<text class="uni-dialog-button-text uni-button-color">确定</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* PopUp 弹出层-对话框样式
|
||||
* @description 弹出层-对话框样式
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} value input 模式下的默认值
|
||||
* @property {String} placeholder input 模式下输入提示
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} mode = [base|input] 模式、
|
||||
* @value base 基础对话框
|
||||
* @value input 可输入对话框
|
||||
* @property {String} content 对话框内容
|
||||
* @property {Boolean} beforeClose 是否拦截取消事件
|
||||
* @event {Function} confirm 点击确认按钮触发
|
||||
* @event {Function} close 点击取消按钮触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "uniPopupDialog",
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: [String, Number],
|
||||
default: '请输入内容'
|
||||
},
|
||||
/**
|
||||
* 对话框主题 success/warning/info/error 默认 success
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'error'
|
||||
},
|
||||
/**
|
||||
* 对话框模式 base/input
|
||||
*/
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'base'
|
||||
},
|
||||
/**
|
||||
* 对话框标题
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
default: '提示'
|
||||
},
|
||||
/**
|
||||
* 对话框内容
|
||||
*/
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 拦截取消事件 ,如果拦截取消事件,必须监听close事件,执行 done()
|
||||
*/
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogType: 'error',
|
||||
focus: false,
|
||||
val: ""
|
||||
}
|
||||
},
|
||||
inject: ['popup'],
|
||||
watch: {
|
||||
type(val) {
|
||||
this.dialogType = val
|
||||
},
|
||||
mode(val) {
|
||||
if (val === 'input') {
|
||||
this.dialogType = 'info'
|
||||
}
|
||||
},
|
||||
value(val) {
|
||||
this.val = val
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 对话框遮罩不可点击
|
||||
this.popup.mkclick = false
|
||||
if (this.mode === 'input') {
|
||||
this.dialogType = 'info'
|
||||
this.val = this.value
|
||||
} else {
|
||||
this.dialogType = this.type
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.focus = true
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
onOk() {
|
||||
this.$emit('confirm', () => {
|
||||
this.popup.close()
|
||||
if (this.mode === 'input') this.val = this.value
|
||||
}, this.mode === 'input' ? this.val : '')
|
||||
},
|
||||
/**
|
||||
* 点击取消按钮
|
||||
*/
|
||||
close() {
|
||||
if (this.beforeClose) {
|
||||
this.$emit('close', () => {
|
||||
this.popup.close()
|
||||
})
|
||||
return
|
||||
}
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-dialog {
|
||||
width: 300px;
|
||||
border-radius: 15px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.uni-dialog-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.uni-dialog-title-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.uni-dialog-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5px 15px 15px 15px;
|
||||
}
|
||||
|
||||
.uni-dialog-content-text {
|
||||
font-size: 14px;
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.uni-dialog-button-group {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
border-top-color: #f5f5f5;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.uni-border-left {
|
||||
border-left-color: #f0f0f0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-button-color {
|
||||
color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-dialog-input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
color: $uni-color-success;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<view class="uni-popup-message" :class="'uni-popup__'+[type]">
|
||||
<text class="uni-popup-message-text" :class="'uni-popup__'+[type]+'-text'">{{message}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
* PopUp 弹出层-消息提示
|
||||
* @description 弹出层-消息提示
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} message 消息提示文字
|
||||
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniPopupMessage',
|
||||
props: {
|
||||
/**
|
||||
* 主题 success/warning/info/error 默认 success
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
/**
|
||||
* 消息文字
|
||||
*/
|
||||
message: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
}
|
||||
},
|
||||
inject: ['popup'],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
this.popup.childrenMsg = this
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
if (this.duration === 0) return
|
||||
clearTimeout(this.popuptimer)
|
||||
this.popuptimer = setTimeout(() => {
|
||||
this.popup.close()
|
||||
}, this.duration)
|
||||
},
|
||||
close() {
|
||||
clearTimeout(this.popuptimer)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-message {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
background-color: #e1f3d8;
|
||||
padding: 10px 15px;
|
||||
border-color: #eee;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
}
|
||||
.uni-popup-message-text {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
background-color: #e1f3d8;
|
||||
}
|
||||
|
||||
.uni-popup__success-text {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
background-color: #faecd8;
|
||||
}
|
||||
|
||||
.uni-popup__warn-text {
|
||||
color: #E6A23C;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
background-color: #fde2e2;
|
||||
}
|
||||
|
||||
.uni-popup__error-text {
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
background-color: #F2F6FC;
|
||||
}
|
||||
|
||||
.uni-popup__info-text {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<view class="uni-popup-share">
|
||||
<view class="uni-share-title"><text class="uni-share-title-text">{{title}}</text></view>
|
||||
<view class="uni-share-content">
|
||||
<view class="uni-share-content-box">
|
||||
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
|
||||
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
|
||||
<text class="uni-share-text">{{item.text}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-share-button-box">
|
||||
<button class="uni-share-button" @click="close">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniPopupShare',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '分享到'
|
||||
}
|
||||
},
|
||||
inject: ['popup'],
|
||||
data() {
|
||||
return {
|
||||
bottomData: [{
|
||||
text: '微信',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-2.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: '支付宝',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-8.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: 'QQ',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/gird-3.png',
|
||||
name: 'qq'
|
||||
},
|
||||
{
|
||||
text: '新浪',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-1.png',
|
||||
name: 'sina'
|
||||
},
|
||||
{
|
||||
text: '百度',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-7.png',
|
||||
name: 'copy'
|
||||
},
|
||||
{
|
||||
text: '其他',
|
||||
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-5.png',
|
||||
name: 'more'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
/**
|
||||
* 选择内容
|
||||
*/
|
||||
select(item, index) {
|
||||
this.$emit('select', {
|
||||
item,
|
||||
index
|
||||
}, () => {
|
||||
this.popup.close()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 关闭窗口
|
||||
*/
|
||||
close() {
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-share {
|
||||
background-color: #fff;
|
||||
}
|
||||
.uni-share-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
}
|
||||
.uni-share-title-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.uni-share-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.uni-share-content-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.uni-share-content-item {
|
||||
width: 90px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-share-content-item:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.uni-share-image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.uni-share-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #3B4144;
|
||||
}
|
||||
|
||||
.uni-share-button-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.uni-share-button {
|
||||
flex: 1;
|
||||
border-radius: 50px;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uni-share-button::after {
|
||||
border-radius: 50px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,294 @@
|
|||
<template>
|
||||
<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" @touchmove.stop.prevent="clear">
|
||||
<uni-transition v-if="maskShow" :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans"
|
||||
@click="onTap" />
|
||||
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
|
||||
<view class="uni-popup__wrapper-box" @click.stop="clear">
|
||||
<slot />
|
||||
</view>
|
||||
</uni-transition>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniTransition from '../uni-transition/uni-transition.vue'
|
||||
import popup from './popup.js'
|
||||
/**
|
||||
* PopUp 弹出层
|
||||
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [top|center|bottom] 弹出方式
|
||||
* @value top 顶部弹出
|
||||
* @value center 中间弹出
|
||||
* @value bottom 底部弹出
|
||||
* @value message 消息提示
|
||||
* @value dialog 对话框
|
||||
* @value share 底部分享示例
|
||||
* @property {Boolean} animation = [ture|false] 是否开启动画
|
||||
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
|
||||
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniPopup',
|
||||
components: {
|
||||
uniTransition
|
||||
},
|
||||
props: {
|
||||
// 开启动画
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
// message: 消息提示 ; dialog : 对话框
|
||||
type: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// maskClick
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
popup: this
|
||||
}
|
||||
},
|
||||
mixins: [popup],
|
||||
watch: {
|
||||
/**
|
||||
* 监听type类型
|
||||
*/
|
||||
type: {
|
||||
handler: function(newVal) {
|
||||
this[this.config[newVal]]()
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
/**
|
||||
* 监听遮罩是否可点击
|
||||
* @param {Object} val
|
||||
*/
|
||||
maskClick(val) {
|
||||
this.mkclick = val
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
duration: 300,
|
||||
ani: [],
|
||||
showPopup: false,
|
||||
showTrans: false,
|
||||
maskClass: {
|
||||
'position': 'fixed',
|
||||
'bottom': 0,
|
||||
'top': 0,
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
transClass: {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
},
|
||||
maskShow: true,
|
||||
mkclick: true,
|
||||
popupstyle: 'top'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.mkclick = this.maskClick
|
||||
if (this.animation) {
|
||||
this.duration = 300
|
||||
} else {
|
||||
this.duration = 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clear(e) {
|
||||
// TODO nvue 取消冒泡
|
||||
e.stopPropagation()
|
||||
},
|
||||
open() {
|
||||
this.showPopup = true
|
||||
this.$nextTick(() => {
|
||||
new Promise(resolve => {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => {
|
||||
this.showTrans = true
|
||||
// fixed by mehaotian 兼容 app 端
|
||||
this.$nextTick(() => {
|
||||
resolve();
|
||||
})
|
||||
}, 50);
|
||||
}).then(res => {
|
||||
// 自定义打开事件
|
||||
clearTimeout(this.msgtimer)
|
||||
this.msgtimer = setTimeout(() => {
|
||||
this.customOpen && this.customOpen()
|
||||
}, 100)
|
||||
this.$emit('change', {
|
||||
show: true,
|
||||
type: this.type
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
this.showTrans = false
|
||||
this.$nextTick(() => {
|
||||
this.$emit('change', {
|
||||
show: false,
|
||||
type: this.type
|
||||
})
|
||||
clearTimeout(this.timer)
|
||||
// 自定义关闭事件
|
||||
this.customOpen && this.customClose()
|
||||
this.timer = setTimeout(() => {
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
})
|
||||
},
|
||||
onTap() {
|
||||
if (!this.mkclick) return
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* 顶部弹出样式处理
|
||||
*/
|
||||
top() {
|
||||
this.popupstyle = 'top'
|
||||
this.ani = ['slide-top']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 底部弹出样式处理
|
||||
*/
|
||||
bottom() {
|
||||
this.popupstyle = 'bottom'
|
||||
this.ani = ['slide-bottom']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'bottom': 0
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 中间弹出样式处理
|
||||
*/
|
||||
center() {
|
||||
this.popupstyle = 'center'
|
||||
this.ani = ['zoom-out', 'fade']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
/* #ifndef APP-NVUE */
|
||||
'display': 'flex',
|
||||
'flexDirection': 'column',
|
||||
/* #endif */
|
||||
'bottom': 0,
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'top': 0,
|
||||
'justifyContent': 'center',
|
||||
'alignItems': 'center'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-popup__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: $uni-bg-color-mask;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mask-ani {
|
||||
transition-property: opacity;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
.uni-top-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-bottom-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-center-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.top {
|
||||
/* #ifdef H5 */
|
||||
top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
/* iphonex 等安全区设置,底部安全区适配 */
|
||||
/* #ifndef APP-NVUE */
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.content-ani {
|
||||
// transition: transform 0.3s;
|
||||
transition-property: transform, opacity;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
|
||||
.uni-top-content {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.uni-bottom-content {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.uni-center-content {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,135 @@
|
|||
<template>
|
||||
<view class="uni-section" nvue>
|
||||
<view v-if="type" class="uni-section__head">
|
||||
<view :class="type" class="uni-section__head-tag" />
|
||||
</view>
|
||||
<view class="uni-section__content">
|
||||
<text :class="{'distraction':!subTitle}" class="uni-section__content-title">{{ title }}</text>
|
||||
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
|
||||
</view>
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
* Section 标题栏
|
||||
* @description 标题栏
|
||||
* @property {String} type = [line|circle] 标题装饰类型
|
||||
* @value line 竖线
|
||||
* @value circle 圆形
|
||||
* @property {String} title 主标题
|
||||
* @property {String} subTitle 副标题
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniTitle',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
watch: {
|
||||
title(newVal) {
|
||||
if (uni.report && newVal !== '') {
|
||||
uni.report('title', newVal)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-section {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
margin-top: 10px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
height: 50px;
|
||||
background-color: $uni-bg-color-grey;
|
||||
/* #ifdef APP-NVUE */
|
||||
border-bottom-color: $uni-border-color;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.5px;
|
||||
/* #endif */
|
||||
font-weight: normal;
|
||||
}
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-section:after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(.5);
|
||||
transform: scaleY(.5);
|
||||
background-color: $uni-border-color;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.uni-section__head {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 15px;
|
||||
background-color: $uni-text-color-disable;
|
||||
border-radius: 5px;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-top-right-radius: 50px;
|
||||
border-top-left-radius: 50px;
|
||||
border-bottom-left-radius: 50px;
|
||||
border-bottom-right-radius: 50px;
|
||||
background-color: $uni-text-color-disable;
|
||||
}
|
||||
|
||||
.uni-section__content {
|
||||
flex: 1;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.uni-section__content-title {
|
||||
font-size: $uni-font-size-base;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.distraction {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-section__content-sub {
|
||||
font-size: $uni-font-size-sm;
|
||||
color: $uni-text-color-grey;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<view :style="{ height: statusBarHeight }" class="uni-status-bar">
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
|
||||
export default {
|
||||
name: 'UniStatusBar',
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: statusBarHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-status-bar {
|
||||
width: 750rpx;
|
||||
height: 20px;
|
||||
// height: var(--status-bar-height);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,253 @@
|
|||
<template>
|
||||
<view class="uni-steps">
|
||||
<view :class="[direction==='column'?'uni-steps__column':'uni-steps__row']">
|
||||
<view :class="[direction==='column'?'uni-steps__column-text-container':'uni-steps__row-text-container']">
|
||||
<view v-for="(item,index) in options" :key="index" :class="[direction==='column'?'uni-steps__column-text':'uni-steps__row-text']">
|
||||
<text :style="{color:index<=active?activeColor:deactiveColor}" :class="[direction==='column'?'uni-steps__column-title':'uni-steps__row-title']">{{item.title}}</text>
|
||||
<text v-if="direction=='column'" :style="{color:index<=active?activeColor:deactiveColor}" :class="[direction==='column'?'uni-steps__column-desc':'uni-steps__row-desc']">{{item.desc}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="[direction==='column'?'uni-steps__column-container':'uni-steps__row-container']">
|
||||
<view :class="[direction==='column'?'uni-steps__column-line-item':'uni-steps__row-line-item']" v-for="(item,index) in options"
|
||||
:key="index">
|
||||
<view :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--before':'uni-steps__row-line--before']"
|
||||
:style="{backgroundColor:index<=active&&index!==0?activeColor:index===0?'transparent':deactiveColor}"></view>
|
||||
<view :class="[direction==='column'?'uni-steps__column-check':'uni-steps__row-check']" v-if="index === active">
|
||||
<uni-icons :color="activeColor" type="checkbox-filled" size="14"></uni-icons>
|
||||
</view>
|
||||
<view :class="[direction==='column'?'uni-steps__column-circle':'uni-steps__row-circle']" v-else :style="{backgroundColor:index<active?activeColor:deactiveColor}"></view>
|
||||
<view :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--after':'uni-steps__row-line--after']"
|
||||
:style="{backgroundColor:index<active&&index!==options.length-1?activeColor:index===options.length-1?'transparent':deactiveColor}"></view>
|
||||
<!-- <view v-if="index==0 && direction!='column'" class="address">北京市</view>
|
||||
<view v-if="options.length-1 == index && direction!='column'" class="address">太原市</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '../uni-icons/uni-icons.vue'
|
||||
export default {
|
||||
name: 'UniSteps',
|
||||
components: {
|
||||
uniIcons
|
||||
},
|
||||
props: {
|
||||
direction: {
|
||||
// 排列方向 row column
|
||||
type: String,
|
||||
default: 'row'
|
||||
},
|
||||
activeColor: {
|
||||
// 激活状态颜色
|
||||
type: String,
|
||||
default: '#1aad19'
|
||||
},
|
||||
deactiveColor: {
|
||||
// 未激活状态颜色
|
||||
type: String,
|
||||
default: '#999999'
|
||||
},
|
||||
active: {
|
||||
// 当前步骤
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
} // 数据
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-steps {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-steps__row {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-steps__column {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.uni-steps__row-text-container {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-steps__column-text-container {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-steps__row-text {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-steps__column-text {
|
||||
padding: 6px 0px;
|
||||
// border-bottom-style: solid;
|
||||
// border-bottom-width: 1px;
|
||||
// border-bottom-color: $uni-border-color;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-steps__row-title {
|
||||
font-size: 24rpx;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.uni-steps__column-title {
|
||||
font-size: 24rpx;
|
||||
text-align: left;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.uni-steps__row-desc {
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.uni-steps__column-desc {
|
||||
font-size: $uni-font-size-sm;
|
||||
text-align: left;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.uni-steps__row-container {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-steps__column-container {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
width: 30px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-steps__row-line-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
.address{
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 60rpx;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-steps__column-line-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-steps__row-line {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background-color: $uni-text-color-grey;
|
||||
}
|
||||
|
||||
.uni-steps__column-line {
|
||||
width: 1px;
|
||||
background-color: $uni-text-color-grey;
|
||||
}
|
||||
|
||||
.uni-steps__row-line--after {
|
||||
transform: translateX(1px);
|
||||
}
|
||||
|
||||
.uni-steps__column-line--after {
|
||||
flex: 1;
|
||||
transform: translate(0px, 1px);
|
||||
}
|
||||
|
||||
.uni-steps__row-line--before {
|
||||
transform: translateX(-1px);
|
||||
}
|
||||
|
||||
.uni-steps__column-line--before {
|
||||
height: 6px;
|
||||
transform: translate(0px, -1px);
|
||||
}
|
||||
|
||||
.uni-steps__row-circle {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 100px;
|
||||
background-color: $uni-text-color-grey;
|
||||
margin: 0px 3px;
|
||||
}
|
||||
|
||||
.uni-steps__column-circle {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 100px;
|
||||
background-color: $uni-text-color-grey;
|
||||
margin: 4px 0px 5px 0px;
|
||||
}
|
||||
|
||||
.uni-steps__row-check {
|
||||
margin: 0px 6px;
|
||||
}
|
||||
|
||||
.uni-steps__column-check {
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
margin: 2px 0px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,184 @@
|
|||
<template>
|
||||
<view class="uni-swiper__warp">
|
||||
<slot />
|
||||
<view v-if="mode === 'default'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='default'>
|
||||
<view v-for="(item,index) in info" :style="{
|
||||
'width': (index === current? dots.width*2:dots.width ) + 'px','height':dots.width/3 +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border-radius':'0px'}"
|
||||
:key="index" class="uni-swiper__dots-item uni-swiper__dots-bar" />
|
||||
</view>
|
||||
<view v-if="mode === 'dot'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='dot'>
|
||||
<view v-for="(item,index) in info" :style="{
|
||||
'width': dots.width + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item" />
|
||||
</view>
|
||||
<view v-if="mode === 'round'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='round'>
|
||||
<view v-for="(item,index) in info" :class="[index === current&&'uni-swiper__dots-long']" :style="{
|
||||
'width':(index === current? dots.width*3:dots.width ) + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item " />
|
||||
</view>
|
||||
<view v-if="mode === 'nav'" key='nav' :style="{'background-color':dotsStyles.backgroundColor,'bottom':'0'}" class="uni-swiper__dots-box uni-swiper__dots-nav">
|
||||
<text :style="{'color':dotsStyles.color}" class="uni-swiper__dots-nav-item">{{ (current+1)+"/"+info.length +' ' +info[current][field] }}</text>
|
||||
</view>
|
||||
<view v-if="mode === 'indexes'" key='indexes' :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box">
|
||||
<view v-for="(item,index) in info" :style="{
|
||||
'width':dots.width + 'px','height':dots.height +'px' ,'color':index === current?dots.selectedColor:dots.color,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item uni-swiper__dots-indexes"><text class="uni-swiper__dots-indexes-text">{{ index+1 }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniSwiperDot',
|
||||
props: {
|
||||
info: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
dotsStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 类型 :default(默认) indexes long nav
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
// 只在 nav 模式下生效,变量名称
|
||||
field: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dots: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
bottom: 10,
|
||||
color: '#fff',
|
||||
backgroundColor: 'rgba(0, 0, 0, .3)',
|
||||
border: '1px rgba(0, 0, 0, .3) solid',
|
||||
selectedBackgroundColor: '#333',
|
||||
selectedBorder: '1px rgba(0, 0, 0, .9) solid'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dotsStyles(newVal) {
|
||||
this.dots = Object.assign(this.dots, this.dotsStyles)
|
||||
},
|
||||
mode(newVal) {
|
||||
if (newVal === 'indexes') {
|
||||
this.dots.width = 20
|
||||
this.dots.height = 20
|
||||
} else {
|
||||
this.dots.width = 8
|
||||
this.dots.height = 8
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
if (this.mode === 'indexes') {
|
||||
this.dots.width = 20
|
||||
this.dots.height = 20
|
||||
}
|
||||
this.dots = Object.assign(this.dots, this.dotsStyles)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-swiper__warp {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-box {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-item {
|
||||
width: 8px;
|
||||
border-radius: 100px;
|
||||
margin-left: 6px;
|
||||
background-color: $uni-bg-color-mask;
|
||||
// transition: width 0.2s linear; 不要取消注释,不然会不能变色
|
||||
}
|
||||
|
||||
.uni-swiper__dots-item:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-default {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-long {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-bar {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-nav {
|
||||
bottom: 0px;
|
||||
height: 40px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.uni-swiper__dots-nav-item {
|
||||
/* overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; */
|
||||
font-size: $uni-font-size-base;
|
||||
color: #fff;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-indexes {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
// flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-indexes-text {
|
||||
color: #fff;
|
||||
font-size: $uni-font-size-sm;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,230 @@
|
|||
<template>
|
||||
<view :class="[
|
||||
'uni-tag--' + type,
|
||||
disabled === true || disabled === 'true' ? 'uni-tag--disabled' : '',
|
||||
inverted === true || inverted === 'true' ? type + '-uni-tag--inverted' : '',
|
||||
circle === true || circle === 'true' ? 'uni-tag--circle' : '',
|
||||
mark === true || mark === 'true' ? 'uni-tag--mark' : '',
|
||||
'uni-tag--' + size
|
||||
]"
|
||||
@click="onClick()" class="uni-tag" v-if="text">
|
||||
<text :class="[type === 'default' ? 'uni-tag--default':'uni-tag-text',inverted === true || inverted === 'true' ? 'uni-tag-text--'+type : '',size === 'small' ? 'uni-tag-text--small':'' ]">{{ text }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Tag 标签
|
||||
* @description 用于展示1个或多个文字标签,可点击切换选中、不选中的状态
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=35
|
||||
* @property {String} text 标签内容
|
||||
* @property {String} size = [normal|small] 大小尺寸
|
||||
* @value normal 正常
|
||||
* @value small 小尺寸
|
||||
* @property {String} type = [default|primary|success|warning|error|royal] 颜色类型
|
||||
* @value default 灰色
|
||||
* @value primary 蓝色
|
||||
* @value success 绿色
|
||||
* @value warning 黄色
|
||||
* @value error 红色
|
||||
* @value royal 紫色
|
||||
* @property {Boolean} disabled = [true|false] 是否为禁用状态
|
||||
* @property {Boolean} inverted = [true|false] 是否无需背景颜色(空心标签)
|
||||
* @property {Boolean} circle = [true|false] 是否为圆角
|
||||
* @event {Function} click 点击 Tag 触发事件
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "UniTag",
|
||||
props: {
|
||||
type: {
|
||||
// 标签类型default、primary、success、warning、error、royal
|
||||
type: String,
|
||||
default: "default"
|
||||
},
|
||||
size: {
|
||||
// 标签大小 normal, small
|
||||
type: String,
|
||||
default: "normal"
|
||||
},
|
||||
// 标签内容
|
||||
text: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
disabled: {
|
||||
// 是否为禁用状态
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
inverted: {
|
||||
// 是否为空心
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
circle: {
|
||||
// 是否为圆角样式
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
mark: {
|
||||
// 是否为标记样式
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
if (this.disabled === true || this.disabled === "true") {
|
||||
return;
|
||||
}
|
||||
this.$emit("click");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$tag-pd: 0px 16px;
|
||||
$tag-small-pd: 0px 8px;
|
||||
|
||||
.uni-tag {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
padding: $tag-pd;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
justify-content: center;
|
||||
color: $uni-text-color;
|
||||
border-radius: $uni-border-radius-base;
|
||||
background-color: $uni-bg-color-grey;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-bg-color-grey;
|
||||
}
|
||||
|
||||
.uni-tag--circle {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.uni-tag--mark {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-right-radius: 15px;
|
||||
border-bottom-right-radius: 15px;
|
||||
}
|
||||
|
||||
.uni-tag--disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.uni-tag--small {
|
||||
height: 20px;
|
||||
padding: $tag-small-pd;
|
||||
line-height: 20px;
|
||||
font-size: $uni-font-size-sm;
|
||||
}
|
||||
|
||||
.uni-tag--default {
|
||||
color: $uni-text-color;
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
||||
|
||||
.uni-tag-text--small {
|
||||
font-size: $uni-font-size-sm !important;
|
||||
}
|
||||
|
||||
.uni-tag-text {
|
||||
color: $uni-text-color-inverse;
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
||||
|
||||
.uni-tag-text--primary {
|
||||
color: $uni-color-primary !important;
|
||||
}
|
||||
|
||||
.uni-tag-text--success {
|
||||
color: $uni-color-success !important;
|
||||
}
|
||||
|
||||
.uni-tag-text--warning {
|
||||
color: $uni-color-warning !important;
|
||||
}
|
||||
|
||||
.uni-tag-text--error {
|
||||
color: $uni-color-error !important;
|
||||
}
|
||||
|
||||
.uni-tag--primary {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-primary;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.primary-uni-tag--inverted {
|
||||
color: $uni-color-primary;
|
||||
background-color: $uni-bg-color;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-tag--success {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-success;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-success;
|
||||
}
|
||||
|
||||
.success-uni-tag--inverted {
|
||||
color: $uni-color-success;
|
||||
background-color: $uni-bg-color;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-success;
|
||||
}
|
||||
|
||||
.uni-tag--warning {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-warning;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.warning-uni-tag--inverted {
|
||||
color: $uni-color-warning;
|
||||
background-color: $uni-bg-color;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.uni-tag--error {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-error;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.error-uni-tag--inverted {
|
||||
color: $uni-color-error;
|
||||
background-color: $uni-bg-color;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-tag--inverted {
|
||||
color: $uni-text-color;
|
||||
background-color: $uni-bg-color;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: $uni-bg-color-grey;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,279 @@
|
|||
<template>
|
||||
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
|
||||
@click="change">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
// #endif
|
||||
/**
|
||||
* Transition 过渡动画
|
||||
* @description 简单过渡动画组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
|
||||
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
|
||||
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
|
||||
* @value fade 渐隐渐出过渡
|
||||
* @value slide-top 由上至下过渡
|
||||
* @value slide-right 由右至左过渡
|
||||
* @value slide-bottom 由下至上过渡
|
||||
* @value slide-left 由左至右过渡
|
||||
* @value zoom-in 由小到大过渡
|
||||
* @value zoom-out 由大到小过渡
|
||||
* @property {Number} duration 过渡动画持续时间
|
||||
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
|
||||
*/
|
||||
export default {
|
||||
name: 'uniTransition',
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
modeClass: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: false,
|
||||
transform: '',
|
||||
ani: { in: '',
|
||||
active: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
this.open()
|
||||
} else {
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
stylesObject() {
|
||||
let styles = {
|
||||
...this.styles,
|
||||
'transition-duration': this.duration / 1000 + 's'
|
||||
}
|
||||
let transfrom = ''
|
||||
for (let i in styles) {
|
||||
let line = this.toLine(i)
|
||||
transfrom += line + ':' + styles[i] + ';'
|
||||
}
|
||||
return transfrom
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.timer = null
|
||||
// this.nextTick = (time = 50) => new Promise(resolve => {
|
||||
// clearTimeout(this.timer)
|
||||
// this.timer = setTimeout(resolve, time)
|
||||
// return this.timer
|
||||
// });
|
||||
},
|
||||
methods: {
|
||||
change() {
|
||||
this.$emit('click', {
|
||||
detail: this.isShow
|
||||
})
|
||||
},
|
||||
open() {
|
||||
clearTimeout(this.timer)
|
||||
this.isShow = true
|
||||
this.transform = ''
|
||||
this.ani.in = ''
|
||||
for (let i in this.getTranfrom(false)) {
|
||||
if (i === 'opacity') {
|
||||
this.ani.in = 'fade-in'
|
||||
} else {
|
||||
this.transform += `${this.getTranfrom(false)[i]} `
|
||||
}
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this._animation(true)
|
||||
}, 50)
|
||||
})
|
||||
|
||||
},
|
||||
close(type) {
|
||||
clearTimeout(this.timer)
|
||||
this._animation(false)
|
||||
},
|
||||
_animation(type) {
|
||||
let styles = this.getTranfrom(type)
|
||||
// #ifdef APP-NVUE
|
||||
if(!this.$refs['ani']) return
|
||||
animation.transition(this.$refs['ani'].ref, {
|
||||
styles,
|
||||
duration: this.duration, //ms
|
||||
timingFunction: 'ease',
|
||||
needLayout: false,
|
||||
delay: 0 //ms
|
||||
}, () => {
|
||||
if (!type) {
|
||||
this.isShow = false
|
||||
}
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.transform = ''
|
||||
for (let i in styles) {
|
||||
if (i === 'opacity') {
|
||||
this.ani.in = `fade-${type?'out':'in'}`
|
||||
} else {
|
||||
this.transform += `${styles[i]} `
|
||||
}
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
if (!type) {
|
||||
this.isShow = false
|
||||
}
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
})
|
||||
|
||||
}, this.duration)
|
||||
// #endif
|
||||
|
||||
},
|
||||
getTranfrom(type) {
|
||||
let styles = {
|
||||
transform: ''
|
||||
}
|
||||
this.modeClass.forEach((mode) => {
|
||||
switch (mode) {
|
||||
case 'fade':
|
||||
styles.opacity = type ? 1 : 0
|
||||
break;
|
||||
case 'slide-top':
|
||||
styles.transform += `translateY(${type?'0':'-100%'}) `
|
||||
break;
|
||||
case 'slide-right':
|
||||
styles.transform += `translateX(${type?'0':'100%'}) `
|
||||
break;
|
||||
case 'slide-bottom':
|
||||
styles.transform += `translateY(${type?'0':'100%'}) `
|
||||
break;
|
||||
case 'slide-left':
|
||||
styles.transform += `translateX(${type?'0':'-100%'}) `
|
||||
break;
|
||||
case 'zoom-in':
|
||||
styles.transform += `scale(${type?1:0.8}) `
|
||||
break;
|
||||
case 'zoom-out':
|
||||
styles.transform += `scale(${type?1:1.2}) `
|
||||
break;
|
||||
}
|
||||
})
|
||||
return styles
|
||||
},
|
||||
_modeClassArr(type) {
|
||||
let mode = this.modeClass
|
||||
if (typeof(mode) !== "string") {
|
||||
let modestr = ''
|
||||
mode.forEach((item) => {
|
||||
modestr += (item + '-' + type + ',')
|
||||
})
|
||||
return modestr.substr(0, modestr.length - 1)
|
||||
} else {
|
||||
return mode + '-' + type
|
||||
}
|
||||
},
|
||||
// getEl(el) {
|
||||
// console.log(el || el.ref || null);
|
||||
// return el || el.ref || null
|
||||
// },
|
||||
toLine(name) {
|
||||
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-transition {
|
||||
transition-timing-function: ease;
|
||||
transition-duration: 0.3s;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.slide-top-in {
|
||||
/* transition-property: transform, opacity; */
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.slide-top-active {
|
||||
transform: translateY(0);
|
||||
/* opacity: 1; */
|
||||
}
|
||||
|
||||
.slide-right-in {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.slide-right-active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.slide-bottom-in {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.slide-bottom-active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-left-in {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.slide-left-active {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.zoom-in-in {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.zoom-out-active {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.zoom-out-in {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
Animation 微动画
|
||||
基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
|
||||
*/
|
||||
|
||||
/* css 滤镜 控制黑白底色gif的 */
|
||||
.gif-black{
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
.gif-white{
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
|
||||
/* Animation css */
|
||||
[class*=animation-] {
|
||||
animation-duration: .5s;
|
||||
animation-timing-function: ease-out;
|
||||
animation-fill-mode: both
|
||||
}
|
||||
|
||||
.animation-fade {
|
||||
animation-name: fade;
|
||||
animation-duration: .8s;
|
||||
animation-timing-function: linear
|
||||
}
|
||||
|
||||
.animation-scale-up {
|
||||
animation-name: scale-up
|
||||
}
|
||||
|
||||
.animation-scale-down {
|
||||
animation-name: scale-down
|
||||
}
|
||||
|
||||
.animation-slide-top {
|
||||
animation-name: slide-top
|
||||
}
|
||||
|
||||
.animation-slide-bottom {
|
||||
animation-name: slide-bottom
|
||||
}
|
||||
|
||||
.animation-slide-left {
|
||||
animation-name: slide-left
|
||||
}
|
||||
|
||||
.animation-slide-right {
|
||||
animation-name: slide-right
|
||||
}
|
||||
|
||||
.animation-shake {
|
||||
animation-name: shake
|
||||
}
|
||||
|
||||
.animation-reverse {
|
||||
animation-direction: reverse
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-up {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(.2)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-down {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(1.8)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-top {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-100%)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-bottom {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(100%)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0)
|
||||
}
|
||||
|
||||
10% {
|
||||
transform: translateX(-9px)
|
||||
}
|
||||
|
||||
20% {
|
||||
transform: translateX(8px)
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: translateX(-7px)
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateX(6px)
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(-5px)
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translateX(4px)
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: translateX(-3px)
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: translateX(2px)
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: translateX(-1px)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-left {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-100%)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-right {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(100%)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,682 @@
|
|||
<template>
|
||||
<view>
|
||||
<view v-if="!hid" class="flex-row-center" :style="{ top: scHight }" style="width: 750rpx; position: fixed; z-index: 100; left: 0">
|
||||
<view class="flex-column-center" style="background-color: #fcfcfc; padding: 30rpx; border-radius: 10rpx">
|
||||
<movable-area class="flex" style="width: 100%" animation="false" :style="{ height: originalHeight }">
|
||||
<movable-view scale-value="1" animation="false" damping="5000" :x="moveX" :style="{
|
||||
height: sliderHeight,
|
||||
width: sliderWidth,
|
||||
'z-index': 101,
|
||||
}" direction="horizontal">
|
||||
<image :src="imgbk" class="image" mode="aspectFit" :style="{
|
||||
height: sliderHeight,
|
||||
width: sliderWidth,
|
||||
'margin-top': imgbKH,
|
||||
}"></image>
|
||||
</movable-view>
|
||||
<image :src="img" mode="aspectFit" :style="{ height: originalHeight, width: originalWidth }" style="border-radius: 10rpx"></image>
|
||||
</movable-area>
|
||||
|
||||
<movable-area class="flex-row-start" style="
|
||||
width: 100%;
|
||||
background-color: #efefef;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
margin-top: 30rpx;
|
||||
">
|
||||
<movable-view scale-value="1" animation="false" damping="50" :x="movePv" class="flex-row-center" style="
|
||||
border-radius: 50%;
|
||||
height: 100rpx;
|
||||
width: 100rpx;
|
||||
background-color: #ffffff;
|
||||
border: 2rpx solid #e3e3e3;
|
||||
margin-top: -13rpx;
|
||||
" direction="horizontal" @change="moveChange" @touchend="end">
|
||||
<view :class="endLoad ? 'cuIcon-right' : 'cuIcon-loading turn-load'" class="loadIcon" style="">
|
||||
</view>
|
||||
</movable-view>
|
||||
|
||||
<text style="padding-left: 140rpx" :style="{ color: col }">{{
|
||||
hasImg
|
||||
}}</text>
|
||||
</movable-area>
|
||||
<view class="flex-row-around padding-top" style="width: 100%">
|
||||
<view @click="hide" class="cuIcon-close" style="font-size: 50rpx; color: #e25915">
|
||||
</view>
|
||||
|
||||
<text class="cu-tag bg-cyan round" @click="getCode">刷新拼图</text>
|
||||
<text class="my-neirong-sm cuIcon-safe" style="color: #c1c1c1">Lili-FRAMEWORK</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view
|
||||
@click="hide"
|
||||
v-show="flage"
|
||||
class="flex-row-around"
|
||||
style="border-radius: 10rpx; background-color: #ebebeb"
|
||||
:style="{
|
||||
width: width,
|
||||
height: height,
|
||||
'margin-left': left,
|
||||
'margin-top': top,
|
||||
}"
|
||||
:class="vsr ? 'border-index' : ''"
|
||||
>
|
||||
<view class="flex-row-center" style="width: 45rpx; height: 45rpx">
|
||||
<view v-show="!vsr" class="dh-wt"> </view>
|
||||
<view
|
||||
v-show="vsr"
|
||||
class="cuIcon-roundcheck"
|
||||
style="font-size: 45rpx; color: #07c160"
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<text :class="vsr ? 'ttcl' : ''" style="color: #5a5a5a">{{ vsrtx }}</text>
|
||||
<view class="cuIcon-safe text-gray"> </view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from "@/config/api.js";
|
||||
import storage from "@/utils/storage.js";
|
||||
|
||||
const phone = uni.getSystemInfoSync();
|
||||
const l = phone.screenWidth / 750;
|
||||
export default {
|
||||
name: "verification",
|
||||
created() {
|
||||
// 可自行调整
|
||||
this.scHight = phone.screenHeight / 2 - 200 + "px";
|
||||
this.getCode();
|
||||
// 监听是否要重新验证
|
||||
uni.$on("vert", (data) => {
|
||||
this.vsr = data;
|
||||
this.vsrtx = "点击进行验证";
|
||||
this.getCode();
|
||||
});
|
||||
},
|
||||
props: {
|
||||
height: {
|
||||
type: String,
|
||||
default: "80rpx",
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: "350rpx",
|
||||
},
|
||||
left: {
|
||||
type: String,
|
||||
default: "180rpx",
|
||||
},
|
||||
top: {
|
||||
type: String,
|
||||
default: "30rpx",
|
||||
},
|
||||
business: {
|
||||
type: String,
|
||||
default: "LOGIN",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
flage: false,
|
||||
key: "", //key
|
||||
vsrtx: "点击进行验证", //按钮提示语
|
||||
vsr: false, //
|
||||
hid: true,
|
||||
col: "#838383",
|
||||
movePv: 0,
|
||||
hasImg: "拖动滑块已完成拼图",
|
||||
spcode: "",
|
||||
tl: 0,
|
||||
moveCode: 0,
|
||||
//X轴移动距离
|
||||
moveX: 0,
|
||||
//模版高度
|
||||
originalHeight: "",
|
||||
//模版宽度
|
||||
originalWidth: "",
|
||||
//拼图高度
|
||||
sliderHeight: "",
|
||||
//平涂宽度
|
||||
sliderWidth: "",
|
||||
scHight: 0,
|
||||
//原图
|
||||
img: "",
|
||||
//拼图
|
||||
imgbk: "",
|
||||
endLoad: true,
|
||||
imgbKH: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.hid = false;
|
||||
},
|
||||
hide() {
|
||||
if (!this.vsr) {
|
||||
// vsr判断是否验证成功,成功隐藏验证框
|
||||
this.hid = !this.hid;
|
||||
}
|
||||
},
|
||||
// 获取验证图片
|
||||
getCode() {
|
||||
this.col = "#b3afae";
|
||||
this.hasImg = "图片加载中...";
|
||||
uni.request({
|
||||
url: api.common + "/slider/" + this.business,
|
||||
header: {
|
||||
uuid: storage.getUuid(),
|
||||
},
|
||||
success: (res) => {
|
||||
this.col = "#838383";
|
||||
this.hasImg = "拖动滑块以完成拼图";
|
||||
var data = res.data.result;
|
||||
|
||||
// base64的图片
|
||||
this.img = data.backImage;
|
||||
this.imgbk = data.slidingImage;
|
||||
// 根据参数动态适应验证图片的高宽
|
||||
this.imgbKH = data.randomY * 1.8 + "rpx";
|
||||
this.originalHeight = data.originalHeight * 1.8 + "rpx";
|
||||
this.originalWidth = data.originalWidth * 1.8 + "rpx";
|
||||
this.sliderHeight = data.sliderHeight * 1.8 + "rpx";
|
||||
this.sliderWidth = data.sliderWidth * 1.8 + "rpx";
|
||||
// 适应比率,用来适应滑动距离
|
||||
this.tl = 1 / (1.8 * l);
|
||||
// 无用信息
|
||||
this.spcode = data.capcode;
|
||||
// 验证令牌
|
||||
this.key = data.key;
|
||||
this.$store.state.verificationKey = data.key;
|
||||
},
|
||||
});
|
||||
},
|
||||
end(e) {
|
||||
this.endLoad = false;
|
||||
// 验证拼图位置是否正确
|
||||
uni.request({
|
||||
method: "POST",
|
||||
url:
|
||||
api.common +
|
||||
"/slider/" +
|
||||
this.business +
|
||||
"?xPos=" +
|
||||
parseInt(this.moveCode * this.tl),
|
||||
header: {
|
||||
uuid: storage.getUuid(),
|
||||
},
|
||||
success: (res) => {
|
||||
this.endLoad = true;
|
||||
|
||||
res.data.result == false
|
||||
? (res.data.result = false)
|
||||
: (res.data.result = true);
|
||||
|
||||
if (res.data && res.data.result) {
|
||||
// // 验证成功后把key发送出去,后端会把验证信息存在缓存里
|
||||
this.$emit("send", this.key);
|
||||
this.hide();
|
||||
this.vsr = true;
|
||||
this.vsrtx = "已通过验证";
|
||||
} else {
|
||||
this.getCode(); // 让滑块回到起始位置
|
||||
if (this.movePv == 1) {
|
||||
this.movePv = 0;
|
||||
} else {
|
||||
this.movePv = 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: (res) => {
|
||||
this.$msg("连接服务器失败");
|
||||
},
|
||||
});
|
||||
},
|
||||
// 绑定拼图位置
|
||||
moveChange(e) {
|
||||
this.moveX = e.detail.x;
|
||||
this.moveCode = e.detail.x;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./animation.css";
|
||||
@import "./icon.css";
|
||||
// @import './main.css';
|
||||
.dh-wt {
|
||||
animation: at 1.1s ease;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
background-color: $main-color;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@keyframes at {
|
||||
from {
|
||||
width: 27rpx;
|
||||
height: 27rpx;
|
||||
}
|
||||
|
||||
to {
|
||||
width: 45rpx;
|
||||
height: 45rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.ttcl {
|
||||
color: $main-color;
|
||||
}
|
||||
|
||||
.border-index {
|
||||
border: 1rpx solid $main-color;
|
||||
}
|
||||
.loadIcon {
|
||||
color: $main-color;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.status_bar {
|
||||
height: var(--status-bar-height);
|
||||
background-color: #f1f1f1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status_bar-nobg {
|
||||
height: var(--status-bar-height);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 转圈动画 */
|
||||
.turn-load {
|
||||
animation: turnmy 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes turnmy {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
|
||||
25% {
|
||||
-webkit-transform: rotate(90deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: rotate(180deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: rotate(270deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.status_bar-fixed {
|
||||
height: var(--status-bar-height);
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
background-color: #f1f1f1;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.head-dh-my {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
z-index: 15;
|
||||
background-color: #e3e3e3;
|
||||
width: 750rpx;
|
||||
}
|
||||
|
||||
.border-bom {
|
||||
border-bottom: 0.5rpx solid #dddddd;
|
||||
}
|
||||
|
||||
.border-red {
|
||||
border-bottom: 1rpx solid #d33e18;
|
||||
}
|
||||
|
||||
.border-bom-big {
|
||||
border-bottom: 8rpx solid #dddddd;
|
||||
}
|
||||
|
||||
.border-bom-white {
|
||||
border-bottom: 2rpx solid #ffffff;
|
||||
}
|
||||
|
||||
.border-bom-green {
|
||||
border-bottom: 4rpx solid #f8f9bd;
|
||||
}
|
||||
|
||||
.border-bom-index {
|
||||
border-bottom: 4rpx solid #27d9b3;
|
||||
}
|
||||
|
||||
.padding-left {
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.padding-left-top {
|
||||
padding-left: 20rpx;
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.padding-right {
|
||||
padding-right: 20rpx;
|
||||
}
|
||||
|
||||
.input-my {
|
||||
padding-left: 20rpx;
|
||||
border-radius: 40rpx;
|
||||
height: 50rpx;
|
||||
margin: 10rpx;
|
||||
}
|
||||
|
||||
.tb-tag-absolute {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
border-radius: 25rpx;
|
||||
font-size: 16rpx;
|
||||
margin-left: 25rpx;
|
||||
margin-top: -35rpx;
|
||||
}
|
||||
|
||||
.lk-tag {
|
||||
height: 50rpx;
|
||||
padding: 0 10rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid #24bd9f;
|
||||
border-radius: 6rpx;
|
||||
color: #1c947a;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tb-tag-my {
|
||||
border-radius: 15rpx;
|
||||
font-size: 16rpx;
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
|
||||
.my-green {
|
||||
color: #29c7a5;
|
||||
}
|
||||
|
||||
.my-hui {
|
||||
color: #585858;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.flex-column-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-column-between {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-column-start {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flex-column-around {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row-start {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row-around {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row-center {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row-between {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.my-title {
|
||||
font-size: 35rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.my-neirong {
|
||||
font-size: 26rpx;
|
||||
color: #6d6d6d;
|
||||
}
|
||||
|
||||
.my-neirong-sm {
|
||||
font-size: 23rpx;
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.my-tag-text {
|
||||
font-size: 22rpx;
|
||||
padding-top: 20rpx;
|
||||
color: #bababa;
|
||||
}
|
||||
|
||||
.padding-top {
|
||||
padding-top: 35rpx;
|
||||
}
|
||||
|
||||
.padding-top-sm {
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.bottom-dh {
|
||||
background-color: #f1f1f1;
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
bottom: 0;
|
||||
width: 750rpx;
|
||||
height: 110rpx;
|
||||
}
|
||||
|
||||
.tb-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bottom-text {
|
||||
width: 750rpx;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #9d9d9d;
|
||||
bottom: 70rpx;
|
||||
}
|
||||
|
||||
.white-box {
|
||||
padding: 0 20rpx;
|
||||
margin-bottom: 15rpx;
|
||||
margin-top: 5rpx;
|
||||
width: 715rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
|
||||
.green-box {
|
||||
padding: 0 20rpx;
|
||||
margin-bottom: 15rpx;
|
||||
margin-top: 5rpx;
|
||||
width: 715rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 30rpx;
|
||||
background-image: linear-gradient(#1faf97, #29c7a5);
|
||||
}
|
||||
|
||||
.yuan-sm {
|
||||
width: 13rpx;
|
||||
height: 13rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #1fc189;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.yuan-normal {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #159f3c;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.yuan-normal-red {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #bc3c11;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.yuan-sm-red {
|
||||
width: 13rpx;
|
||||
height: 13rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #de410d;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.white-box-all {
|
||||
margin-top: 5rpx;
|
||||
width: 750rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 13px;
|
||||
}
|
||||
|
||||
.moneycolor {
|
||||
color: #ea5002;
|
||||
}
|
||||
|
||||
.text-bold-sm {
|
||||
font-weight: 425;
|
||||
}
|
||||
|
||||
.sm-moneycolor {
|
||||
color: #e3793b;
|
||||
}
|
||||
|
||||
.margin-top {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.margin-top-sm {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.margin {
|
||||
margin: 20rpx;
|
||||
}
|
||||
|
||||
.margin-left {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.margin-left-top {
|
||||
margin-left: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.margin-right {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.my-absolute {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.my-fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.my-seach {
|
||||
width: 450rpx;
|
||||
height: 55rpx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 30rpx;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.move-view {
|
||||
width: 48rpx;
|
||||
height: 10rpx;
|
||||
background-color: #28ba91;
|
||||
border-radius: 4rpx;
|
||||
margin-left: 100rpx;
|
||||
}
|
||||
|
||||
.move-view-p {
|
||||
width: 45rpx;
|
||||
height: 10rpx;
|
||||
background-color: #28ba91;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.header-dh {
|
||||
position: fixed;
|
||||
padding-top: 20rpx;
|
||||
padding-bottom: 15rpx;
|
||||
height: 70rpx;
|
||||
width: 750rpx;
|
||||
background-color: #f1f1f1;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.tp-normal {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.tp-sm {
|
||||
width: 45rpx;
|
||||
height: 45rpx;
|
||||
}
|
||||
|
||||
.tp-big {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.main-color {
|
||||
color: #07d188;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* base : 基础业务API
|
||||
* buyer : 买家API
|
||||
*/
|
||||
// 开发环境
|
||||
const dev = {
|
||||
common: "https://common-api.pickmall.cn",
|
||||
buyer: "https://buyer-api.pickmall.cn",
|
||||
};
|
||||
// 生产环境
|
||||
const prod = {
|
||||
common: "https://common-api.pickmall.cn",
|
||||
buyer: "https://buyer-api.pickmall.cn",
|
||||
};
|
||||
|
||||
//默认生产环境
|
||||
let api = prod;
|
||||
//如果是开发环境
|
||||
if (process.env.NODE_ENV == "development") {
|
||||
api = dev;
|
||||
} else {
|
||||
api = prod;
|
||||
}
|
||||
//微信小程序,app的打包方式只能是生产环境,所以这块直接条件编译赋值
|
||||
// #ifdef MP-WEIXIN || APP-PLUS
|
||||
api = prod;
|
||||
// #endif
|
||||
|
||||
api.buyer += "/buyer";
|
||||
api.common += "/common";
|
||||
export default {
|
||||
...api,
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
const name = 'lilishop'
|
||||
export default {
|
||||
name: name,
|
||||
schemeLink: `${name}://`, //唤起app地址
|
||||
downloadLink: "https://pickmall.cn/download-page/index.html", //下载地址
|
||||
shareLink: "https://m-b2b2c.pickmall.cn", //分享地址
|
||||
appid: "wx6f10f29075dc1b0b", //小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
|
||||
appSecret :"6dfbe0c72380dce5d49d65b3c91059b1" //可在 manifest.json 查看
|
||||
};
|
|
@ -0,0 +1,123 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>广告启动页</title>
|
||||
<link rel="stylesheet" href="../css/advertise.css">
|
||||
<!-- uni 的 SDK -->
|
||||
<script type="text/javascript" src="../js/webView.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div class="con">
|
||||
<img id="img" src="../imgs/domain.jpeg">
|
||||
</div>
|
||||
<div class="btn" id="timer">
|
||||
<div id="info">跳过</div>
|
||||
<div class="circleProgress_wrapper btn">
|
||||
<div class="wrapper right">
|
||||
<div class="circleProgress rightcircle"></div>
|
||||
</div>
|
||||
<div class="wrapper left">
|
||||
<div class="circleProgress leftcircle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
// var currentAd = {
|
||||
// operation_type: 'NONE'
|
||||
// };
|
||||
|
||||
|
||||
// function getRandom(start, end, fixed = 0) {
|
||||
// let differ = end - start
|
||||
// let random = Math.random()
|
||||
// return (start + differ * random).toFixed(fixed)
|
||||
// }
|
||||
|
||||
// document.addEventListener('plusready', function () {
|
||||
// var xhr = new plus.net.XMLHttpRequest();
|
||||
// xhr.onreadystatechange = function () {
|
||||
// switch (xhr.readyState) {
|
||||
// case 0:
|
||||
// break;
|
||||
// case 1:
|
||||
// break;
|
||||
// case 2:
|
||||
// break;
|
||||
// case 3:
|
||||
// break;
|
||||
// case 4:
|
||||
// if (xhr.status == 200) {
|
||||
// let res = JSON.parse(xhr.responseText);
|
||||
// if (res.length > 0) {
|
||||
// currentAd = res[getRandom(0, res.length - 1)];
|
||||
// document.getElementById("img").src = currentAd.pic_url;
|
||||
// } else {
|
||||
// plus.webview.currentWebview().close();
|
||||
// }
|
||||
// //alert("xhr请求成功:" + xhr.responseText);
|
||||
// } else {
|
||||
// plus.webview.currentWebview().close();
|
||||
// //alert("xhr请求失败:" + xhr.readyState);
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // xhr.open("GET", "https://api-buyer-app.yinbei.cn/advertisement");
|
||||
// xhr.send();
|
||||
// }, false);
|
||||
|
||||
|
||||
// document.addEventListener('UniAppJSBridgeReady', function () {
|
||||
// document.querySelector('.con').addEventListener('click', function (e) {
|
||||
// if (e.isTrusted) {
|
||||
// plus.webview.currentWebview().close();
|
||||
// switch (currentAd.operation_type) {
|
||||
// // 链接地址
|
||||
// case 'URL':
|
||||
// plus.webview.open(currentAd.operation_url)
|
||||
// break;
|
||||
// // 商品
|
||||
// case 'GOODS':
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/product/goods?id=` + currentAd.operation_param
|
||||
// });
|
||||
// break;
|
||||
// // 关键字
|
||||
// case 'KEYWORD':
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/recommend/recommend' + currentAd.operation_param
|
||||
// });
|
||||
// break;
|
||||
// // 店铺
|
||||
// case 'store':
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/product/shopPage?id=` + currentAd.operation_param
|
||||
// });
|
||||
// break;
|
||||
// // 分类
|
||||
// case 'CATEGORY':
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/category/category'
|
||||
// });
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// document.querySelector('.btn').addEventListener('click', function (e) {
|
||||
// if (e.isTrusted) {
|
||||
// plus.webview.currentWebview().close();
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,149 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content .con {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#timer {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
top: 40px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#info {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.circleProgress_wrapper {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 18px;
|
||||
height: 36px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.circleProgress {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 2px solid #FFFFFF;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.rightcircle {
|
||||
border-top: 2px solid #03A9F4;
|
||||
border-right: 2px solid #03A9F4;
|
||||
right: 0;
|
||||
-webkit-animation: circleProgressLoad_right 4s linear;
|
||||
/*动画停留在最后一帧*/
|
||||
animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
.leftcircle {
|
||||
border-bottom: 2px solid #03A9F4;
|
||||
border-left: 2px solid #03A9F4;
|
||||
left: 0;
|
||||
-webkit-animation: circleProgressLoad_left 4s linear;
|
||||
/*动画停留在最后一帧*/
|
||||
animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@-webkit-keyframes circleProgressLoad_right {
|
||||
0% {
|
||||
border-top: 2px solid #03A9F4;
|
||||
border-right: 2px solid #03A9F4;
|
||||
-webkit-transform: rotate(45deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
border-top: 2px solid #03A9F4;
|
||||
border-right: 2px solid #03A9F4;
|
||||
border-left: 2px solid #FFFFFF;
|
||||
border-bottom: 2px solid #FFFFFF;
|
||||
-webkit-transform: rotate(225deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
border-left: 2px solid #FFFFFF;
|
||||
border-bottom: 2px solid #FFFFFF;
|
||||
-webkit-transform: rotate(225deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes circleProgressLoad_left {
|
||||
0% {
|
||||
border-bottom: 2px solid #03A9F4;
|
||||
border-left: 2px solid #03A9F4;
|
||||
-webkit-transform: rotate(45deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
border-bottom: 2px solid #03A9F4;
|
||||
border-left: 2px solid #03A9F4;
|
||||
border-top: 2px solid #FFFFFF;
|
||||
border-right: 2px solid #FFFFFF;
|
||||
-webkit-transform: rotate(45deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
border-top: 2px solid #FFFFFF;
|
||||
border-right: 2px solid #FFFFFF;
|
||||
-webkit-transform: rotate(225deg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>服务器异常</title>
|
||||
|
||||
<script type="text/javascript" src="./js/webView.js"></script>
|
||||
<script type="text/javascript">
|
||||
// H5 plus事件处理
|
||||
var ws = null;
|
||||
|
||||
function plusReady() {
|
||||
// Android处理返回键
|
||||
plus.key.addEventListener('backbutton', function() {
|
||||
(history.length == 1) && ws.close();
|
||||
var c = setTimeout(function() {
|
||||
ws.close();
|
||||
}, 1000);
|
||||
window.onbeforeunload = function() {
|
||||
clearTimeout(c);
|
||||
}
|
||||
history.go(-2);
|
||||
}, false);
|
||||
ws = plus.webview.currentWebview();
|
||||
}
|
||||
if (window.plus) {
|
||||
plusReady();
|
||||
} else {
|
||||
document.addEventListener('plusready', plusReady, false);
|
||||
}
|
||||
document.addEventListener('touchstart', function() {
|
||||
return false;
|
||||
}, true);
|
||||
// 禁止选择
|
||||
document.oncontextmenu = function() {
|
||||
return false;
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 80px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 150px;
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 1px solid #1ABC9C;
|
||||
border-radius: 2px;
|
||||
background-color: #FFFFFF;
|
||||
color: #1ABC9C;
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
margin-bottom: 30px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.go-index {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
<div class="text">服务器异常</div>
|
||||
<button onclick="if(history.length == 1){ws.close();}else{ws.back();ws.back();}">点击刷新</button>
|
||||
<button onclick="ws.close()">点击关闭</button>
|
||||
<button onclick="plus.runtime.restart()">点击重启</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 52 KiB |
|
@ -0,0 +1 @@
|
|||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));
|
After Width: | Height: | Size: 8.8 KiB |
|
@ -0,0 +1,31 @@
|
|||
function AMapWX(a){this.key=a.key;this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};this.MeRequestConfig={key:a.key,serviceName:"https://restapi.amap.com/rest/me"}}
|
||||
AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(c){c=c.longitude+","+c.latitude;wx.setStorage({key:"userLocation",data:c});b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(d){d.data&&b(d.data)}});a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
|
||||
AMapWX.prototype.getMEKeywordsSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.city&&(d.city=b.city);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);b.sig&&(d.sig=
|
||||
b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/local",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
|
||||
AMapWX.prototype.getMEIdSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.id&&(d.id=b.id);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/id",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&
|
||||
0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
|
||||
AMapWX.prototype.getMEPolygonSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.polygon&&(d.polygon=b.polygon);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);
|
||||
b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/polygon",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
|
||||
AMapWX.prototype.getMEaroundSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.center&&(d.center=b.center);b.radius&&(d.radius=b.radius);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&
|
||||
(d.pageSize=b.pageSize);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/around",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
|
||||
AMapWX.prototype.getGeo=function(a){var b=this.requestConfig,c=a.options;b={key:this.key,extensions:"all",s:b.s,platform:b.platform,appname:this.key,sdkversion:b.sdkversion,logversion:b.logversion};c.address&&(b.address=c.address);c.city&&(b.city=c.city);c.batch&&(b.batch=c.batch);c.sig&&(b.sig=c.sig);wx.request({url:"https://restapi.amap.com/v3/geocode/geo",data:b,method:"GET",header:{"content-type":"application/json"},success:function(d){(d=d.data)&&d.status&&"1"===d.status?a.success(d):a.fail({errCode:"0",
|
||||
errMsg:d})},fail:function(d){a.fail({errCode:"0",errMsg:d.errMsg||""})}})};
|
||||
AMapWX.prototype.getRegeo=function(a){function b(d){var e=c.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:c.key,location:d,extensions:"all",s:e.s,platform:e.platform,appname:c.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){g=g.data.regeocode;var h=g.addressComponent,f=[],k=g.roads[0].name+"\u9644\u8fd1",m=d.split(",")[0],n=d.split(",")[1];if(g.pois&&
|
||||
g.pois[0]){k=g.pois[0].name+"\u9644\u8fd1";var l=g.pois[0].location;l&&(m=parseFloat(l.split(",")[0]),n=parseFloat(l.split(",")[1]))}h.provice&&f.push(h.provice);h.city&&f.push(h.city);h.district&&f.push(h.district);h.streetNumber&&h.streetNumber.street&&h.streetNumber.number?(f.push(h.streetNumber.street),f.push(h.streetNumber.number)):f.push(g.roads[0].name);f=f.join("");a.success([{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:k,longitude:m,latitude:n,id:0,regeocodeData:g}])}else a.fail({errCode:g.data.infocode,
|
||||
errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this;a.location?b(a.location):c.getWxLocation(a,function(d){b(d)})};
|
||||
AMapWX.prototype.getWeather=function(a){function b(g){var h="base";a.type&&"forecast"==a.type&&(h="all");wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:d.key,city:g,extensions:h,s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(f){if(f.data.status&&"1"==f.data.status)if(f.data.lives){if((f=f.data.lives)&&0<f.length){f=f[0];var k={city:{text:"\u57ce\u5e02",data:f.city},
|
||||
weather:{text:"\u5929\u6c14",data:f.weather},temperature:{text:"\u6e29\u5ea6",data:f.temperature},winddirection:{text:"\u98ce\u5411",data:f.winddirection+"\u98ce"},windpower:{text:"\u98ce\u529b",data:f.windpower+"\u7ea7"},humidity:{text:"\u6e7f\u5ea6",data:f.humidity+"%"}};k.liveData=f;a.success(k)}}else f.data.forecasts&&f.data.forecasts[0]&&a.success({forecast:f.data.forecasts[0]});else a.fail({errCode:f.data.infocode,errMsg:f.data.info})},fail:function(f){a.fail({errCode:"0",errMsg:f.errMsg||""})}})}
|
||||
function c(g){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:d.key,location:g,extensions:"all",s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(h){if(h.data.status&&"1"==h.data.status){h=h.data.regeocode;if(h.addressComponent)var f=h.addressComponent.adcode;else h.aois&&0<h.aois.length&&(f=h.aois[0].adcode);b(f)}else a.fail({errCode:h.data.infocode,errMsg:h.data.info})},
|
||||
fail:function(h){a.fail({errCode:"0",errMsg:h.errMsg||""})}})}var d=this,e=d.requestConfig;a.city?b(a.city):d.getWxLocation(a,function(g){c(g)})};
|
||||
AMapWX.prototype.getPoiAround=function(a){function b(e){e={key:c.key,location:e,s:d.s,platform:d.platform,appname:c.key,sdkversion:d.sdkversion,logversion:d.logversion};a.querytypes&&(e.types=a.querytypes);a.querykeywords&&(e.keywords=a.querykeywords);wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){if((g=g.data)&&g.pois){for(var h=[],f=0;f<g.pois.length;f++){var k=0==
|
||||
f?a.iconPathSelected:a.iconPath;h.push({latitude:parseFloat(g.pois[f].location.split(",")[1]),longitude:parseFloat(g.pois[f].location.split(",")[0]),iconPath:k,width:22,height:32,id:f,name:g.pois[f].name,address:g.pois[f].address})}a.success({markers:h,poisData:g.pois})}}else a.fail({errCode:g.data.infocode,errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this,d=c.requestConfig;a.location?b(a.location):c.getWxLocation(a,function(e){b(e)})};
|
||||
AMapWX.prototype.getStaticmap=function(a){function b(e){c.push("location="+e);a.zoom&&c.push("zoom="+a.zoom);a.size&&c.push("size="+a.size);a.scale&&c.push("scale="+a.scale);a.markers&&c.push("markers="+a.markers);a.labels&&c.push("labels="+a.labels);a.paths&&c.push("paths="+a.paths);a.traffic&&c.push("traffic="+a.traffic);e="https://restapi.amap.com/v3/staticmap?"+c.join("&");a.success({url:e})}var c=[];c.push("key="+this.key);var d=this.requestConfig;c.push("s="+d.s);c.push("platform="+d.platform);
|
||||
c.push("appname="+d.appname);c.push("sdkversion="+d.sdkversion);c.push("logversion="+d.logversion);a.location?b(a.location):this.getWxLocation(a,function(e){b(e)})};
|
||||
AMapWX.prototype.getInputtips=function(a){var b=Object.assign({},this.requestConfig);a.location&&(b.location=a.location);a.keywords&&(b.keywords=a.keywords);a.type&&(b.type=a.type);a.city&&(b.city=a.city);a.citylimit&&(b.citylimit=a.citylimit);wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.tips&&a.success({tips:c.data.tips})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||
|
||||
""})}})};
|
||||
AMapWX.prototype.getDrivingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.waypoints&&(b.waypoints=a.waypoints);a.avoidpolygons&&(b.avoidpolygons=a.avoidpolygons);a.avoidroad&&(b.avoidroad=a.avoidroad);wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths,
|
||||
taxi_cost:c.data.route.taxi_cost||""})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
|
||||
AMapWX.prototype.getWalkingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
|
||||
AMapWX.prototype.getTransitRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.city&&(b.city=a.city);a.cityd&&(b.cityd=a.cityd);wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&(c=c.data.route,a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||
|
||||
"",transits:c.transits}))},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
|
||||
AMapWX.prototype.getRidingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/riding",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};module.exports.AMapWX=AMapWX;
|
|
@ -0,0 +1,18 @@
|
|||
export default function h5Copy(content) {
|
||||
|
||||
if (!document.queryCommandSupported('copy')) {
|
||||
// 不支持
|
||||
return false
|
||||
}
|
||||
|
||||
let textarea = document.createElement("textarea")
|
||||
textarea.value = content
|
||||
textarea.readOnly = "readOnly"
|
||||
document.body.appendChild(textarea)
|
||||
textarea.select() // 选择对象
|
||||
textarea.setSelectionRange(0, content.length) //核心
|
||||
let result = document.execCommand("copy") // 执行浏览器复制命令
|
||||
textarea.remove()
|
||||
return result
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import { initiatePay } from "@/api/trade";
|
||||
class LiLiWXPay {
|
||||
constructor(...payList) {
|
||||
this.data = payList[0];
|
||||
// 调用支付
|
||||
this.pay = () => {
|
||||
uni.showLoading({
|
||||
title: "加载中",
|
||||
});
|
||||
|
||||
let submitData = {
|
||||
sn: this.data.sn,
|
||||
orderType: this.data.orderType || "TRADE",
|
||||
clientType: "WECHAT_MP",
|
||||
};
|
||||
const paymentMethod = "WECHAT";
|
||||
const paymentClient = "MP";
|
||||
// 调用支付
|
||||
initiatePay(paymentMethod, paymentClient, submitData).then((res) => {
|
||||
let response = res.data.result;
|
||||
console.log(res.data.result);
|
||||
uni.hideLoading();
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
appid: response.appid,
|
||||
timeStamp: response.timeStamp,
|
||||
nonceStr: response.nonceStr,
|
||||
package: response.package,
|
||||
signType: response.signType,
|
||||
paySign: response.paySign,
|
||||
success: (e) => {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "支付成功!",
|
||||
});
|
||||
// 之后成功后跳转到支付成功页面
|
||||
uni.redirectTo({
|
||||
url:
|
||||
"/pages/cart/payment/success?paymentMethod=WECHAT" +
|
||||
"&payPrice=" +
|
||||
this.data.price,
|
||||
});
|
||||
},
|
||||
fail: (e) => {
|
||||
this.exception = e;
|
||||
// 支付异常或支付失败之后跳转到订单页面
|
||||
uni.showModal({
|
||||
content: "支付失败,如果您已支付,请勿反复支付",
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
uni.redirectTo({
|
||||
url: "/pages/order/myOrder?status=0",
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default LiLiWXPay;
|
|
@ -0,0 +1,38 @@
|
|||
import { Canvas, DrawPosterCanvasCtx, CreateImagePathOptions, DrawPosterBuildOpts, DrawPosterUseOpts, drawPosterExtends, DrawPosterUseCtxOpts } from "./utils/interface";
|
||||
declare type DrawPosterInstanceType = InstanceType<typeof DrawPoster> & drawPosterExtends;
|
||||
declare class DrawPoster {
|
||||
canvas: Canvas;
|
||||
ctx: DrawPosterCanvasCtx;
|
||||
canvasId: string;
|
||||
loading: boolean;
|
||||
debugging: boolean;
|
||||
loadingText: string;
|
||||
createText: string;
|
||||
[key: string]: any;
|
||||
private executeOnions;
|
||||
private stopStatus;
|
||||
private drawType;
|
||||
/** 构建器, 构建返回当前实例, 并挂载多个方法 */
|
||||
constructor(canvas: Canvas, ctx: DrawPosterCanvasCtx, canvasId: string, loading: boolean, debugging: boolean, loadingText: string, createText: string, tips: boolean);
|
||||
/** 提示器, 传入消息与数据 */
|
||||
private debuggingLog;
|
||||
/** 传入挂载配置对象, 添加扩展方法 */
|
||||
static use: (opts: DrawPosterUseOpts) => void;
|
||||
/** 传入挂载配置对象, 添加绘画扩展方法 */
|
||||
static useCtx: (opts: DrawPosterUseCtxOpts) => void;
|
||||
/** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
|
||||
static build: (options: string | DrawPosterBuildOpts, tips?: boolean) => Promise<DrawPosterInstanceType>;
|
||||
/** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
|
||||
static buildAll: (optionsAll: (string | DrawPosterBuildOpts)[]) => Promise<{
|
||||
[key: string]: DrawPosterInstanceType;
|
||||
}>;
|
||||
/** 绘制器, 接收执行器函数, 添加到绘制容器中 */
|
||||
draw: (execute: (ctx: DrawPosterCanvasCtx) => Promise<any> | void) => void;
|
||||
/** 等待创建绘画, 成功后清空绘制器容器 */
|
||||
awaitCreate: () => Promise<boolean[]>;
|
||||
/** 创建canvas本地地址 @returns {string} 本地地址 */
|
||||
createImagePath: (baseOptions?: CreateImagePathOptions) => Promise<string>;
|
||||
/** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
|
||||
stop: () => void;
|
||||
}
|
||||
export default DrawPoster;
|
|
@ -0,0 +1,194 @@
|
|||
import uni from "./utils/global";
|
||||
import { handleBuildOpts, extendMount } from "./utils/utils";
|
||||
import { getCanvas2dContext } from "./utils/wx-utils";
|
||||
// 扩展挂载储存
|
||||
let drawPosterExtend = {};
|
||||
let drawCtxPosterExtend = {};
|
||||
class DrawPoster {
|
||||
/** 构建器, 构建返回当前实例, 并挂载多个方法 */
|
||||
constructor(canvas, ctx, canvasId, loading, debugging, loadingText, createText, tips) {
|
||||
var _a;
|
||||
this.canvas = canvas;
|
||||
this.ctx = ctx;
|
||||
|
||||
this.canvasId = canvasId;
|
||||
this.loading = loading;
|
||||
this.debugging = debugging;
|
||||
this.loadingText = loadingText;
|
||||
this.createText = createText;
|
||||
this.executeOnions = [];
|
||||
this.stopStatus = false;
|
||||
/** 提示器, 传入消息与数据 */
|
||||
this.debuggingLog = (message, data, color = "#3489fd") => {
|
||||
if (this.debugging) {
|
||||
if (data) {
|
||||
console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`, data);
|
||||
}
|
||||
else {
|
||||
console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
/** 绘制器, 接收执行器函数, 添加到绘制容器中 */
|
||||
this.draw = (execute) => {
|
||||
const length = this.executeOnions.length;
|
||||
this.executeOnions.push(async () => {
|
||||
var _a, _b;
|
||||
try {
|
||||
this.ctx.save();
|
||||
await execute(this.ctx);
|
||||
this.ctx.restore();
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
const isOutError = ((_b = (_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.search) === null || _b === void 0 ? void 0 : _b.call(_a, `'nodeId' of undefined`)) >= 0;
|
||||
!isOutError && console.error(`${this.canvasId} -> 绘画栈(${length}),绘制错误:`, error);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
/** 等待创建绘画, 成功后清空绘制器容器 */
|
||||
this.awaitCreate = async () => {
|
||||
this.debuggingLog('绘制海报中...');
|
||||
this.loading && uni.showLoading({ title: this.loadingText });
|
||||
const tips = [];
|
||||
for (let i = 0; i < this.executeOnions.length; i++) {
|
||||
const execute = this.executeOnions[i];
|
||||
tips.push(await execute());
|
||||
}
|
||||
this.executeOnions = [];
|
||||
this.debuggingLog('绘制状况', tips);
|
||||
// 当前绘制为 type2 绘制
|
||||
if (this.drawType === 'type2d') {
|
||||
this.loading && uni.hideLoading();
|
||||
|
||||
return tips;
|
||||
}
|
||||
// 当前绘制为 context 绘制
|
||||
return await new Promise((resolve) => {
|
||||
this.ctx.draw(true, () => {
|
||||
resolve(tips);
|
||||
this.loading && uni.hideLoading();
|
||||
});
|
||||
});
|
||||
};
|
||||
/** 创建canvas本地地址 @returns {string} 本地地址 */
|
||||
this.createImagePath = async (baseOptions = {}) => {
|
||||
const { canvas, canvasId, executeOnions, awaitCreate } = this;
|
||||
executeOnions.length && await awaitCreate();
|
||||
// 如果当前为停止状态
|
||||
if (this.stopStatus) {
|
||||
this.stopStatus = false;
|
||||
return '---stop createImagePath---';
|
||||
}
|
||||
this.loading && uni.showLoading({ title: this.createText });
|
||||
const options = Object.assign({}, baseOptions);
|
||||
if (this.drawType === 'context')
|
||||
options.canvasId = canvasId;
|
||||
if (this.drawType === 'type2d')
|
||||
options.canvas = canvas;
|
||||
|
||||
console.log(options)
|
||||
return new Promise((resolve, reject) => {
|
||||
options.success = (res) => {
|
||||
resolve(res.tempFilePath);
|
||||
this.loading && uni.hideLoading();
|
||||
this.debuggingLog('绘制成功 🎉', res, '#19be6b');
|
||||
};
|
||||
options.fail = (err) => {
|
||||
reject(err);
|
||||
this.loading && uni.hideLoading();
|
||||
this.debuggingLog('绘制失败 🌟', err, '#fa3534');
|
||||
};
|
||||
uni.canvasToTempFilePath(options);
|
||||
});
|
||||
};
|
||||
/** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
|
||||
this.stop = () => {
|
||||
this.executeOnions = [];
|
||||
this.stopStatus = true;
|
||||
};
|
||||
if (!canvas || !ctx || !canvasId) {
|
||||
throw new Error("DrawPoster Error: Use DrawPoster.build(string | ops) to build drawPoster instance objects");
|
||||
}
|
||||
// 判断当前绘制类型
|
||||
ctx.drawType = this.drawType = (ctx.draw) ? 'context' : 'type2d';
|
||||
// 挂载全局实例, 绘画扩展
|
||||
extendMount(this.ctx, drawCtxPosterExtend, (extend, target) => {
|
||||
var _a;
|
||||
(_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this.canvas, this.ctx);
|
||||
return (...args) => extend(this.canvas, this.ctx, ...args);
|
||||
});
|
||||
extendMount(this, drawPosterExtend, (extend, target) => {
|
||||
var _a;
|
||||
(_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this);
|
||||
return (...args) => extend(this, ...args);
|
||||
});
|
||||
// 当离开页面时, 自动调用停止绘画
|
||||
const _this = this;
|
||||
const pages = getCurrentPages();
|
||||
const page = pages[pages.length - 1];
|
||||
// 查询标识, 不存在, 在替换页面卸载回调, 避免产生死循环
|
||||
if (!((_a = page === null || page === void 0 ? void 0 : page.onUnload) === null || _a === void 0 ? void 0 : _a.identification)) {
|
||||
page.oldOnUnload = page.onUnload;
|
||||
page.onUnload = function () {
|
||||
_this === null || _this === void 0 ? void 0 : _this.stop();
|
||||
page.oldOnUnload();
|
||||
};
|
||||
page.onUnload.identification = true;
|
||||
}
|
||||
tips && this.debuggingLog('构建完成', { canvas, ctx, selector: canvasId }, '#19be6b');
|
||||
}
|
||||
}
|
||||
/** 传入挂载配置对象, 添加扩展方法 */
|
||||
DrawPoster.use = (opts) => {
|
||||
if (opts.name)
|
||||
drawPosterExtend[opts.name] = opts;
|
||||
};
|
||||
/** 传入挂载配置对象, 添加绘画扩展方法 */
|
||||
DrawPoster.useCtx = (opts) => {
|
||||
if (opts.name)
|
||||
drawCtxPosterExtend[opts.name] = opts;
|
||||
};
|
||||
/** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
|
||||
DrawPoster.build = async (options, tips = true) => {
|
||||
var _a, _b, _c, _d, _e;
|
||||
const config = handleBuildOpts(options);
|
||||
// 初始化监测当前页面绘制对象
|
||||
const pages = getCurrentPages();
|
||||
const page = pages[pages.length - 1];
|
||||
const gcanvas = DrawPoster.prototype['gcanvas'];
|
||||
if (page[config.selector + '__dp']) {
|
||||
return page[config.selector + '__dp'];
|
||||
}
|
||||
if (config.gcanvas) {
|
||||
if (!gcanvas)
|
||||
console.error('--- 当前未引入gcanvas扩展, 将自动切换为普通 canvas ---');
|
||||
else
|
||||
gcanvas.enable((_b = (_a = config.componentThis) === null || _a === void 0 ? void 0 : _a.$refs) === null || _b === void 0 ? void 0 : _b[config.selector], {
|
||||
bridge: gcanvas.WeexBridge
|
||||
});
|
||||
}
|
||||
// 获取canvas实例
|
||||
const canvas = config.gcanvas && gcanvas ?
|
||||
gcanvas.enable((_d = (_c = config.componentThis) === null || _c === void 0 ? void 0 : _c.$refs) === null || _d === void 0 ? void 0 : _d[config.selector], {
|
||||
bridge: gcanvas.WeexBridge
|
||||
}) :
|
||||
await getCanvas2dContext(config.selector, config.componentThis);
|
||||
const ctx = (((_e = canvas.getContext) === null || _e === void 0 ? void 0 : _e.call(canvas, "2d")) || uni.createCanvasContext(config.selector, config.componentThis));
|
||||
const dp = new DrawPoster(canvas, ctx, config.selector, config.loading, config.debugging, config.loadingText, config.createText, tips);
|
||||
// 储存当前绘制对象
|
||||
page[config.selector + '__dp'] = dp;
|
||||
return page[config.selector + '__dp'];
|
||||
};
|
||||
/** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
|
||||
DrawPoster.buildAll = async (optionsAll) => {
|
||||
const dpsArr = await Promise.all(optionsAll.map(async (options) => {
|
||||
return await DrawPoster.build(options, false);
|
||||
}));
|
||||
const dpsObj = {};
|
||||
dpsArr.forEach(dp => dpsObj[dp.canvasId] = dp);
|
||||
console.log("%cdraw-poster 构建完成:", "#E3712A", dpsObj);
|
||||
return dpsObj;
|
||||
};
|
||||
export default DrawPoster;
|
|
@ -0,0 +1,17 @@
|
|||
import { DrawPosterUseOpts } from '../../utils/interface';
|
||||
export interface CreateLayerOpts {
|
||||
background?: string;
|
||||
self?: boolean;
|
||||
line?: boolean;
|
||||
lineHeight?: number;
|
||||
}
|
||||
export interface DrawRowOpt {
|
||||
text?: string;
|
||||
font?: string;
|
||||
color?: string;
|
||||
center?: boolean;
|
||||
width?: number;
|
||||
}
|
||||
declare const _default: DrawPosterUseOpts;
|
||||
/** 绘制表单扩展方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,140 @@
|
|||
/** 绘制表单扩展方法 */
|
||||
export default {
|
||||
name: 'createLayer',
|
||||
init: (dp) => {
|
||||
dp.from = {
|
||||
height: 0,
|
||||
padding: 8,
|
||||
margin: 0
|
||||
};
|
||||
dp.setFromOptions = (opts) => {
|
||||
if (typeof opts.height !== 'undefined') {
|
||||
dp.from.height = opts.height;
|
||||
}
|
||||
if (typeof opts.margin !== 'undefined') {
|
||||
dp.from.margin = opts.margin;
|
||||
}
|
||||
if (typeof opts.padding !== 'undefined') {
|
||||
dp.from.padding = opts.padding;
|
||||
}
|
||||
};
|
||||
},
|
||||
handle: (dp, afferOpts, rowList) => {
|
||||
// 当前配置(头部偏移量, 列内边距, 表单外边距)
|
||||
const height = dp.from.height;
|
||||
const margin = dp.from.margin;
|
||||
const padding = dp.from.padding;
|
||||
// 当前层宽度
|
||||
const containerWidth = dp.canvas.width - (margin * 2);
|
||||
// 基本层配置
|
||||
const opts = Object.assign({ background: "#fff", columnY: height || margin, self: true, line: true, lineHeight: 0, border: true }, afferOpts);
|
||||
// 基本列配置
|
||||
const baseRowOpts = {
|
||||
text: "",
|
||||
font: "24px sans-serif",
|
||||
color: "#333",
|
||||
center: false,
|
||||
width: 0,
|
||||
};
|
||||
// 累计最高的列为标准定义为层高度
|
||||
let maxRowHeight = 0;
|
||||
// 累计固定栅格列偏移量
|
||||
let columnOffsetX = margin;
|
||||
// 创建行绘制任务
|
||||
const drawLayerInfos = rowList.map((afferRowOpts = {}, index) => {
|
||||
const rowOpts = Object.assign(Object.assign({}, baseRowOpts), afferRowOpts);
|
||||
let columnX = 0; // 每列的X轴
|
||||
let columnW = 0; // 每列的宽度
|
||||
let fontOffsetX = 0; // 字体偏移X轴
|
||||
let fontMaxWidth = 100; // 字体最大宽度
|
||||
opts.lineHeight = opts.lineHeight || Number(rowOpts.font.replace(/[^0-9.]/g, ""));
|
||||
if (opts.self) {
|
||||
// 自适应栅格格子计算
|
||||
columnX = containerWidth - (containerWidth / (index + 1)) + margin;
|
||||
columnW = containerWidth / rowList.length;
|
||||
if (columnX > 0 && columnX < containerWidth - columnW) {
|
||||
columnX = (columnW * index) + margin;
|
||||
}
|
||||
fontOffsetX = rowOpts.center ? columnX + (columnW / 2) : columnX + padding;
|
||||
fontMaxWidth = columnW - (padding * 3);
|
||||
}
|
||||
if (!opts.self) {
|
||||
// 固定栅格格子计算
|
||||
columnW = rowOpts.width;
|
||||
columnX = columnOffsetX;
|
||||
fontMaxWidth = columnW - (padding * 3);
|
||||
fontOffsetX = rowOpts.center ? columnOffsetX + (rowOpts.width / 2) : columnOffsetX + padding;
|
||||
columnOffsetX += rowOpts.width;
|
||||
}
|
||||
dp.ctx.font = rowOpts.font;
|
||||
const drawFontInfos = dp.ctx.fillWarpText({
|
||||
text: rowOpts.text,
|
||||
maxWidth: fontMaxWidth,
|
||||
lineHeight: opts.lineHeight,
|
||||
x: fontOffsetX,
|
||||
y: opts.columnY,
|
||||
layer: 10,
|
||||
notFillText: true
|
||||
});
|
||||
// 当前行的高度
|
||||
const rowHeight = (opts.lineHeight * drawFontInfos.length) + (padding * 3);
|
||||
// 若该列高度大于累计高度, 将累计高度替换
|
||||
if (rowHeight > maxRowHeight) {
|
||||
maxRowHeight = rowHeight;
|
||||
}
|
||||
return {
|
||||
font: rowOpts.font,
|
||||
center: rowOpts.center,
|
||||
color: rowOpts.color,
|
||||
border: opts.border,
|
||||
background: opts.background,
|
||||
lineHeight: opts.lineHeight,
|
||||
line: opts.line,
|
||||
drawFontInfos,
|
||||
columnY: opts.columnY,
|
||||
columnX,
|
||||
columnW,
|
||||
columnH: maxRowHeight,
|
||||
margin,
|
||||
padding
|
||||
};
|
||||
});
|
||||
// 将行绘制任务添加至绘制容器中
|
||||
dp.draw((ctx) => drawLayerInfos.forEach((rowOpts, index) => {
|
||||
ctx.font = rowOpts.font;
|
||||
ctx.fillStyle = rowOpts.background;
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = 'left';
|
||||
if (rowOpts.center) {
|
||||
ctx.textAlign = "center";
|
||||
}
|
||||
ctx.fillRect(rowOpts.columnX, rowOpts.columnY, rowOpts.columnW, rowOpts.columnH);
|
||||
if (rowOpts.border) {
|
||||
dp.ctx.strokeRect(margin, rowOpts.columnY, dp.canvas.width - margin, maxRowHeight);
|
||||
}
|
||||
if (rowOpts.line && rowOpts.columnX !== margin) {
|
||||
ctx.moveTo(rowOpts.columnX, rowOpts.columnY);
|
||||
ctx.lineTo(rowOpts.columnX, rowOpts.columnY + rowOpts.columnH);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
}
|
||||
ctx.fillStyle = rowOpts.color;
|
||||
rowOpts.drawFontInfos.forEach(fontInfo => {
|
||||
// 计算每行字体绘制y轴长度
|
||||
// y(当前列置顶轴) + (rowOpts.columnH(当前列最高长度) / 2) - (((总列数-1) * 行高) / 2)
|
||||
const textTotal = rowOpts.drawFontInfos.length - 1;
|
||||
const textMiddleY = (textTotal * rowOpts.lineHeight) / 2;
|
||||
let fontOffsetY = fontInfo.y + (rowOpts.columnH / 2);
|
||||
fontOffsetY -= textMiddleY;
|
||||
ctx.fillText(fontInfo.text, fontInfo.x, fontOffsetY);
|
||||
});
|
||||
}));
|
||||
if (opts.columnY === 0 || opts.columnY === margin) {
|
||||
maxRowHeight += margin;
|
||||
}
|
||||
// 叠加高度
|
||||
dp.from.height += maxRowHeight;
|
||||
return maxRowHeight;
|
||||
},
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseOpts } from '../../utils/interface';
|
||||
export * from './gcanvas';
|
||||
declare const _default: DrawPosterUseOpts;
|
||||
export default _default;
|
|
@ -0,0 +1,9 @@
|
|||
import { WeexBridge, enable, Image } from './gcanvas';
|
||||
export * from './gcanvas';
|
||||
import DrawPoster from "../../draw-poster";
|
||||
DrawPoster.prototype['gcanvas'] = {
|
||||
WeexBridge,
|
||||
enable,
|
||||
Image
|
||||
};
|
||||
export default {};
|
|
@ -0,0 +1,12 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
import { ObjectFit, ObjectPosition, Size } from "../../utils/object-sizing";
|
||||
export interface ImageFitOption {
|
||||
radius?: number;
|
||||
objectFit?: ObjectFit;
|
||||
intrinsicSize?: Size;
|
||||
specifiedSize?: Size;
|
||||
intrinsicPosition?: ObjectPosition;
|
||||
specifiedPosition?: [number, number];
|
||||
}
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
export default _default;
|
|
@ -0,0 +1,25 @@
|
|||
import { calculateConcreteRect } from "../../utils/object-sizing";
|
||||
import uni from "../../utils/global";
|
||||
export default {
|
||||
name: 'drawImageFit',
|
||||
handle: async (canvas, ctx, url, options) => {
|
||||
var _a, _b, _c;
|
||||
const [error, imageInfo] = await uni.getImageInfo({ src: url });
|
||||
// 配置默认值
|
||||
const style = Object.assign({ radius: 0, objectFit: 'cover', intrinsicSize: { width: (_a = imageInfo === null || imageInfo === void 0 ? void 0 : imageInfo.width) !== null && _a !== void 0 ? _a : 100, height: (_b = imageInfo === null || imageInfo === void 0 ? void 0 : imageInfo.height) !== null && _b !== void 0 ? _b : 100 }, specifiedSize: { width: 100, height: 100 }, intrinsicPosition: ['center', 'center'], specifiedPosition: [0, 0] }, options);
|
||||
// 计算图片尺寸
|
||||
const drawImageInfo = calculateConcreteRect(style, style.intrinsicSize, style.specifiedSize);
|
||||
// 如有圆角, 则进行裁剪
|
||||
if (style.radius > 0) {
|
||||
ctx.save();
|
||||
(_c = ctx.setFillStyle) === null || _c === void 0 ? void 0 : _c.call(ctx, 'transparent');
|
||||
ctx.fillStyle = 'transparent';
|
||||
ctx.fillRoundRect(style.specifiedPosition[0], style.specifiedPosition[1], style.specifiedSize.width, style.specifiedSize.height, style.radius);
|
||||
ctx.clip();
|
||||
}
|
||||
const result = await ctx.drawImage(url, ...Object.values(drawImageInfo));
|
||||
if (style.radius > 0)
|
||||
ctx.restore();
|
||||
return result;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 等待绘制图片原型方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,42 @@
|
|||
import { downloadImgUrl } from '../../utils/wx-utils';
|
||||
/** 等待绘制图片原型方法 */
|
||||
export default {
|
||||
name: 'drawImage',
|
||||
init: (canvas, ctx) => {
|
||||
ctx.drawImageProto = ctx.drawImage;
|
||||
},
|
||||
handle: async (canvas, ctx, url, sx, sy, sh, sw, dx, dy, dh, dw) => {
|
||||
// 下载路径
|
||||
const path = await downloadImgUrl(url);
|
||||
// 标记当前绘画存在图片绘制
|
||||
let result = false;
|
||||
// 基本绘制方法, 如果是 fit 方式, 则传入所有参数, 不然则只传入四个参数
|
||||
const baseDrawImage = (imageResource) => {
|
||||
const isFit = typeof dx === 'number' && typeof dw === 'number';
|
||||
if (isFit) {
|
||||
ctx.drawImageProto(imageResource, sx, sy, sh, sw, dx, dy, dh, dw);
|
||||
}
|
||||
else {
|
||||
ctx.drawImageProto(imageResource, sx, sy, sh, sw);
|
||||
}
|
||||
};
|
||||
// 如果是 context 绘制方式, 则直接绘制
|
||||
if (ctx.drawType === 'context') {
|
||||
baseDrawImage(path);
|
||||
result = true;
|
||||
}
|
||||
// 如果是 type2d 绘制方式, 则等待图片绘制完毕
|
||||
if (ctx.drawType === 'type2d') {
|
||||
result = await new Promise(resolve => {
|
||||
const image = canvas.createImage();
|
||||
image.src = path;
|
||||
image.onload = () => {
|
||||
baseDrawImage(image);
|
||||
resolve(true);
|
||||
};
|
||||
image.onerror = () => resolve(false);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 绘制圆角图片原型方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,15 @@
|
|||
/** 绘制圆角图片原型方法 */
|
||||
export default {
|
||||
name: 'drawRoundImage',
|
||||
handle: async (canvas, ctx, url, x, y, w, h, r = 15) => {
|
||||
var _a;
|
||||
ctx.save();
|
||||
(_a = ctx.setFillStyle) === null || _a === void 0 ? void 0 : _a.call(ctx, 'transparent');
|
||||
ctx.fillStyle = 'transparent';
|
||||
ctx.fillRoundRect(x, y, w, h, r);
|
||||
ctx.clip();
|
||||
const result = await ctx.drawImage(url, x, y, w, h);
|
||||
ctx.restore();
|
||||
return result;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 绘制填充圆角矩形方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,7 @@
|
|||
/** 绘制填充圆角矩形方法 */
|
||||
export default {
|
||||
name: 'fillRoundRect',
|
||||
handle: (canvas, ctx, x, y, w, h, r) => {
|
||||
ctx.roundRect(x, y, w, h, r, true);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 绘制换行字体原型方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,76 @@
|
|||
/** 绘制换行字体原型方法 */
|
||||
export default {
|
||||
name: 'fillWarpText',
|
||||
handle: (canvas, ctx, config) => {
|
||||
const newConfig = config = Object.assign({ maxWidth: 100, layer: 2, lineHeight: Number(ctx.font.replace(/[^0-9.]/g, '')), x: 0, y: Number(ctx.font.replace(/[^0-9.]/g, '')) / 1.2, splitText: '', notFillText: false }, config);
|
||||
const { text, splitText, maxWidth, layer, lineHeight, notFillText, x, y } = newConfig;
|
||||
// 当字符串为空时, 抛出错误
|
||||
if (!text) {
|
||||
throw Error('warpFillText Error: text is empty string');
|
||||
}
|
||||
// 分割所有单个字符串
|
||||
const chr = text.split(splitText);
|
||||
// 存入的每行字体的容器
|
||||
let row = [];
|
||||
// 判断字符串
|
||||
let timp = '';
|
||||
if (splitText) {
|
||||
row = chr;
|
||||
}
|
||||
else {
|
||||
// 遍历所有字符串, 填充行容器
|
||||
for (let i = 0; i < chr.length; i++) {
|
||||
// 当超出行列时, 停止执行遍历, 节省计算时间
|
||||
if (row.length > layer) {
|
||||
break;
|
||||
}
|
||||
if (ctx.measureText(timp).width < maxWidth) {
|
||||
// 如果超出长度, 添加进row数组
|
||||
timp += chr[i];
|
||||
}
|
||||
else {
|
||||
// 如超出一行长度, 则换行, 并清除容器
|
||||
i--;
|
||||
row.push(timp);
|
||||
timp = '';
|
||||
}
|
||||
}
|
||||
// 如有剩下字体, 则在最后时添加一行
|
||||
if (timp) {
|
||||
row.push(timp);
|
||||
}
|
||||
// 如果数组长度大于指定行数
|
||||
if (row.length > layer) {
|
||||
row = row.slice(0, layer);
|
||||
// 结束的索引
|
||||
const end = layer - 1;
|
||||
for (let i = 0; i < row[end].length; i++) {
|
||||
const currentWidth = ctx.measureText(`${row[end]}...`).width;
|
||||
if (currentWidth > maxWidth) {
|
||||
// 加上... 当前宽度大于最大宽度时, 去除一位字符串
|
||||
const strEnd = row[end].length - 1;
|
||||
row[end] = row[end].slice(0, strEnd);
|
||||
}
|
||||
else {
|
||||
row[end] += '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 储存并返回绘制信息
|
||||
const drawInfos = row.map((item, index) => {
|
||||
const info = {
|
||||
text: item,
|
||||
y: y + index * lineHeight,
|
||||
x: x,
|
||||
};
|
||||
// 默认执行绘制信息
|
||||
if (!notFillText) {
|
||||
ctx.fillText(info.text, info.x, info.y);
|
||||
}
|
||||
return info;
|
||||
});
|
||||
return drawInfos;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
export { default as drawImage } from "./draw-image";
|
||||
export { default as roundRect } from "./round-rect";
|
||||
export { default as fillRoundRect } from "./fill-round-rect";
|
||||
export { default as strokeRoundRect } from "./stroke-round-rect";
|
||||
export { default as fillWarpText } from "./fill-warp-text";
|
||||
export { default as drawRoundImage } from "./draw-round-image";
|
||||
export { default as drawImageFit } from "./draw-image-fit";
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* @Author: Mr.Mao
|
||||
* @LastEditors: Mr.Mao
|
||||
* @Date: 2020-11-11 20:43:33
|
||||
* @LastEditTime: 2021-01-02 00:16:59
|
||||
* @Description:
|
||||
* @任何一个傻子都能写出让电脑能懂的代码,而只有好的程序员可以写出让人能看懂的代码
|
||||
*/
|
||||
export { default as drawImage } from "./draw-image";
|
||||
export { default as roundRect } from "./round-rect";
|
||||
export { default as fillRoundRect } from "./fill-round-rect";
|
||||
export { default as strokeRoundRect } from "./stroke-round-rect";
|
||||
export { default as fillWarpText } from "./fill-warp-text";
|
||||
export { default as drawRoundImage } from "./draw-round-image";
|
||||
export { default as drawImageFit } from "./draw-image-fit";
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 绘制圆角矩形原型方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,41 @@
|
|||
/** 绘制圆角矩形原型方法 */
|
||||
export default {
|
||||
name: 'roundRect',
|
||||
handle: (canvas, ctx, x, y, w, h, r = 15, fill = false, stroke = false) => {
|
||||
if (r === 0) {
|
||||
if (stroke)
|
||||
ctx.strokeRect(x, y, w, h);
|
||||
if (fill)
|
||||
ctx.fillRect(x, y, w, h);
|
||||
return;
|
||||
}
|
||||
if (w < 2 * r) {
|
||||
r = w / 2;
|
||||
}
|
||||
if (h < 2 * r) {
|
||||
r = h / 2;
|
||||
}
|
||||
// 开始绘制
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
|
||||
// 移动复制
|
||||
ctx.moveTo(x + r, y);
|
||||
ctx.lineTo(x + w - r, y);
|
||||
ctx.lineTo(x + w, y + r);
|
||||
// (x,y,z,j,f) x,y圆心z半径,j起始弧度f,终止弧度
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
|
||||
ctx.lineTo(x + w, y + h - r);
|
||||
ctx.lineTo(x + w - r, y + h);
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
|
||||
ctx.lineTo(x + r, y + h);
|
||||
ctx.lineTo(x, y + h - r);
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
|
||||
ctx.lineTo(x, y + r);
|
||||
ctx.lineTo(x + r, y);
|
||||
if (stroke)
|
||||
ctx.stroke();
|
||||
if (fill)
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
}
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
import { DrawPosterUseCtxOpts } from '../../utils/interface';
|
||||
declare const _default: DrawPosterUseCtxOpts;
|
||||
/** 绘制填充圆角矩形方法 */
|
||||
export default _default;
|
|
@ -0,0 +1,7 @@
|
|||
/** 绘制填充圆角矩形方法 */
|
||||
export default {
|
||||
name: 'strokeRoundRect',
|
||||
handle: (canvas, ctx, x, y, w, h, r) => {
|
||||
ctx.roundRect(x, y, w, h, r, false, true);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,101 @@
|
|||
import { DrawPosterUseOpts } from '../../utils/interface';
|
||||
import { ImageFitOption } from '../draw-function/draw-image-fit';
|
||||
/** 矩形基本信息 */
|
||||
interface PainterItemSize {
|
||||
/** 容器的宽度,固定值 */
|
||||
width: number;
|
||||
/** 容器的高度,固定值 */
|
||||
height: number;
|
||||
}
|
||||
/** 元素位置信息 */
|
||||
interface PainterItemSite {
|
||||
/** 元素锚点距左边的距离; 默认: 0 */
|
||||
left?: number;
|
||||
/** 元素锚点距上边的距离; 默认: 0 */
|
||||
top?: number;
|
||||
}
|
||||
/** 绘制图片信息 */
|
||||
interface PainterImageInfo extends PainterItemSize, PainterItemSite {
|
||||
/** 绘制图片元素 */
|
||||
type: 'image';
|
||||
/** 图片地址 */
|
||||
src: string;
|
||||
/** 图片自适应, 可参考 css 属性 object-fit */
|
||||
objectFit?: ImageFitOption['objectFit'];
|
||||
/** 图片在元素容器中显示的位置,可参考 css 属性 object-position */
|
||||
position?: ImageFitOption['intrinsicPosition'];
|
||||
/** 圆角尺寸; 默认: 0 */
|
||||
radius?: number;
|
||||
}
|
||||
/** 绘制矩形信息 */
|
||||
interface PainterRectInfo extends PainterItemSize, PainterItemSite {
|
||||
/** 绘制矩形元素 */
|
||||
type: "rect";
|
||||
/** 矩形背景颜色; 默认: "#000" */
|
||||
background?: string;
|
||||
/** 圆角尺寸; 默认: 0 */
|
||||
radius?: number;
|
||||
}
|
||||
/** 绘制单行文字信息 */
|
||||
interface PainterTextInfo extends PainterItemSite {
|
||||
/** 绘制文本元素 */
|
||||
type: "text";
|
||||
/** 文本颜色; 默认: "#000" */
|
||||
color?: string;
|
||||
/** 字体; 默认: "serial" */
|
||||
fontFamily?: string;
|
||||
/** 字号(单位rpx); 默认: 30 rpx */
|
||||
fontSize?: number;
|
||||
/** 字重; 默认: "normal" 可选项: "bold" */
|
||||
fontWeight?: string;
|
||||
/** 字型 默认: "normal" 可选项: "italic" */
|
||||
fontStyle?: string;
|
||||
/** 元素的宽度(单位rpx), 水平排布时影响后一个元素的位置,为 null 时根据文字实际占用的宽度计算 */
|
||||
width?: number;
|
||||
/** 文本内容 */
|
||||
content: string;
|
||||
}
|
||||
/** 绘制多行文字信息 */
|
||||
interface PainterLineFeedTextInfo extends PainterItemSite {
|
||||
/** 绘制换行文本元素 */
|
||||
type: "line-feed-text";
|
||||
/** 文本颜色; 默认: "#000" */
|
||||
color?: string;
|
||||
/** 字体; 默认: "serial" */
|
||||
fontFamily?: string;
|
||||
/** 字号(单位rpx); 默认: 30 rpx */
|
||||
fontSize?: number;
|
||||
/** 字重; 默认: "normal" 可选项: "bold" */
|
||||
fontWeight?: string;
|
||||
/** 字型 默认: "normal" 可选项: "italic" */
|
||||
fontStyle?: string;
|
||||
/** 文本块的宽度,不能为空 */
|
||||
width: number;
|
||||
/** 行高; 默认取当前文字行高 */
|
||||
lineHeight?: number;
|
||||
/** 文本最大行数,超出即显示省略号; 默认3行 */
|
||||
lineClamp?: number;
|
||||
/** 文本内容 */
|
||||
content: string;
|
||||
}
|
||||
/** 绘制二维码信息 */
|
||||
interface PainterQrCodeInfo extends PainterItemSite {
|
||||
/** 绘制换行文本元素 */
|
||||
type: "qr-code";
|
||||
/** 二维码尺寸 */
|
||||
size: number;
|
||||
/** 二维码内容 */
|
||||
content: string;
|
||||
/** 边距,二维码实际尺寸会根据所设边距值进行缩放调整(默认:5) */
|
||||
margin?: number;
|
||||
/** 背景色(默认:'#ffffff')*/
|
||||
backgroundColor?: string;
|
||||
/** 前景色(默认:'#000000') */
|
||||
foregroundColor?: string;
|
||||
}
|
||||
export interface PainterContainerOption extends PainterItemSize {
|
||||
/** 绘制项的数组 */
|
||||
contents: Array<PainterImageInfo | PainterRectInfo | PainterTextInfo | PainterLineFeedTextInfo | PainterQrCodeInfo>;
|
||||
}
|
||||
declare const _default: DrawPosterUseOpts;
|
||||
export default _default;
|
|
@ -0,0 +1,73 @@
|
|||
export default {
|
||||
name: 'painter',
|
||||
handle: (dp, option) => {
|
||||
dp.canvas.width = option.width;
|
||||
dp.canvas.height = option.height;
|
||||
dp.draw(async (ctx) => {
|
||||
for (let i = 0; i < option.contents.length; i++) {
|
||||
ctx.save();
|
||||
const drawInfo = option.contents[i];
|
||||
const { left = 0, top = 0 } = drawInfo;
|
||||
if (drawInfo.type === 'rect') {
|
||||
ctx.fillStyle = drawInfo.background || '#000000';
|
||||
ctx.fillRoundRect(left, top, drawInfo.width, drawInfo.height, drawInfo.radius || 0);
|
||||
}
|
||||
if (drawInfo.type === 'image') {
|
||||
await ctx.drawImageFit(drawInfo.src, {
|
||||
objectFit: drawInfo.objectFit || 'cover',
|
||||
intrinsicPosition: drawInfo.position || ['center', 'center'],
|
||||
specifiedPosition: [left, top],
|
||||
specifiedSize: {
|
||||
width: drawInfo.width,
|
||||
height: drawInfo.height
|
||||
},
|
||||
radius: drawInfo.radius
|
||||
});
|
||||
}
|
||||
if (drawInfo.type === 'text') {
|
||||
ctx.fillStyle = drawInfo.color || '#000000';
|
||||
ctx.font = `\
|
||||
${drawInfo.fontStyle || 'normal'} \
|
||||
${drawInfo.fontWeight || 'normal'} \
|
||||
${drawInfo.fontSize || 30} \
|
||||
${drawInfo.fontFamily || 'serial'}\
|
||||
`;
|
||||
ctx.fillText(drawInfo.content, left, top, drawInfo.width);
|
||||
}
|
||||
if (drawInfo.type === 'line-feed-text') {
|
||||
ctx.fillStyle = drawInfo.color || '#000000';
|
||||
ctx.font = `\
|
||||
${drawInfo.fontStyle || 'normal'} \
|
||||
${drawInfo.fontWeight || 'normal'} \
|
||||
${drawInfo.fontSize || 30} \
|
||||
${drawInfo.fontFamily || 'serial'}\
|
||||
`;
|
||||
ctx.fillWarpText({
|
||||
x: drawInfo.left,
|
||||
y: drawInfo.top,
|
||||
layer: drawInfo.lineClamp,
|
||||
lineHeight: drawInfo.lineHeight,
|
||||
maxWidth: drawInfo.width,
|
||||
text: drawInfo.content
|
||||
});
|
||||
}
|
||||
if (drawInfo.type === 'qr-code') {
|
||||
if (typeof ctx.drawQrCode !== 'function') {
|
||||
console.error('--- 当前未引入qr-code扩展, 将自动省略该二维码绘制 ---');
|
||||
return false;
|
||||
}
|
||||
ctx.drawQrCode({
|
||||
x: left,
|
||||
y: top,
|
||||
size: drawInfo.size,
|
||||
text: drawInfo.content,
|
||||
margin: drawInfo.margin || 5,
|
||||
backgroundColor: drawInfo.backgroundColor || '#ffffff',
|
||||
foregroundColor: drawInfo.foregroundColor || '#000000',
|
||||
});
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
declare const _default: {
|
||||
name: string;
|
||||
handle: any;
|
||||
errorCorrectLevel: any;
|
||||
};
|
||||
export default _default;
|