commit message

master
Chopper 2021-05-13 11:03:32 +08:00
commit 23804939eb
2158 changed files with 149684 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# OSX
#
.DS_Store
#Intellij idea
.idea/
/idea/
.vscode/
/unpackage/
.hbuilderx/launch.json

11
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,11 @@
{ // launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version": "0.0",
"configurations": [{
"type": "uniCloud",
"default": {
"launchtype": "remote"
}
}
]
}

15
.vscode/launch.json vendored Normal file
View File

@ -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}"
}
]
}

113
App.vue Normal file
View File

@ -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");
},
});
}
},
// h5app
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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
CustomStoryboard/1@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
CustomStoryboard/1@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
CustomStoryboard/2@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
CustomStoryboard/2@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -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>

View File

@ -0,0 +1 @@
qSyvBPhDsPdxvOhC

114
api/address.js Normal file
View File

@ -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,
});
}

207
api/after-sale.js Normal file
View File

@ -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,
});
}

30
api/article.js Normal file
View File

@ -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,
});
}

42
api/common.js Normal file
View File

@ -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';

61
api/connect.js Normal file
View 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
});
}

215
api/goods.js Normal file
View File

@ -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,
})
}

62
api/home.js Normal file
View File

@ -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",
});
}

76
api/login.js Normal file
View File

@ -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",
});
}

438
api/members.js Normal file
View File

@ -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
})
}

81
api/message.js Normal file
View File

@ -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,
});
}

115
api/order.js Normal file
View File

@ -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}
});
}

111
api/passport.js Normal file
View File

@ -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
})
}

28
api/point.js Normal file
View File

@ -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,
});
}

82
api/promotions.js Normal file
View File

@ -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,
});
}

136
api/safe.js Normal file
View File

@ -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
})
}

29
api/store.js Normal file
View File

@ -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,
});
}

283
api/trade.js Normal file
View File

@ -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,
});
}

View File

@ -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>

52
components/empty.vue Normal file

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -0,0 +1 @@
### 说明 https://ext.dcloud.net.cn/plugin?id=3237

View File

@ -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>

View File

@ -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,swipertabbar
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>

View File

@ -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>

View File

@ -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,
},
],
};
},
// typegoods,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>

View File

@ -0,0 +1,8 @@
.share-btn {
background: none;
font-size: 24rpx;
color: #666;
display: flex;
flex-direction: column;
align-items: center;
}

View File

@ -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">&#xe851;</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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"
}

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
}

View File

@ -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-loadingloading-loadingnoMore-
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>

View File

@ -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: {
// 1s100px
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>

View File

@ -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()
}
}
}
}

View File

@ -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],
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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: bottomcenter
// 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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|successwarningerrorroyal] 颜色类型
* @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: {
// defaultprimarysuccesswarningerrorroyal
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>

View File

@ -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>

View File

@ -0,0 +1,184 @@
/*
Animation
ColorUI by 201932619: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)
}
}

File diff suppressed because one or more lines are too long

View File

@ -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>

33
config/api.js Normal file
View File

@ -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,
};

9
config/config.js Normal file
View File

@ -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 查看
};

View File

@ -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>

View File

@ -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);
}
}

94
hybrid/html/error.html Normal file
View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -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}));

BIN
icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

31
js_sdk/amap-wx.130.js Normal file
View File

@ -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;

18
js_sdk/h5-copy/h5-copy.js Normal file
View File

@ -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
}

63
js_sdk/lili-pay/wx-pay.js Normal file
View File

@ -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;

38
js_sdk/u-draw-poster/draw-poster.d.ts vendored Normal file
View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
},
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseOpts } from '../../utils/interface';
export * from './gcanvas';
declare const _default: DrawPosterUseOpts;
export default _default;

View File

@ -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 {};

View File

@ -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;

View File

@ -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;
}
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 等待绘制图片原型方法 */
export default _default;

View File

@ -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;
}
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 绘制圆角图片原型方法 */
export default _default;

View File

@ -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;
}
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 绘制填充圆角矩形方法 */
export default _default;

View File

@ -0,0 +1,7 @@
/** 绘制填充圆角矩形方法 */
export default {
name: 'fillRoundRect',
handle: (canvas, ctx, x, y, w, h, r) => {
ctx.roundRect(x, y, w, h, r, true);
}
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 绘制换行字体原型方法 */
export default _default;

View File

@ -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;
}
};

View File

@ -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";

View File

@ -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";

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 绘制圆角矩形原型方法 */
export default _default;

View File

@ -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();
}
};

View File

@ -0,0 +1,4 @@
import { DrawPosterUseCtxOpts } from '../../utils/interface';
declare const _default: DrawPosterUseCtxOpts;
/** 绘制填充圆角矩形方法 */
export default _default;

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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();
}
});
}
};

View File

@ -0,0 +1,6 @@
declare const _default: {
name: string;
handle: any;
errorCorrectLevel: any;
};
export default _default;

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