Browse Source

路径

dev_des
1054425342@qq.com 2 months ago
parent
commit
7f3c089597
  1. 173
      pages.json
  2. 8
      pages/index/iSoul.vue
  3. 0
      subPackages/orderQy/confrim.vue
  4. 818
      subPackages/orderQy/detail.vue
  5. 739
      subPackages/orderQy/list.vue
  6. 20
      uni_modules/uni-icons/changelog.md
  7. 91
      uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
  8. 48
      uni_modules/uni-icons/components/uni-icons/uni-icons.vue
  9. 63
      uni_modules/uni-icons/components/uni-icons/uniicons.css
  10. BIN
      uni_modules/uni-icons/components/uni-icons/uniicons.ttf
  11. 664
      uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
  12. 649
      uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
  13. 29
      uni_modules/uni-icons/package.json
  14. 11
      uni_modules/uni-transition/changelog.md
  15. 85
      uni_modules/uni-transition/components/uni-transition/createAnimation.js
  16. 643
      uni_modules/uni-transition/components/uni-transition/uni-transition.vue
  17. 105
      uni_modules/uni-transition/package.json

173
pages.json

@ -10,35 +10,30 @@
"path": "pages/index/index",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "CGC-ICH"
}
},
{
"path": "pages/index/readingBody",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "阅读体"
}
},
{
"path": "pages/index/sensoryStore",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "有感商店"
}
},
{
"path": "pages/index/intelligentAgent",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "智能体"
}
},
{
"path": "pages/index/iSoul",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "iSoul"
}
},
{
@ -48,13 +43,13 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/index/timeShopBank",
"style": {
"navigationBarTitleText": "时间银行",
"navigationStyle": "custom"
}
}
{
"path": "pages/index/timeShopBank",
"style": {
"navigationBarTitleText": "时间银行",
"navigationStyle": "custom"
}
}
],
"subPackages": [
{
@ -184,24 +179,42 @@
"navigationBarTitleText": "搜索"
}
},
{
"path": "equityGoods/index",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/list",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/detail",
"style": {
"navigationBarTitleText": "权益商品"
}
}
{
"path": "equityGoods/index",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/list",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/detail",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "orderQy/list",
"style": {
"navigationBarTitleText": "权益商品订单"
}
},
{
"path": "orderQy/detail",
"style": {
"navigationBarTitleText": "订单详情"
}
},
{
"path": "orderQy/confrim",
"style": {
"navigationBarTitleText": "确认订单"
}
}
]
},
{
@ -326,7 +339,6 @@
"navigationStyle": "custom"
}
}
]
},
{
@ -476,56 +488,55 @@
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/chapter4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/secBuy",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/first",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/second",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/third",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/fourth",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
}
{
"path": "chapter4/chapter4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/secBuy",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/first",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/second",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/third",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/fourth",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
}
]
}
],

8
pages/index/iSoul.vue

@ -380,22 +380,22 @@ export default {
switch (action) {
case "待核销":
uni.navigateTo({
url: "/subPackages/order/trades?status=PAYMENT_SUCCESSFULLY",
url: "/subPackages/orderQy/list?status=PAYMENT_SUCCESSFULLY",
});
break;
case "待发货":
uni.navigateTo({
url: "/subPackages/order/trades?status=POST",
url: "/subPackages/orderQy/list?status=POST",
});
break;
case "退货/退款":
uni.navigateTo({
url: "/subPackages/order/trades?status=WAIT_REFUND",
url: "/subPackages/orderQy/list?status=WAIT_REFUND",
});
break;
case "历史记录":
uni.navigateTo({
url: "/subPackages/order/trades",
url: "/subPackages/orderQy/list",
});
break;
}

0
subPackages/orderQy/confrim.vue

818
subPackages/orderQy/detail.vue

@ -0,0 +1,818 @@
<template>
<view class="order-detail-container">
<!-- 订单状态 -->
<view class="status-section">
<view class="status-icon">
<image
:src="getStatusIcon(orderDetail.status)"
mode="aspectFit"
class="icon"
/>
</view>
<view class="status-info">
<text class="status-text">{{ getStatusText(orderDetail.status) }}</text>
<text class="status-desc">{{ getStatusDesc(orderDetail.status) }}</text>
</view>
</view>
<!-- 订单信息 -->
<view class="order-info-section">
<view class="section-title">订单信息</view>
<view class="info-item">
<text class="label">订单号</text>
<text class="value">{{ orderDetail.orderNo }}</text>
<text class="copy-btn" @click="copyOrderNo">复制</text>
</view>
<view class="info-item">
<text class="label">下单时间</text>
<text class="value">{{ formatTime(orderDetail.createTime) }}</text>
</view>
<view class="info-item" v-if="orderDetail.payTime">
<text class="label">付款时间</text>
<text class="value">{{ formatTime(orderDetail.payTime) }}</text>
</view>
<view class="info-item">
<text class="label">支付方式</text>
<text class="value">{{ orderDetail.payMethod || "微信支付" }}</text>
</view>
</view>
<!-- 权益商品包 -->
<view class="package-section">
<view class="section-title">权益商品包</view>
<view class="package-name">{{ orderDetail.packageName }}</view>
</view>
<!-- 商品列表 -->
<view class="goods-section">
<view class="section-title">商品清单</view>
<view
class="goods-item"
v-for="goods in orderDetail.goodsList"
:key="goods.id"
>
<image class="goods-image" :src="goods.image" mode="aspectFill" />
<view class="goods-info">
<text class="goods-name">{{ goods.name }}</text>
<text class="goods-type">{{ getGoodsTypeName(goods.type) }}</text>
<text class="goods-spec" v-if="goods.spec">{{ goods.spec }}</text>
</view>
<view class="goods-price">
<text class="price">¥{{ goods.price }}</text>
<text class="quantity">×{{ goods.quantity || 1 }}</text>
</view>
</view>
</view>
<!-- 权益码信息 -->
<view class="equity-section" v-if="orderDetail.status !== 0">
<view class="section-title">权益码信息</view>
<view class="equity-card" @click="showEquityCode">
<view class="equity-info">
<text class="equity-label">权益码</text>
<text class="equity-code">{{ orderDetail.equityCode }}</text>
</view>
<view class="equity-action">
<text class="view-qr">查看二维码</text>
</view>
</view>
</view>
<!-- 费用明细 -->
<view class="cost-section">
<view class="section-title">费用明细</view>
<view class="cost-item">
<text class="cost-label">商品总价</text>
<text class="cost-value">¥{{ orderDetail.goodsAmount }}</text>
</view>
<view class="cost-item" v-if="orderDetail.discountAmount > 0">
<text class="cost-label">优惠金额</text>
<text class="cost-value discount"
>-¥{{ orderDetail.discountAmount }}</text
>
</view>
<view class="cost-item total">
<text class="cost-label">实付金额</text>
<text class="cost-value">¥{{ orderDetail.totalAmount }}</text>
</view>
</view>
<!-- 收货信息 -->
<view class="address-section" v-if="hasPhysicalGoods">
<view class="section-title">收货信息</view>
<view class="address-info" v-if="orderDetail.address">
<view class="receiver-info">
<text class="receiver-name">{{ orderDetail.address.name }}</text>
<text class="receiver-phone">{{ orderDetail.address.phone }}</text>
</view>
<text class="receiver-address">{{
orderDetail.address.fullAddress
}}</text>
</view>
<view class="no-address" v-else>
<text>该订单无需收货地址</text>
</view>
</view>
<!-- 底部操作 -->
<view class="bottom-actions" v-if="showBottomActions">
<button
class="action-btn secondary"
v-if="orderDetail.status === 0"
@click="cancelOrder"
>
取消订单
</button>
<button
class="action-btn primary"
v-if="orderDetail.status === 0"
@click="payOrder"
>
立即支付
</button>
<button
class="action-btn primary"
v-if="orderDetail.status === 3"
@click="buyAgain"
>
再次购买
</button>
</view>
<!-- 权益码弹窗 -->
<view
class="equity-popup-mask"
v-if="showEquityPopup"
@click="closeEquityPopup"
>
<view class="equity-popup" @click.stop>
<view class="popup-header">
<text class="popup-title">权益码</text>
<text class="popup-close" @click="closeEquityPopup">×</text>
</view>
<view class="popup-content">
<!-- 二维码 -->
<view class="qrcode-container">
<image
class="qrcode-image"
:src="orderDetail.qrcode"
mode="aspectFit"
/>
</view>
<!-- 编号串码 -->
<view class="code-container">
<text class="code-label">权益码</text>
<text class="code-value" @longpress="copyEquityCode">{{
orderDetail.equityCode
}}</text>
</view>
<text class="code-tip">长按编号可复制</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
orderId: "",
showEquityPopup: false,
orderDetail: {
id: "",
orderNo: "",
status: 0,
packageName: "",
goodsList: [],
totalAmount: "0.00",
goodsAmount: "0.00",
discountAmount: "0.00",
createTime: "",
payTime: "",
payMethod: "",
equityCode: "",
qrcode: "",
address: null,
},
};
},
computed: {
//
hasPhysicalGoods() {
return this.orderDetail.goodsList.some((goods) => goods.type === 2);
},
//
showBottomActions() {
return [0, 3].includes(this.orderDetail.status);
},
},
onLoad(options) {
if (options.id) {
this.orderId = options.id;
this.loadOrderDetail();
}
},
methods: {
//
async loadOrderDetail() {
try {
uni.showLoading({ title: "加载中..." });
const res = await this.getOrderDetail(this.orderId);
this.orderDetail = res.data;
} catch (error) {
console.error("加载订单详情失败:", error);
uni.showToast({
title: "加载失败",
icon: "none",
});
} finally {
uni.hideLoading();
}
},
//
getStatusIcon(status) {
const iconMap = {
0: "/static/icon/status-pending.png",
1: "/static/icon/status-waiting.png",
2: "/static/icon/status-shipping.png",
3: "/static/icon/status-completed.png",
4: "/static/icon/status-refund.png",
};
return iconMap[status] || "/static/icon/status-default.png";
},
//
getStatusText(status) {
const statusMap = {
0: "待付款",
1: "待使用",
2: "待收货",
3: "已完成",
4: "售后/退款",
};
return statusMap[status] || "未知状态";
},
//
getStatusDesc(status) {
const descMap = {
0: "请尽快完成支付",
1: "权益商品可随时使用",
2: "商品正在配送中",
3: "订单已完成,感谢您的购买",
4: "退款处理中",
};
return descMap[status] || "";
},
//
getGoodsTypeName(type) {
const typeMap = {
1: "IP数字资产",
2: "IP资源商品",
3: "君道苏州门票",
};
return typeMap[type] || "未知类型";
},
//
copyOrderNo() {
uni.setClipboardData({
data: this.orderDetail.orderNo,
success: () => {
uni.showToast({
title: "订单号已复制",
icon: "success",
});
},
});
},
//
showEquityCode() {
this.showEquityPopup = true;
},
//
closeEquityPopup() {
this.showEquityPopup = false;
},
//
copyEquityCode() {
uni.setClipboardData({
data: this.orderDetail.equityCode,
success: () => {
uni.showToast({
title: "权益码已复制",
icon: "success",
});
},
});
},
//
async cancelOrder() {
const res = await uni.showModal({
title: "确认取消",
content: "确定要取消这个订单吗?",
});
if (res.confirm) {
try {
await this.cancelOrderApi(this.orderId);
uni.showToast({
title: "订单已取消",
icon: "success",
});
this.loadOrderDetail();
} catch (error) {
uni.showToast({
title: "取消失败",
icon: "none",
});
}
}
},
//
payOrder() {
//
uni.navigateTo({
url: `/pages/payment/index?orderId=${this.orderId}`,
});
},
//
buyAgain() {
//
uni.navigateTo({
url: `/subPackages/equityGoods/detail?id=${this.orderDetail.packageId}`,
});
},
//
formatTime(time) {
if (!time) return "";
const date = new Date(time);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")} ${String(
date.getHours()
).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
},
// API -
async getOrderDetail(orderId) {
// API
return new Promise((resolve) => {
setTimeout(() => {
const mockData = {
code: 200,
data: {
id: orderId,
orderNo: "EQ202401011234567",
status: 1,
packageName: "Epic Soul限定权益包",
packageId: "pkg001",
totalAmount: "249.00",
goodsAmount: "299.00",
discountAmount: "50.00",
createTime: "2024-01-01 12:00:00",
payTime: "2024-01-01 12:05:00",
payMethod: "微信支付",
equityCode: "EPIC2024010112345",
qrcode: "/static/image/qrcode-sample.png",
goodsList: [
{
id: 1,
name: "数字藏品-桃子系列",
type: 1,
price: "99.00",
quantity: 1,
image: "/static/image/goods1.jpg",
spec: "限量版",
},
{
id: 2,
name: "文创周边产品",
type: 2,
price: "150.00",
quantity: 1,
image: "/static/image/goods2.jpg",
spec: "桃花主题",
},
{
id: 3,
name: "君道苏州体验门票",
type: 3,
price: "50.00",
quantity: 1,
image: "/static/image/goods3.jpg",
spec: "成人票",
},
],
address: {
name: "张三",
phone: "138****8888",
fullAddress: "江苏省苏州市工业园区某某街道某某小区1号楼101室",
},
},
};
resolve(mockData);
}, 500);
});
},
// API -
async cancelOrderApi(orderId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ code: 200, message: "取消成功" });
}, 500);
});
},
},
};
</script>
<style lang="scss" scoped>
.order-detail-container {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 140rpx;
}
//
.status-section {
background-color: #fff;
padding: 40rpx 30rpx;
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.status-icon {
margin-right: 30rpx;
.icon {
width: 80rpx;
height: 80rpx;
}
}
.status-info {
flex: 1;
}
.status-text {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
}
.status-desc {
font-size: 26rpx;
color: #666;
}
//
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
}
//
.order-info-section,
.package-section,
.goods-section,
.equity-section,
.cost-section,
.address-section {
background-color: #fff;
padding: 30rpx;
margin-bottom: 20rpx;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
.label {
font-size: 28rpx;
color: #666;
width: 160rpx;
}
.value {
flex: 1;
font-size: 28rpx;
color: #333;
}
.copy-btn {
font-size: 24rpx;
color: #007aff;
padding: 8rpx 16rpx;
border: 1px solid #007aff;
border-radius: 20rpx;
}
//
.package-name {
font-size: 28rpx;
color: #333;
background-color: #f8f9fa;
padding: 20rpx;
border-radius: 12rpx;
}
//
.goods-item {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
.goods-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
margin-right: 20rpx;
}
.goods-info {
flex: 1;
margin-right: 20rpx;
}
.goods-name {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods-type {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.goods-spec {
font-size: 24rpx;
color: #666;
}
.goods-price {
text-align: right;
}
.price {
display: block;
font-size: 28rpx;
color: #ff4757;
font-weight: bold;
margin-bottom: 5rpx;
}
.quantity {
font-size: 24rpx;
color: #999;
}
//
.equity-card {
display: flex;
align-items: center;
padding: 30rpx;
background-color: #f8f9fa;
border-radius: 12rpx;
border: 2rpx dashed #007aff;
}
.equity-info {
flex: 1;
}
.equity-label {
display: block;
font-size: 26rpx;
color: #666;
margin-bottom: 10rpx;
}
.equity-code {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.equity-action {
.view-qr {
font-size: 26rpx;
color: #007aff;
}
}
//
.cost-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
&.total {
padding-top: 20rpx;
border-top: 1px solid #f0f0f0;
.cost-label,
.cost-value {
font-size: 32rpx;
font-weight: bold;
}
}
}
.cost-label {
font-size: 28rpx;
color: #666;
}
.cost-value {
font-size: 28rpx;
color: #333;
&.discount {
color: #ff4757;
}
}
//
.receiver-info {
display: flex;
align-items: center;
margin-bottom: 15rpx;
}
.receiver-name {
font-size: 28rpx;
color: #333;
font-weight: bold;
margin-right: 20rpx;
}
.receiver-phone {
font-size: 28rpx;
color: #666;
}
.receiver-address {
font-size: 26rpx;
color: #666;
line-height: 1.5;
}
.no-address {
text-align: center;
padding: 30rpx;
color: #999;
}
//
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 20rpx 30rpx;
border-top: 1px solid #eee;
display: flex;
gap: 20rpx;
}
.action-btn {
flex: 1;
height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
border: none;
&.secondary {
background-color: #f0f0f0;
color: #666;
}
&.primary {
background-color: #007aff;
color: #fff;
}
}
//
.equity-popup-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.equity-popup {
width: 600rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.popup-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.popup-close {
font-size: 40rpx;
color: #999;
}
.popup-content {
padding: 40rpx 30rpx;
text-align: center;
}
.qrcode-container {
margin-bottom: 40rpx;
}
.qrcode-image {
width: 300rpx;
height: 300rpx;
border: 1px solid #eee;
border-radius: 12rpx;
}
.code-container {
margin-bottom: 20rpx;
}
.code-label {
font-size: 28rpx;
color: #666;
margin-right: 10rpx;
}
.code-value {
font-size: 28rpx;
color: #333;
font-weight: bold;
background-color: #f8f9fa;
padding: 8rpx 16rpx;
border-radius: 8rpx;
}
.code-tip {
font-size: 24rpx;
color: #999;
}
</style>

739
subPackages/orderQy/list.vue

@ -0,0 +1,739 @@
<template>
<view class="order-list-container">
<!-- Tab切换 -->
<view class="tab-container">
<view
class="tab-item"
:class="{ active: currentTab === index }"
v-for="(tab, index) in tabs"
:key="index"
@click="switchTab(index)"
>
<text class="tab-text">{{ tab.name }}</text>
</view>
</view>
<!-- 订单列表 -->
<scroll-view
class="order-scroll"
scroll-y
@scrolltolower="loadMore"
refresher-enabled
:refresher-triggered="refresherTriggered"
@refresherrefresh="onRefresh"
>
<!-- 订单项 -->
<view class="order-item" v-for="order in orderList" :key="order.id">
<!-- 订单头部 -->
<view class="order-header">
<text class="order-number">订单号{{ order.orderNo }}</text>
<text class="order-status" :class="[getStatusClass(order.status)]">{{
getStatusText(order.status)
}}</text>
</view>
<!-- 权益商品包名 -->
<view class="package-name">
<text>{{ order.packageName }}</text>
</view>
<!-- 商品列表 -->
<view class="goods-list">
<view
class="goods-item"
v-for="goods in order.goodsList"
:key="goods.id"
>
<image class="goods-image" :src="goods.image" mode="aspectFill" />
<view class="goods-info">
<text class="goods-name">{{ goods.name }}</text>
<text class="goods-type">{{ getGoodsTypeName(goods.type) }}</text>
<text class="goods-price">¥{{ goods.price }}</text>
</view>
<view class="goods-action">
<button
class="action-btn"
:class="[getActionBtnClass(goods.type)]"
@click="handleGoodsAction(goods)"
>
{{ getActionBtnText(goods.type) }}
</button>
</view>
</view>
</view>
<!-- 订单底部 -->
<view class="order-footer">
<view class="order-info">
<text class="order-time">{{ formatTime(order.createTime) }}</text>
<text class="order-total">总计¥{{ order.totalAmount }}</text>
</view>
<view class="order-actions">
<button
class="equity-code-btn"
@click="showEquityCode(order)"
v-if="order.status !== 0"
>
权益码
</button>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="orderList.length === 0 && !loading">
<image
class="empty-image"
src="/static/image/empty-order.png"
mode="aspectFit"
/>
<text class="empty-text">暂无订单</text>
</view>
<!-- 加载更多 -->
<view class="load-more" v-if="hasMore && orderList.length > 0">
<text class="load-text">{{
loading ? "加载中..." : "上拉加载更多"
}}</text>
</view>
<!-- 没有更多数据 -->
<view class="no-more" v-if="!hasMore && orderList.length > 0">
<text class="no-more-text">没有更多数据了</text>
</view>
</scroll-view>
<!-- 权益码弹窗 -->
<uni-popup ref="equityPopup" type="center">
<view class="equity-popup">
<view class="popup-header">
<text class="popup-title">权益码</text>
<text class="popup-close" @click="closeEquityPopup">×</text>
</view>
<view class="popup-content">
<!-- 二维码 -->
<view class="qrcode-container">
<image
class="qrcode-image"
:src="currentEquity.qrcode"
mode="aspectFit"
/>
</view>
<!-- 编号串码 -->
<view class="code-container">
<text class="code-label">权益码</text>
<text class="code-value" @longpress="copyCode">{{
currentEquity.code
}}</text>
</view>
<text class="code-tip">长按编号可复制</text>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
currentTab: 0,
tabs: [
{ name: "全部", status: "" },
{ name: "待使用", status: 1 },
{ name: "待收货", status: 2 },
{ name: "已完成", status: 3 },
{ name: "售后/退款", status: 4 },
],
orderList: [],
loading: false,
refresherTriggered: false,
hasMore: true,
currentPage: 1,
pageSize: 10,
currentEquity: {
qrcode: "",
code: "",
},
};
},
onLoad() {
this.loadOrderList();
},
methods: {
// Tab
switchTab(index) {
this.currentTab = index;
this.resetList();
this.loadOrderList();
},
//
resetList() {
this.orderList = [];
this.currentPage = 1;
this.hasMore = true;
},
//
async loadOrderList() {
if (this.loading || !this.hasMore) return;
this.loading = true;
try {
const params = {
page: this.currentPage,
pageSize: this.pageSize,
status: this.tabs[this.currentTab].status,
};
// API
const res = await this.getOrderList(params);
if (this.currentPage === 1) {
this.orderList = res.data.list || [];
} else {
this.orderList = [...this.orderList, ...(res.data.list || [])];
}
this.hasMore = res.data.list.length === this.pageSize;
this.currentPage++;
} catch (error) {
console.error("加载订单列表失败:", error);
uni.showToast({
title: "加载失败",
icon: "none",
});
} finally {
this.loading = false;
this.refresherTriggered = false;
}
},
//
loadMore() {
this.loadOrderList();
},
//
onRefresh() {
this.refresherTriggered = true;
this.resetList();
this.loadOrderList();
},
//
getStatusText(status) {
const statusMap = {
0: "待付款",
1: "待使用",
2: "待收货",
3: "已完成",
4: "售后/退款",
};
return statusMap[status] || "未知";
},
//
getStatusClass(status) {
const classMap = {
0: "status-pending",
1: "status-waiting",
2: "status-shipping",
3: "status-completed",
4: "status-refund",
};
return classMap[status] || "";
},
//
getGoodsTypeName(type) {
const typeMap = {
1: "IP数字资产",
2: "IP资源商品",
3: "君道苏州门票",
};
return typeMap[type] || "未知类型";
},
//
getActionBtnText(type) {
const textMap = {
1: "查看",
2: "预约发货",
3: "去使用",
};
return textMap[type] || "操作";
},
//
getActionBtnClass(type) {
const classMap = {
1: "btn-view",
2: "btn-reserve",
3: "btn-use",
};
return classMap[type] || "";
},
//
handleGoodsAction(goods) {
switch (goods.type) {
case 1: // IP -
this.viewDigitalAsset(goods);
break;
case 2: // IP -
this.reserveDelivery(goods);
break;
case 3: // - 使
this.useTicket(goods);
break;
}
},
//
viewDigitalAsset(goods) {
//
uni.showToast({
title: "查看数字资产",
icon: "none",
});
},
//
reserveDelivery(goods) {
//
uni.showToast({
title: "预约发货",
icon: "none",
});
},
// 使
useTicket(goods) {
// 使
uni.showToast({
title: "使用门票",
icon: "none",
});
},
//
showEquityCode(order) {
this.currentEquity = {
qrcode: order.qrcode || "/static/image/default-qrcode.png",
code: order.equityCode || "EQUITY123456789",
};
this.$refs.equityPopup.open();
},
//
closeEquityPopup() {
this.$refs.equityPopup.close();
},
//
copyCode() {
uni.setClipboardData({
data: this.currentEquity.code,
success: () => {
uni.showToast({
title: "已复制到剪贴板",
icon: "success",
});
},
});
},
//
formatTime(time) {
if (!time) return "";
const date = new Date(time);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")} ${String(
date.getHours()
).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
},
// API -
async getOrderList(params) {
// API
return new Promise((resolve) => {
setTimeout(() => {
const mockData = {
code: 200,
data: {
list: [
{
id: 1,
orderNo: "EQ202401011234567",
packageName: "Epic Soul限定权益包",
status: 1,
totalAmount: "299.00",
createTime: "2024-01-01 12:00:00",
qrcode: "/static/image/qrcode-sample.png",
equityCode: "EPIC2024010112345",
goodsList: [
{
id: 1,
name: "数字藏品-桃子系列",
type: 1,
price: "99.00",
image: "/static/image/goods1.jpg",
},
{
id: 2,
name: "文创周边产品",
type: 2,
price: "150.00",
image: "/static/image/goods2.jpg",
},
{
id: 3,
name: "君道苏州体验门票",
type: 3,
price: "50.00",
image: "/static/image/goods3.jpg",
},
],
},
//
],
},
};
resolve(mockData);
}, 1000);
});
},
},
};
</script>
<style lang="scss" scoped>
.order-list-container {
min-height: 100vh;
background-color: #f5f5f5;
}
// Tab
.tab-container {
display: flex;
background-color: #fff;
border-bottom: 1px solid #eee;
position: sticky;
top: 0;
z-index: 10;
}
.tab-item {
flex: 1;
padding: 30rpx 0;
text-align: center;
position: relative;
&.active {
.tab-text {
color: #007aff;
font-weight: bold;
}
&::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: #007aff;
border-radius: 2rpx;
}
}
}
.tab-text {
font-size: 28rpx;
color: #333;
}
//
.order-scroll {
height: calc(100vh - 120rpx);
padding: 20rpx;
}
.order-item {
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 20rpx;
overflow: hidden;
}
//
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
font-size: 28rpx;
color: #333;
}
.order-status {
font-size: 26rpx;
padding: 8rpx 16rpx;
border-radius: 20rpx;
&.status-pending {
background-color: #fff3cd;
color: #856404;
}
&.status-waiting {
background-color: #d4edda;
color: #155724;
}
&.status-shipping {
background-color: #cce5ff;
color: #004085;
}
&.status-completed {
background-color: #e2e3e5;
color: #383d41;
}
&.status-refund {
background-color: #f8d7da;
color: #721c24;
}
}
//
.package-name {
padding: 20rpx 30rpx;
background-color: #f8f9fa;
border-bottom: 1px solid #f0f0f0;
text {
font-size: 26rpx;
color: #666;
}
}
//
.goods-list {
padding: 0 30rpx;
}
.goods-item {
display: flex;
align-items: center;
padding: 30rpx 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
.goods-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
margin-right: 20rpx;
}
.goods-info {
flex: 1;
margin-right: 20rpx;
}
.goods-name {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods-type {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 10rpx;
}
.goods-price {
font-size: 28rpx;
color: #ff4757;
font-weight: bold;
}
.goods-action {
.action-btn {
padding: 12rpx 24rpx;
border-radius: 20rpx;
font-size: 24rpx;
border: none;
&.btn-view {
background-color: #007aff;
color: #fff;
}
&.btn-reserve {
background-color: #ff9500;
color: #fff;
}
&.btn-use {
background-color: #34c759;
color: #fff;
}
}
}
//
.order-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
background-color: #f8f9fa;
}
.order-info {
flex: 1;
}
.order-time {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 10rpx;
}
.order-total {
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.order-actions {
.equity-code-btn {
padding: 16rpx 32rpx;
background-color: #007aff;
color: #fff;
border-radius: 24rpx;
font-size: 26rpx;
border: none;
}
}
//
.empty-state {
text-align: center;
padding: 200rpx 0;
}
.empty-image {
width: 200rpx;
height: 200rpx;
margin-bottom: 30rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
//
.load-more,
.no-more {
text-align: center;
padding: 30rpx;
}
.load-text,
.no-more-text {
font-size: 26rpx;
color: #999;
}
//
.equity-popup {
width: 600rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.popup-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.popup-close {
font-size: 40rpx;
color: #999;
}
.popup-content {
padding: 40rpx 30rpx;
text-align: center;
}
.qrcode-container {
margin-bottom: 40rpx;
}
.qrcode-image {
width: 300rpx;
height: 300rpx;
border: 1px solid #eee;
border-radius: 12rpx;
}
.code-container {
margin-bottom: 20rpx;
}
.code-label {
font-size: 28rpx;
color: #666;
margin-right: 10rpx;
}
.code-value {
font-size: 28rpx;
color: #333;
font-weight: bold;
background-color: #f8f9fa;
padding: 8rpx 16rpx;
border-radius: 8rpx;
}
.code-tip {
font-size: 24rpx;
color: #999;
}
</style>

20
uni_modules/uni-icons/changelog.md

@ -1,3 +1,23 @@
## 2.0.10(2024-06-07)
- 优化 uni-app x 中,size 属性的类型
## 2.0.9(2024-01-12)
fix: 修复图标大小默认值错误的问题
## 2.0.8(2023-12-14)
- 修复 项目未使用 ts 情况下,打包报错的bug
## 2.0.7(2023-12-14)
- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug
## 2.0.6(2023-12-11)
- 优化 兼容老版本icon类型,如 top ,bottom 等
## 2.0.5(2023-12-11)
- 优化 兼容老版本icon类型,如 top ,bottom 等
## 2.0.4(2023-12-06)
- 优化 uni-app x 下示例项目图标排序
## 2.0.3(2023-12-06)
- 修复 nvue下引入组件报错的bug
## 2.0.2(2023-12-05)
-优化 size 属性支持单位
## 2.0.1(2023-12-05)
- 新增 uni-app x 支持定义图标
## 1.3.5(2022-01-24)
- 优化 size 属性可以传入不带单位的字符串数值
## 1.3.4(2022-01-24)

91
uni_modules/uni-icons/components/uni-icons/uni-icons.uvue

@ -0,0 +1,91 @@
<template>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
</template>
<script>
import { fontData, IconsDataItem } from './uniicons_file'
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number,String} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
</script>
<style scoped>
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
</style>

48
uni_modules/uni-icons/components/uni-icons/uni-icons.vue

@ -1,24 +1,28 @@
<template>
<!-- #ifdef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
<slot></slot>
</text>
<!-- #endif -->
</template>
<script>
import icons from './icons.js';
import { fontData } from './uniicons_file_vue.js';
const getVal = (val) => {
const reg = /^[0-9]*$/g
return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
}
return (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;
}
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
import iconUrl from './uniicons.ttf'
domModule.addRule('fontFace', {
'fontFamily': "uniicons",
'src': "url('"+iconUrl+"')"
'src': "url('" + iconUrl + "')"
});
// #endif
@ -34,7 +38,7 @@
*/
export default {
name: 'UniIcons',
emits:['click'],
emits: ['click'],
props: {
type: {
type: String,
@ -48,26 +52,36 @@
type: [Number, String],
default: 16
},
customPrefix:{
customPrefix: {
type: String,
default: ''
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {
icons: icons.glyphs
icons: fontData
}
},
computed:{
unicode(){
let code = this.icons.find(v=>v.font_class === this.type)
if(code){
return unescape(`%u${code.unicode}`)
computed: {
unicode() {
let code = this.icons.find(v => v.font_class === this.type)
if (code) {
return code.unicode
}
return ''
},
iconSize(){
iconSize() {
return getVal(this.size)
},
styleObj() {
if (this.fontFamily !== '') {
return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
}
return `color: ${this.color}; font-size: ${this.iconSize};`
}
},
methods: {
@ -81,9 +95,10 @@
<style lang="scss">
/* #ifndef APP-NVUE */
@import './uniicons.css';
@font-face {
font-family: uniicons;
src: url('./uniicons.ttf') format('truetype');
src: url('./uniicons.ttf');
}
/* #endif */
@ -92,5 +107,4 @@
text-decoration: none;
text-align: center;
}
</style>

63
uni_modules/uni-icons/components/uni-icons/uniicons.css

@ -1,3 +1,12 @@
.uniui-cart-filled:before {
content: "\e6d0";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-color:before {
content: "\e6cf";
}
@ -58,10 +67,6 @@
content: "\e6c3";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-fire-filled:before {
content: "\e6c5";
}
@ -82,6 +87,18 @@
content: "\e698";
}
.uniui-arrowthinleft:before {
content: "\e6d2";
}
.uniui-arrowthinup:before {
content: "\e6d3";
}
.uniui-arrowthindown:before {
content: "\e6d4";
}
.uniui-back:before {
content: "\e6b9";
}
@ -94,55 +111,43 @@
content: "\e6bb";
}
.uniui-arrowthinright:before {
content: "\e6bb";
}
.uniui-arrow-left:before {
content: "\e6bc";
}
.uniui-arrowthinleft:before {
content: "\e6bc";
}
.uniui-arrow-up:before {
content: "\e6bd";
}
.uniui-arrowthinup:before {
content: "\e6bd";
}
.uniui-arrow-down:before {
content: "\e6be";
}
.uniui-arrowthindown:before {
content: "\e6be";
.uniui-arrowthinright:before {
content: "\e6d1";
}
.uniui-bottom:before {
.uniui-down:before {
content: "\e6b8";
}
.uniui-arrowdown:before {
.uniui-bottom:before {
content: "\e6b8";
}
.uniui-right:before {
content: "\e6b5";
.uniui-arrowright:before {
content: "\e6d5";
}
.uniui-arrowright:before {
.uniui-right:before {
content: "\e6b5";
}
.uniui-top:before {
.uniui-up:before {
content: "\e6b6";
}
.uniui-arrowup:before {
.uniui-top:before {
content: "\e6b6";
}
@ -150,8 +155,8 @@
content: "\e6b7";
}
.uniui-arrowleft:before {
content: "\e6b7";
.uniui-arrowup:before {
content: "\e6d6";
}
.uniui-eye:before {
@ -638,10 +643,6 @@
content: "\e627";
}
.uniui-cart-filled:before {
content: "\e629";
}
.uniui-checkbox:before {
content: "\e62b";
}

BIN
uni_modules/uni-icons/components/uni-icons/uniicons.ttf

Binary file not shown.

664
uni_modules/uni-icons/components/uni-icons/uniicons_file.ts

@ -0,0 +1,664 @@
export type IconsData = {
id : string
name : string
font_family : string
css_prefix_text : string
description : string
glyphs : Array<IconsDataItem>
}
export type IconsDataItem = {
font_class : string
unicode : string
}
export const fontData = [
{
"font_class": "arrow-down",
"unicode": "\ue6be"
},
{
"font_class": "arrow-left",
"unicode": "\ue6bc"
},
{
"font_class": "arrow-right",
"unicode": "\ue6bb"
},
{
"font_class": "arrow-up",
"unicode": "\ue6bd"
},
{
"font_class": "auth",
"unicode": "\ue6ab"
},
{
"font_class": "auth-filled",
"unicode": "\ue6cc"
},
{
"font_class": "back",
"unicode": "\ue6b9"
},
{
"font_class": "bars",
"unicode": "\ue627"
},
{
"font_class": "calendar",
"unicode": "\ue6a0"
},
{
"font_class": "calendar-filled",
"unicode": "\ue6c0"
},
{
"font_class": "camera",
"unicode": "\ue65a"
},
{
"font_class": "camera-filled",
"unicode": "\ue658"
},
{
"font_class": "cart",
"unicode": "\ue631"
},
{
"font_class": "cart-filled",
"unicode": "\ue6d0"
},
{
"font_class": "chat",
"unicode": "\ue65d"
},
{
"font_class": "chat-filled",
"unicode": "\ue659"
},
{
"font_class": "chatboxes",
"unicode": "\ue696"
},
{
"font_class": "chatboxes-filled",
"unicode": "\ue692"
},
{
"font_class": "chatbubble",
"unicode": "\ue697"
},
{
"font_class": "chatbubble-filled",
"unicode": "\ue694"
},
{
"font_class": "checkbox",
"unicode": "\ue62b"
},
{
"font_class": "checkbox-filled",
"unicode": "\ue62c"
},
{
"font_class": "checkmarkempty",
"unicode": "\ue65c"
},
{
"font_class": "circle",
"unicode": "\ue65b"
},
{
"font_class": "circle-filled",
"unicode": "\ue65e"
},
{
"font_class": "clear",
"unicode": "\ue66d"
},
{
"font_class": "close",
"unicode": "\ue673"
},
{
"font_class": "closeempty",
"unicode": "\ue66c"
},
{
"font_class": "cloud-download",
"unicode": "\ue647"
},
{
"font_class": "cloud-download-filled",
"unicode": "\ue646"
},
{
"font_class": "cloud-upload",
"unicode": "\ue645"
},
{
"font_class": "cloud-upload-filled",
"unicode": "\ue648"
},
{
"font_class": "color",
"unicode": "\ue6cf"
},
{
"font_class": "color-filled",
"unicode": "\ue6c9"
},
{
"font_class": "compose",
"unicode": "\ue67f"
},
{
"font_class": "contact",
"unicode": "\ue693"
},
{
"font_class": "contact-filled",
"unicode": "\ue695"
},
{
"font_class": "down",
"unicode": "\ue6b8"
},
{
"font_class": "bottom",
"unicode": "\ue6b8"
},
{
"font_class": "download",
"unicode": "\ue68d"
},
{
"font_class": "download-filled",
"unicode": "\ue681"
},
{
"font_class": "email",
"unicode": "\ue69e"
},
{
"font_class": "email-filled",
"unicode": "\ue69a"
},
{
"font_class": "eye",
"unicode": "\ue651"
},
{
"font_class": "eye-filled",
"unicode": "\ue66a"
},
{
"font_class": "eye-slash",
"unicode": "\ue6b3"
},
{
"font_class": "eye-slash-filled",
"unicode": "\ue6b4"
},
{
"font_class": "fire",
"unicode": "\ue6a1"
},
{
"font_class": "fire-filled",
"unicode": "\ue6c5"
},
{
"font_class": "flag",
"unicode": "\ue65f"
},
{
"font_class": "flag-filled",
"unicode": "\ue660"
},
{
"font_class": "folder-add",
"unicode": "\ue6a9"
},
{
"font_class": "folder-add-filled",
"unicode": "\ue6c8"
},
{
"font_class": "font",
"unicode": "\ue6a3"
},
{
"font_class": "forward",
"unicode": "\ue6ba"
},
{
"font_class": "gear",
"unicode": "\ue664"
},
{
"font_class": "gear-filled",
"unicode": "\ue661"
},
{
"font_class": "gift",
"unicode": "\ue6a4"
},
{
"font_class": "gift-filled",
"unicode": "\ue6c4"
},
{
"font_class": "hand-down",
"unicode": "\ue63d"
},
{
"font_class": "hand-down-filled",
"unicode": "\ue63c"
},
{
"font_class": "hand-up",
"unicode": "\ue63f"
},
{
"font_class": "hand-up-filled",
"unicode": "\ue63e"
},
{
"font_class": "headphones",
"unicode": "\ue630"
},
{
"font_class": "heart",
"unicode": "\ue639"
},
{
"font_class": "heart-filled",
"unicode": "\ue641"
},
{
"font_class": "help",
"unicode": "\ue679"
},
{
"font_class": "help-filled",
"unicode": "\ue674"
},
{
"font_class": "home",
"unicode": "\ue662"
},
{
"font_class": "home-filled",
"unicode": "\ue663"
},
{
"font_class": "image",
"unicode": "\ue670"
},
{
"font_class": "image-filled",
"unicode": "\ue678"
},
{
"font_class": "images",
"unicode": "\ue650"
},
{
"font_class": "images-filled",
"unicode": "\ue64b"
},
{
"font_class": "info",
"unicode": "\ue669"
},
{
"font_class": "info-filled",
"unicode": "\ue649"
},
{
"font_class": "left",
"unicode": "\ue6b7"
},
{
"font_class": "link",
"unicode": "\ue6a5"
},
{
"font_class": "list",
"unicode": "\ue644"
},
{
"font_class": "location",
"unicode": "\ue6ae"
},
{
"font_class": "location-filled",
"unicode": "\ue6af"
},
{
"font_class": "locked",
"unicode": "\ue66b"
},
{
"font_class": "locked-filled",
"unicode": "\ue668"
},
{
"font_class": "loop",
"unicode": "\ue633"
},
{
"font_class": "mail-open",
"unicode": "\ue643"
},
{
"font_class": "mail-open-filled",
"unicode": "\ue63a"
},
{
"font_class": "map",
"unicode": "\ue667"
},
{
"font_class": "map-filled",
"unicode": "\ue666"
},
{
"font_class": "map-pin",
"unicode": "\ue6ad"
},
{
"font_class": "map-pin-ellipse",
"unicode": "\ue6ac"
},
{
"font_class": "medal",
"unicode": "\ue6a2"
},
{
"font_class": "medal-filled",
"unicode": "\ue6c3"
},
{
"font_class": "mic",
"unicode": "\ue671"
},
{
"font_class": "mic-filled",
"unicode": "\ue677"
},
{
"font_class": "micoff",
"unicode": "\ue67e"
},
{
"font_class": "micoff-filled",
"unicode": "\ue6b0"
},
{
"font_class": "minus",
"unicode": "\ue66f"
},
{
"font_class": "minus-filled",
"unicode": "\ue67d"
},
{
"font_class": "more",
"unicode": "\ue64d"
},
{
"font_class": "more-filled",
"unicode": "\ue64e"
},
{
"font_class": "navigate",
"unicode": "\ue66e"
},
{
"font_class": "navigate-filled",
"unicode": "\ue67a"
},
{
"font_class": "notification",
"unicode": "\ue6a6"
},
{
"font_class": "notification-filled",
"unicode": "\ue6c1"
},
{
"font_class": "paperclip",
"unicode": "\ue652"
},
{
"font_class": "paperplane",
"unicode": "\ue672"
},
{
"font_class": "paperplane-filled",
"unicode": "\ue675"
},
{
"font_class": "person",
"unicode": "\ue699"
},
{
"font_class": "person-filled",
"unicode": "\ue69d"
},
{
"font_class": "personadd",
"unicode": "\ue69f"
},
{
"font_class": "personadd-filled",
"unicode": "\ue698"
},
{
"font_class": "personadd-filled-copy",
"unicode": "\ue6d1"
},
{
"font_class": "phone",
"unicode": "\ue69c"
},
{
"font_class": "phone-filled",
"unicode": "\ue69b"
},
{
"font_class": "plus",
"unicode": "\ue676"
},
{
"font_class": "plus-filled",
"unicode": "\ue6c7"
},
{
"font_class": "plusempty",
"unicode": "\ue67b"
},
{
"font_class": "pulldown",
"unicode": "\ue632"
},
{
"font_class": "pyq",
"unicode": "\ue682"
},
{
"font_class": "qq",
"unicode": "\ue680"
},
{
"font_class": "redo",
"unicode": "\ue64a"
},
{
"font_class": "redo-filled",
"unicode": "\ue655"
},
{
"font_class": "refresh",
"unicode": "\ue657"
},
{
"font_class": "refresh-filled",
"unicode": "\ue656"
},
{
"font_class": "refreshempty",
"unicode": "\ue6bf"
},
{
"font_class": "reload",
"unicode": "\ue6b2"
},
{
"font_class": "right",
"unicode": "\ue6b5"
},
{
"font_class": "scan",
"unicode": "\ue62a"
},
{
"font_class": "search",
"unicode": "\ue654"
},
{
"font_class": "settings",
"unicode": "\ue653"
},
{
"font_class": "settings-filled",
"unicode": "\ue6ce"
},
{
"font_class": "shop",
"unicode": "\ue62f"
},
{
"font_class": "shop-filled",
"unicode": "\ue6cd"
},
{
"font_class": "smallcircle",
"unicode": "\ue67c"
},
{
"font_class": "smallcircle-filled",
"unicode": "\ue665"
},
{
"font_class": "sound",
"unicode": "\ue684"
},
{
"font_class": "sound-filled",
"unicode": "\ue686"
},
{
"font_class": "spinner-cycle",
"unicode": "\ue68a"
},
{
"font_class": "staff",
"unicode": "\ue6a7"
},
{
"font_class": "staff-filled",
"unicode": "\ue6cb"
},
{
"font_class": "star",
"unicode": "\ue688"
},
{
"font_class": "star-filled",
"unicode": "\ue68f"
},
{
"font_class": "starhalf",
"unicode": "\ue683"
},
{
"font_class": "trash",
"unicode": "\ue687"
},
{
"font_class": "trash-filled",
"unicode": "\ue685"
},
{
"font_class": "tune",
"unicode": "\ue6aa"
},
{
"font_class": "tune-filled",
"unicode": "\ue6ca"
},
{
"font_class": "undo",
"unicode": "\ue64f"
},
{
"font_class": "undo-filled",
"unicode": "\ue64c"
},
{
"font_class": "up",
"unicode": "\ue6b6"
},
{
"font_class": "top",
"unicode": "\ue6b6"
},
{
"font_class": "upload",
"unicode": "\ue690"
},
{
"font_class": "upload-filled",
"unicode": "\ue68e"
},
{
"font_class": "videocam",
"unicode": "\ue68c"
},
{
"font_class": "videocam-filled",
"unicode": "\ue689"
},
{
"font_class": "vip",
"unicode": "\ue6a8"
},
{
"font_class": "vip-filled",
"unicode": "\ue6c6"
},
{
"font_class": "wallet",
"unicode": "\ue6b1"
},
{
"font_class": "wallet-filled",
"unicode": "\ue6c2"
},
{
"font_class": "weibo",
"unicode": "\ue68b"
},
{
"font_class": "weixin",
"unicode": "\ue691"
}
] as IconsDataItem[]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

649
uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js

@ -0,0 +1,649 @@
export const fontData = [
{
"font_class": "arrow-down",
"unicode": "\ue6be"
},
{
"font_class": "arrow-left",
"unicode": "\ue6bc"
},
{
"font_class": "arrow-right",
"unicode": "\ue6bb"
},
{
"font_class": "arrow-up",
"unicode": "\ue6bd"
},
{
"font_class": "auth",
"unicode": "\ue6ab"
},
{
"font_class": "auth-filled",
"unicode": "\ue6cc"
},
{
"font_class": "back",
"unicode": "\ue6b9"
},
{
"font_class": "bars",
"unicode": "\ue627"
},
{
"font_class": "calendar",
"unicode": "\ue6a0"
},
{
"font_class": "calendar-filled",
"unicode": "\ue6c0"
},
{
"font_class": "camera",
"unicode": "\ue65a"
},
{
"font_class": "camera-filled",
"unicode": "\ue658"
},
{
"font_class": "cart",
"unicode": "\ue631"
},
{
"font_class": "cart-filled",
"unicode": "\ue6d0"
},
{
"font_class": "chat",
"unicode": "\ue65d"
},
{
"font_class": "chat-filled",
"unicode": "\ue659"
},
{
"font_class": "chatboxes",
"unicode": "\ue696"
},
{
"font_class": "chatboxes-filled",
"unicode": "\ue692"
},
{
"font_class": "chatbubble",
"unicode": "\ue697"
},
{
"font_class": "chatbubble-filled",
"unicode": "\ue694"
},
{
"font_class": "checkbox",
"unicode": "\ue62b"
},
{
"font_class": "checkbox-filled",
"unicode": "\ue62c"
},
{
"font_class": "checkmarkempty",
"unicode": "\ue65c"
},
{
"font_class": "circle",
"unicode": "\ue65b"
},
{
"font_class": "circle-filled",
"unicode": "\ue65e"
},
{
"font_class": "clear",
"unicode": "\ue66d"
},
{
"font_class": "close",
"unicode": "\ue673"
},
{
"font_class": "closeempty",
"unicode": "\ue66c"
},
{
"font_class": "cloud-download",
"unicode": "\ue647"
},
{
"font_class": "cloud-download-filled",
"unicode": "\ue646"
},
{
"font_class": "cloud-upload",
"unicode": "\ue645"
},
{
"font_class": "cloud-upload-filled",
"unicode": "\ue648"
},
{
"font_class": "color",
"unicode": "\ue6cf"
},
{
"font_class": "color-filled",
"unicode": "\ue6c9"
},
{
"font_class": "compose",
"unicode": "\ue67f"
},
{
"font_class": "contact",
"unicode": "\ue693"
},
{
"font_class": "contact-filled",
"unicode": "\ue695"
},
{
"font_class": "down",
"unicode": "\ue6b8"
},
{
"font_class": "bottom",
"unicode": "\ue6b8"
},
{
"font_class": "download",
"unicode": "\ue68d"
},
{
"font_class": "download-filled",
"unicode": "\ue681"
},
{
"font_class": "email",
"unicode": "\ue69e"
},
{
"font_class": "email-filled",
"unicode": "\ue69a"
},
{
"font_class": "eye",
"unicode": "\ue651"
},
{
"font_class": "eye-filled",
"unicode": "\ue66a"
},
{
"font_class": "eye-slash",
"unicode": "\ue6b3"
},
{
"font_class": "eye-slash-filled",
"unicode": "\ue6b4"
},
{
"font_class": "fire",
"unicode": "\ue6a1"
},
{
"font_class": "fire-filled",
"unicode": "\ue6c5"
},
{
"font_class": "flag",
"unicode": "\ue65f"
},
{
"font_class": "flag-filled",
"unicode": "\ue660"
},
{
"font_class": "folder-add",
"unicode": "\ue6a9"
},
{
"font_class": "folder-add-filled",
"unicode": "\ue6c8"
},
{
"font_class": "font",
"unicode": "\ue6a3"
},
{
"font_class": "forward",
"unicode": "\ue6ba"
},
{
"font_class": "gear",
"unicode": "\ue664"
},
{
"font_class": "gear-filled",
"unicode": "\ue661"
},
{
"font_class": "gift",
"unicode": "\ue6a4"
},
{
"font_class": "gift-filled",
"unicode": "\ue6c4"
},
{
"font_class": "hand-down",
"unicode": "\ue63d"
},
{
"font_class": "hand-down-filled",
"unicode": "\ue63c"
},
{
"font_class": "hand-up",
"unicode": "\ue63f"
},
{
"font_class": "hand-up-filled",
"unicode": "\ue63e"
},
{
"font_class": "headphones",
"unicode": "\ue630"
},
{
"font_class": "heart",
"unicode": "\ue639"
},
{
"font_class": "heart-filled",
"unicode": "\ue641"
},
{
"font_class": "help",
"unicode": "\ue679"
},
{
"font_class": "help-filled",
"unicode": "\ue674"
},
{
"font_class": "home",
"unicode": "\ue662"
},
{
"font_class": "home-filled",
"unicode": "\ue663"
},
{
"font_class": "image",
"unicode": "\ue670"
},
{
"font_class": "image-filled",
"unicode": "\ue678"
},
{
"font_class": "images",
"unicode": "\ue650"
},
{
"font_class": "images-filled",
"unicode": "\ue64b"
},
{
"font_class": "info",
"unicode": "\ue669"
},
{
"font_class": "info-filled",
"unicode": "\ue649"
},
{
"font_class": "left",
"unicode": "\ue6b7"
},
{
"font_class": "link",
"unicode": "\ue6a5"
},
{
"font_class": "list",
"unicode": "\ue644"
},
{
"font_class": "location",
"unicode": "\ue6ae"
},
{
"font_class": "location-filled",
"unicode": "\ue6af"
},
{
"font_class": "locked",
"unicode": "\ue66b"
},
{
"font_class": "locked-filled",
"unicode": "\ue668"
},
{
"font_class": "loop",
"unicode": "\ue633"
},
{
"font_class": "mail-open",
"unicode": "\ue643"
},
{
"font_class": "mail-open-filled",
"unicode": "\ue63a"
},
{
"font_class": "map",
"unicode": "\ue667"
},
{
"font_class": "map-filled",
"unicode": "\ue666"
},
{
"font_class": "map-pin",
"unicode": "\ue6ad"
},
{
"font_class": "map-pin-ellipse",
"unicode": "\ue6ac"
},
{
"font_class": "medal",
"unicode": "\ue6a2"
},
{
"font_class": "medal-filled",
"unicode": "\ue6c3"
},
{
"font_class": "mic",
"unicode": "\ue671"
},
{
"font_class": "mic-filled",
"unicode": "\ue677"
},
{
"font_class": "micoff",
"unicode": "\ue67e"
},
{
"font_class": "micoff-filled",
"unicode": "\ue6b0"
},
{
"font_class": "minus",
"unicode": "\ue66f"
},
{
"font_class": "minus-filled",
"unicode": "\ue67d"
},
{
"font_class": "more",
"unicode": "\ue64d"
},
{
"font_class": "more-filled",
"unicode": "\ue64e"
},
{
"font_class": "navigate",
"unicode": "\ue66e"
},
{
"font_class": "navigate-filled",
"unicode": "\ue67a"
},
{
"font_class": "notification",
"unicode": "\ue6a6"
},
{
"font_class": "notification-filled",
"unicode": "\ue6c1"
},
{
"font_class": "paperclip",
"unicode": "\ue652"
},
{
"font_class": "paperplane",
"unicode": "\ue672"
},
{
"font_class": "paperplane-filled",
"unicode": "\ue675"
},
{
"font_class": "person",
"unicode": "\ue699"
},
{
"font_class": "person-filled",
"unicode": "\ue69d"
},
{
"font_class": "personadd",
"unicode": "\ue69f"
},
{
"font_class": "personadd-filled",
"unicode": "\ue698"
},
{
"font_class": "personadd-filled-copy",
"unicode": "\ue6d1"
},
{
"font_class": "phone",
"unicode": "\ue69c"
},
{
"font_class": "phone-filled",
"unicode": "\ue69b"
},
{
"font_class": "plus",
"unicode": "\ue676"
},
{
"font_class": "plus-filled",
"unicode": "\ue6c7"
},
{
"font_class": "plusempty",
"unicode": "\ue67b"
},
{
"font_class": "pulldown",
"unicode": "\ue632"
},
{
"font_class": "pyq",
"unicode": "\ue682"
},
{
"font_class": "qq",
"unicode": "\ue680"
},
{
"font_class": "redo",
"unicode": "\ue64a"
},
{
"font_class": "redo-filled",
"unicode": "\ue655"
},
{
"font_class": "refresh",
"unicode": "\ue657"
},
{
"font_class": "refresh-filled",
"unicode": "\ue656"
},
{
"font_class": "refreshempty",
"unicode": "\ue6bf"
},
{
"font_class": "reload",
"unicode": "\ue6b2"
},
{
"font_class": "right",
"unicode": "\ue6b5"
},
{
"font_class": "scan",
"unicode": "\ue62a"
},
{
"font_class": "search",
"unicode": "\ue654"
},
{
"font_class": "settings",
"unicode": "\ue653"
},
{
"font_class": "settings-filled",
"unicode": "\ue6ce"
},
{
"font_class": "shop",
"unicode": "\ue62f"
},
{
"font_class": "shop-filled",
"unicode": "\ue6cd"
},
{
"font_class": "smallcircle",
"unicode": "\ue67c"
},
{
"font_class": "smallcircle-filled",
"unicode": "\ue665"
},
{
"font_class": "sound",
"unicode": "\ue684"
},
{
"font_class": "sound-filled",
"unicode": "\ue686"
},
{
"font_class": "spinner-cycle",
"unicode": "\ue68a"
},
{
"font_class": "staff",
"unicode": "\ue6a7"
},
{
"font_class": "staff-filled",
"unicode": "\ue6cb"
},
{
"font_class": "star",
"unicode": "\ue688"
},
{
"font_class": "star-filled",
"unicode": "\ue68f"
},
{
"font_class": "starhalf",
"unicode": "\ue683"
},
{
"font_class": "trash",
"unicode": "\ue687"
},
{
"font_class": "trash-filled",
"unicode": "\ue685"
},
{
"font_class": "tune",
"unicode": "\ue6aa"
},
{
"font_class": "tune-filled",
"unicode": "\ue6ca"
},
{
"font_class": "undo",
"unicode": "\ue64f"
},
{
"font_class": "undo-filled",
"unicode": "\ue64c"
},
{
"font_class": "up",
"unicode": "\ue6b6"
},
{
"font_class": "top",
"unicode": "\ue6b6"
},
{
"font_class": "upload",
"unicode": "\ue690"
},
{
"font_class": "upload-filled",
"unicode": "\ue68e"
},
{
"font_class": "videocam",
"unicode": "\ue68c"
},
{
"font_class": "videocam-filled",
"unicode": "\ue689"
},
{
"font_class": "vip",
"unicode": "\ue6a8"
},
{
"font_class": "vip-filled",
"unicode": "\ue6c6"
},
{
"font_class": "wallet",
"unicode": "\ue6b1"
},
{
"font_class": "wallet-filled",
"unicode": "\ue6c2"
},
{
"font_class": "weibo",
"unicode": "\ue68b"
},
{
"font_class": "weixin",
"unicode": "\ue691"
}
]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

29
uni_modules/uni-icons/package.json

@ -1,7 +1,7 @@
{
"id": "uni-icons",
"displayName": "uni-icons 图标",
"version": "1.3.5",
"version": "2.0.10",
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
"keywords": [
"uni-ui",
@ -16,11 +16,7 @@
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
@ -37,7 +33,8 @@
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": ["uni-scss"],
@ -45,12 +42,14 @@
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
"aliyun": "y",
"alipay": "n"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
"app-nvue": "y",
"app-uvue": "y"
},
"H5-mobile": {
"Safari": "y",
@ -70,11 +69,15 @@
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
@ -83,4 +86,4 @@
}
}
}
}
}

11
uni_modules/uni-transition/changelog.md

@ -1,3 +1,14 @@
## 1.3.6(2025-07-18)
- 修复 nvue 页面,样式错误问题
## 1.3.5(2025-06-11)
- 修复 第一次执行不显示动画的问题
## 1.3.4(2025-04-16)
- 修复 页面数据更新到底动画复原的问题
- 修复 示例页面打开报错的问题
## 1.3.3(2024-04-23)
- 修复 当元素会受变量影响自动隐藏的bug
## 1.3.2(2023-05-04)
- 修复 NVUE 平台报错的问题
## 1.3.1(2021-11-23)
- 修复 init 方法初始化问题
## 1.3.0(2021-11-19)

85
uni_modules/uni-transition/components/uni-transition/createAnimation.js

@ -10,12 +10,10 @@ const nvueAnimation = uni.requireNativePlugin('animation')
class MPAnimation {
constructor(options, _this) {
this.options = options
try {
this.animation = uni.createAnimation(options)
} catch (error) {
console.error('uni.createAnimation failed:', error)
this.animation = null
}
// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
this.animation = uni.createAnimation({
...options
})
this.currentStepAnimates = {}
this.next = 0
this.$ = _this
@ -80,48 +78,27 @@ class MPAnimation {
step(config = {}) {
// #ifndef APP-NVUE
if (this.animation && typeof this.animation.step === 'function') {
try {
this.animation.step(config)
} catch (error) {
console.error('Animation step failed:', error)
}
}
this.animation.step(config)
// #endif
// #ifdef APP-NVUE
if (this.currentStepAnimates[this.next]) {
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
this.next++
}
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
this.next++
// #endif
return this
}
run(fn) {
// #ifndef APP-NVUE
if (this.animation && typeof this.animation.export === 'function') {
try {
this.$.animationData = this.animation.export()
this.$.timer = setTimeout(() => {
typeof fn === 'function' && fn()
}, this.$.durationTime)
} catch (error) {
console.error('Animation run failed:', error)
typeof fn === 'function' && fn()
}
} else {
// 如果动画对象不存在,直接执行回调
this.$.animationData = this.animation.export()
this.$.timer = setTimeout(() => {
typeof fn === 'function' && fn()
}
}, this.$.durationTime)
// #endif
// #ifdef APP-NVUE
this.isEnd = false
let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
if(!ref) {
typeof fn === 'function' && fn()
return
}
if(!ref) return
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
this.next = 0
// #endif
@ -138,13 +115,7 @@ const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
MPAnimation.prototype[type] = function(...args) {
// #ifndef APP-NVUE
if (this.animation && typeof this.animation[type] === 'function') {
try {
this.animation[type](...args)
} catch (error) {
console.error(`Animation method ${type} failed:`, error)
}
}
this.animation[type](...args)
// #endif
// #ifdef APP-NVUE
this._nvuePushAnimates(type, args)
@ -154,35 +125,7 @@ animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
})
export function createAnimation(option, _this) {
if(!_this) {
console.warn('uni-transition: _this parameter is undefined, returning empty animation object')
// 创建一个完整的空动画对象,确保所有方法都返回自身以支持链式调用
const emptyAnimation = {}
// 添加step和run方法
emptyAnimation.step = function(config = {}) {
return emptyAnimation
}
emptyAnimation.run = function(fn) {
typeof fn === 'function' && fn()
return emptyAnimation
}
// 添加所有动画类型方法
const allAnimateTypes = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
'translateZ', 'opacity', 'backgroundColor', 'width', 'height', 'left', 'right', 'top', 'bottom']
allAnimateTypes.forEach(type => {
emptyAnimation[type] = function(...args) {
return emptyAnimation
}
})
return emptyAnimation
}
if(!_this) return
clearTimeout(_this.timer)
return new MPAnimation(option, _this)
}
// #ifdef MP-WEIXIN
module.exports = {
createAnimation
}
// #endif

643
uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@ -1,369 +1,292 @@
<template>
<view
v-if="isShow"
ref="ani"
:animation="animationData"
:class="customClass"
:style="transformStyles"
@click="onClick"
><slot></slot
></view>
<!-- #ifndef APP-NVUE -->
<view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick">
<slot></slot>
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick">
<slot></slot>
</view>
<!-- #endif -->
</template>
<script>
// #ifndef MP-WEIXIN
import { createAnimation } from "./createAnimation";
// #endif
// #ifdef MP-WEIXIN
const createAnimation = require("./createAnimation.js").createAnimation;
// #endif
import { createAnimation } from './createAnimation'
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} 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",
emits: ["click", "change"],
props: {
show: {
type: Boolean,
default: false,
},
modeClass: {
type: [Array, String],
default() {
return "fade";
},
},
duration: {
type: Number,
default: 300,
},
styles: {
type: Object,
default() {
return {};
},
},
customClass: {
type: String,
default: "",
},
},
data() {
return {
isShow: false,
transform: "",
opacity: 1,
animationData: {},
durationTime: 300,
config: {},
};
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open();
} else {
// close,
if (this.isShow) {
this.close();
}
}
},
immediate: true,
},
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
"transition-duration": this.duration / 1000 + "s",
};
let transform = "";
for (let i in styles) {
let line = this.toLine(i);
transform += line + ":" + styles[i] + ";";
}
return transform;
},
//
transformStyles() {
return (
"transform:" +
this.transform +
";" +
"opacity:" +
this.opacity +
";" +
this.stylesObject
);
},
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: "ease",
transformOrigin: "50% 50%",
delay: 0,
};
this.durationTime = this.duration;
},
beforeUnmount() {
//
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
if (this.animation) {
this.animation = null;
}
},
beforeDestroy() {
// Vue2
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
if (this.animation) {
this.animation = null;
}
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration;
}
this.animation = createAnimation(Object.assign(this.config, obj), this);
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit("click", {
detail: this.isShow,
});
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return this;
for (let i in obj) {
try {
if (this.animation && typeof this.animation[i] === "function") {
if (typeof obj[i] === "object") {
this.animation[i](...obj[i]);
} else {
this.animation[i](obj[i]);
}
}
} catch (e) {
console.error(`方法 ${i} 不存在:`, e);
}
}
try {
if (this.animation && typeof this.animation.step === "function") {
this.animation.step(config);
}
} catch (e) {
console.error("动画step执行错误:", e);
}
return this;
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return;
try {
if (this.animation && typeof this.animation.run === "function") {
this.animation.run(fn);
}
} catch (e) {
console.error("动画执行错误:", e);
}
},
//
open() {
clearTimeout(this.timer);
this.transform = "";
this.isShow = true;
let { opacity, transform } = this.styleInit(false);
if (typeof opacity !== "undefined") {
this.opacity = opacity;
}
this.transform = transform;
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
//
if (!this.isShow || !this.$el) {
return;
}
try {
this.animation = createAnimation(this.config, this);
if (this.animation && typeof this.animation.step === "function" && typeof this.animation.run === "function") {
this.tranfromInit(false);
if (typeof this.animation.step === "function") {
this.animation.step();
if (typeof this.animation.run === "function") {
this.animation.run();
}
}
}
} catch (error) {
console.error('uni-transition animation error:', error);
}
this.$emit("change", {
detail: this.isShow,
});
}, 20);
});
},
//
close(type) {
if (!this.animation || typeof this.animation.step !== 'function' || typeof this.animation.run !== 'function') return;
try {
this.tranfromInit(true);
if (typeof this.animation.step === 'function') {
this.animation.step();
if (typeof this.animation.run === 'function') {
this.animation.run(() => {
this.isShow = false;
this.animationData = null;
this.animation = null;
let { opacity, transform } = this.styleInit(false);
this.opacity = opacity || 1;
this.transform = transform;
this.$emit('change', {
detail: this.isShow,
});
});
}
}
} catch (error) {
console.error('uni-transition close animation error:', error);
//
this.isShow = false;
this.animationData = null;
this.animation = null;
this.$emit('change', {
detail: this.isShow
});
}
},
//
styleInit(type) {
let styles = {
transform: "",
};
let buildStyle = (type, mode) => {
if (mode === "fade") {
styles.opacity = this.animationType(type)[mode];
} else {
styles.transform += this.animationType(type)[mode] + " ";
}
};
if (typeof this.modeClass === "string") {
buildStyle(type, this.modeClass);
} else {
this.modeClass.forEach((mode) => {
buildStyle(type, mode);
});
}
return styles;
},
//
tranfromInit(type) {
if (!this.animation) {
console.warn('uni-transition: animation object is not initialized');
return this.animation;
}
let buildTranfrom = (type, mode) => {
let aniNum = null;
if (mode === 'fade') {
aniNum = type ? 0 : 1;
} else {
aniNum = type ? '-100%' : '0';
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1;
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1;
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0';
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0';
}
}
const animationMethod = this.animationMode()[mode];
if (this.animation && typeof this.animation[animationMethod] === 'function') {
this.animation[animationMethod](aniNum);
}
};
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass);
} else {
this.modeClass.forEach((mode) => {
buildTranfrom(type, mode);
});
}
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} 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',
emits: ['click', 'change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default () {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default () {
return {}
}
},
customClass: {
type: String,
default: ''
},
onceRender: {
type: Boolean,
default: false
},
},
data() {
return {
isShow: false,
transform: '',
opacity: 0,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj), this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return this
Object.keys(obj).forEach(key => {
const value = obj[key]
if (typeof this.animation[key] === 'function') {
Array.isArray(value) ?
this.animation[key](...value) :
this.animation[key](value)
}
})
this.animation.step(config)
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
this.animation.run(fn)
},
//
open() {
clearTimeout(this.timer)
this.isShow = true
//
this.transform = this.styleInit(false).transform || ''
this.opacity = this.styleInit(false).opacity || 0
return this.animation;
},
animationType(type) {
return {
fade: type ? 1 : 0,
"slide-top": `translateY(${type ? "0" : "-100%"})`,
"slide-right": `translateX(${type ? "0" : "100%"})`,
"slide-bottom": `translateY(${type ? "0" : "100%"})`,
"slide-left": `translateX(${type ? "0" : "-100%"})`,
"zoom-in": `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
"zoom-out": `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`,
};
},
//
animationMode() {
return {
fade: "opacity",
"slide-top": "translateY",
"slide-right": "translateX",
"slide-bottom": "translateY",
"slide-left": "translateX",
"zoom-in": "scale",
"zoom-out": "scale",
};
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
},
},
};
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
this.animation = createAnimation(this.config, this)
this.tranfromInit(false).step()
this.animation.run(() => {
// #ifdef APP-NVUE
this.transform = this.styleInit(false).transform || ''
this.opacity = this.styleInit(false).opacity || 1
// #endif
// #ifndef APP-NVUE
this.transform = ''
this.opacity = this.styleInit(false).opacity || 1
// #endif
this.$emit('change', {
detail: this.isShow
})
})
}, 80)
})
},
//
close(type) {
if (!this.animation) return
this.tranfromInit(true)
.step()
.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
},
//
styleInit(type) {
let styles = { transform: '', opacity: 1 }
const buildStyle = (type, mode) => {
const value = this.animationType(type)[mode] // 使 type
if (mode.startsWith('fade')) {
styles.opacity = value
} else {
styles.transform += value + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => buildStyle(type, mode))
}
return styles
},
//
tranfromInit(type) {
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
this.animation[this.animationMode()[mode]](aniNum)
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>

105
uni_modules/uni-transition/package.json

@ -1,7 +1,7 @@
{
"id": "uni-transition",
"displayName": "uni-transition 过渡动画",
"version": "1.3.1",
"version": "1.3.6",
"description": "元素的简单过渡动画",
"keywords": [
"uni-ui",
@ -12,16 +12,14 @@
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
"HBuilderX": "",
"uni-app": "^4.12",
"uni-app-x": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
@ -38,48 +36,75 @@
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": ["uni-scss"],
"dependencies": [
"uni-scss"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
"tcb": "x",
"aliyun": "x",
"alipay": "x"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "√",
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": {
},
"alipay": {
},
"toutiao": {
},
"baidu": {
},
"kuaishou": {
},
"jd": {
},
"harmony": "-",
"qq": "√",
"lark": "-"
},
"quickapp": {
"huawei": "√",
"union": "√"
}
},
"Vue": {
"vue2": "y",
"vue3": "y"
"uni-app-x": {
"web": {
"safari": "-",
"chrome": "-"
},
"app": {
"android": "-",
"ios": "-",
"harmony": "-"
},
"mp": {
"weixin": "-"
}
}
}
}

Loading…
Cancel
Save