87d7b854 by 华明祺

feat(personal): 完善个人会员申请及支付流程

- 协议勾选区域固定在页面底部,优化用户体验
- 联系方式改为非必填,但填写时验证手机号格式
- 支付逻辑使用 await-to-js 重构,统一错误处理
- 支付流程添加 loading 状态,防止重复提交
- 支付成功后传递 orderId,跳转时获取并展示订单详情
- 支付成功页面优化:标签不换行、值支持自动换行
- 新增获取订单详情接口 /common/order/{orderId}
1 parent 7d54d38d
...@@ -195,11 +195,11 @@ export function regionsList(params) { ...@@ -195,11 +195,11 @@ export function regionsList(params) {
195 export function carUrl(data, type) { 195 export function carUrl(data, type) {
196 return uni.uploadFile({ 196 return uni.uploadFile({
197 url: `${config.baseUrl_api}/person/info/getPersonInfoFromCert/${type}`, 197 url: `${config.baseUrl_api}/person/info/getPersonInfoFromCert/${type}`,
198 header: { 198 // header: {
199 'Authorization': uni.getStorageSync('token'), 199 // 'Authorization': uni.getStorageSync('token'),
200 'Content-Language': 'zh_CN', 200 // 'Content-Language': 'zh_CN',
201 'Accept-Language': 'zh-CN,zh', 201 // 'Accept-Language': 'zh-CN,zh',
202 }, 202 // },
203 name: 'pic', 203 name: 'pic',
204 filePath: data 204 filePath: data
205 }).then(res => { 205 }).then(res => {
...@@ -237,10 +237,10 @@ export function addPersonCommit(data) { ...@@ -237,10 +237,10 @@ export function addPersonCommit(data) {
237 } 237 }
238 238
239 export function getZtxFeeConfig() { 239 export function getZtxFeeConfig() {
240 return request({ 240 return request({
241 url: '/system/config/getZtxFeeConfig', 241 url: '/system/config/getZtxFeeConfig',
242 method: 'get' 242 method: 'get'
243 }) 243 })
244 } 244 }
245 // 图片上传 245 // 图片上传
246 export function uploadImg(e) { 246 export function uploadImg(e) {
...@@ -747,10 +747,10 @@ export function personalCommit(id) { ...@@ -747,10 +747,10 @@ export function personalCommit(id) {
747 }) 747 })
748 } 748 }
749 export function getNewCountByRangeId(rangeId) { 749 export function getNewCountByRangeId(rangeId) {
750 return request({ 750 return request({
751 url: `/person/paymentNew/getNewCountByRangeId/${rangeId}`, 751 url: `/person/paymentNew/getNewCountByRangeId/${rangeId}`,
752 method: 'get', 752 method: 'get',
753 }) 753 })
754 } 754 }
755 755
756 export function delPayment(payIds) { 756 export function delPayment(payIds) {
...@@ -774,11 +774,11 @@ export function delcertified(ids) { ...@@ -774,11 +774,11 @@ export function delcertified(ids) {
774 } 774 }
775 775
776 export function editYear(data) { 776 export function editYear(data) {
777 return request({ 777 return request({
778 url: `/person/paymentNew/editYear/${data.payId}?payId=${data.payId}&year=${data.year}`, 778 url: `/person/paymentNew/editYear/${data.payId}?payId=${data.payId}&year=${data.year}`,
779 method: 'post', 779 method: 'post',
780 params: data 780 params: data
781 }) 781 })
782 } 782 }
783 783
784 export function editGroupYear(data) { 784 export function editGroupYear(data) {
...@@ -1283,135 +1283,143 @@ export function checkPersonByPersonId(perId) { ...@@ -1283,135 +1283,143 @@ export function checkPersonByPersonId(perId) {
1283 } 1283 }
1284 // 获取团体会员优惠政策 1284 // 获取团体会员优惠政策
1285 export function canUseDiscount(params) { 1285 export function canUseDiscount(params) {
1286 return request({ 1286 return request({
1287 url: `/system/certifiedNew/canUseDiscount`, 1287 url: `/system/certifiedNew/canUseDiscount`,
1288 method: 'get', 1288 method: 'get',
1289 params 1289 params
1290 }) 1290 })
1291 } 1291 }
1292 // 获取团体会员一年缴费价格 1292 // 获取团体会员一年缴费价格
1293 export function getMyMemberCertUnitFee(params) { 1293 export function getMyMemberCertUnitFee(params) {
1294 return request({ 1294 return request({
1295 url: `/system/certifiedNew/getMyMemberCertUnitFee`, 1295 url: `/system/certifiedNew/getMyMemberCertUnitFee`,
1296 method: 'get', 1296 method: 'get',
1297 params 1297 params
1298 }) 1298 })
1299 } 1299 }
1300 export function checkBusinessLicense(data) { 1300 export function checkBusinessLicense(data) {
1301 return request({ 1301 return request({
1302 url: `/member/info/checkBusinessLicense`, 1302 url: `/member/info/checkBusinessLicense`,
1303 method: 'post', 1303 method: 'post',
1304 params: data 1304 params: data
1305 }) 1305 })
1306 } 1306 }
1307 1307
1308 // 生成团体订单renewYear 1308 // 生成团体订单renewYear
1309 export function certifiedNew(params) { 1309 export function certifiedNew(params) {
1310 return request({ 1310 return request({
1311 url: `/system/certifiedNew/commit`, 1311 url: `/system/certifiedNew/commit`,
1312 method: 'post', 1312 method: 'post',
1313 params 1313 params
1314 }) 1314 })
1315 } 1315 }
1316 1316
1317 // 模拟回调 1317 // 模拟回调
1318 export function callBack2(orderId) { 1318 export function callBack2(orderId) {
1319 return request({ 1319 return request({
1320 url: `/system/certifiedNew/callBack2/${orderId}`, 1320 url: `/system/certifiedNew/callBack2/${orderId}`,
1321 method: 'get', 1321 method: 'get',
1322 }) 1322 })
1323 } 1323 }
1324 export function pcallBack2(orderId) { 1324 export function pcallBack2(orderId) {
1325 return request({ 1325 return request({
1326 url: `/person/paymentRangeNew/callBack2/${orderId}`, 1326 url: `/person/paymentRangeNew/callBack2/${orderId}`,
1327 method: 'get', 1327 method: 'get',
1328 }) 1328 })
1329 } 1329 }
1330 // 优惠政策回显 1330 // 优惠政策回显
1331 export function getZtxDiscountPolicy(params) { 1331 export function getZtxDiscountPolicy(params) {
1332 return request({ 1332 return request({
1333 url: '/system/config/getZtxDiscountPolicy', 1333 url: '/system/config/getZtxDiscountPolicy',
1334 method: 'get', 1334 method: 'get',
1335 params 1335 params
1336 }) 1336 })
1337 } 1337 }
1338 // 考官列表 1338 // 考官列表
1339 export function listApi(params) { 1339 export function listApi(params) {
1340 return request({ 1340 return request({
1341 url: `/member/examiner/list`, 1341 url: `/member/examiner/list`,
1342 method: 'get', 1342 method: 'get',
1343 params 1343 params
1344 }) 1344 })
1345 } 1345 }
1346 1346
1347 // 考官列表 1347 // 考官列表
1348 export function examinerDel(id) { 1348 export function examinerDel(id) {
1349 return request({ 1349 return request({
1350 url: `/member/examiner/${id}`, 1350 url: `/member/examiner/${id}`,
1351 method: 'delete' 1351 method: 'delete'
1352 }) 1352 })
1353 } 1353 }
1354 1354
1355 // 添加考官 1355 // 添加考官
1356 export function otherAdd(memId, ids) { 1356 export function otherAdd(memId, ids) {
1357 return request({ 1357 return request({
1358 url: `/member/examiner/otherAdd/${memId}/${ids}`, 1358 url: `/member/examiner/otherAdd/${memId}/${ids}`,
1359 method: 'post' 1359 method: 'post'
1360 }) 1360 })
1361 } 1361 }
1362 1362
1363 export function commitExamPointApply(params) { 1363 export function commitExamPointApply(params) {
1364 return request({ 1364 return request({
1365 url: `/member/examPointApply/commit?selfSelect=${params.selfSelect}`, 1365 url: `/member/examPointApply/commit?selfSelect=${params.selfSelect}`,
1366 method: 'post', 1366 method: 'post',
1367 params 1367 params
1368 }) 1368 })
1369 } 1369 }
1370 1370
1371 export function getMyStatus() { 1371 export function getMyStatus() {
1372 return request({ 1372 return request({
1373 url: `/member/examPointApply/getMyStatus` 1373 url: `/member/examPointApply/getMyStatus`
1374 }) 1374 })
1375 } 1375 }
1376 1376
1377 // 个人会员缴费支付 1377 // 个人会员缴费支付
1378 export function goPay(id) { 1378 export function goPay(id) {
1379 return request({ 1379 return request({
1380 url: `/person/paymentRangeNew/pay/${id}`, 1380 url: `/person/paymentRangeNew/pay/${id}`,
1381 method: 'post' 1381 method: 'post'
1382 }) 1382 })
1383 } 1383 }
1384 // 缴费单列表学员 1384 // 缴费单列表学员
1385 export function listAPI(params) { 1385 export function listAPI(params) {
1386 return request({ 1386 return request({
1387 url: `/person/paymentNew/list`, 1387 url: `/person/paymentNew/list`,
1388 method: 'get', 1388 method: 'get',
1389 params 1389 params
1390 }) 1390 })
1391 } 1391 }
1392 1392
1393 1393
1394 // 删除学员 1394 // 删除学员
1395 export function paymentNewDel(id) { 1395 export function paymentNewDel(id) {
1396 return request({ 1396 return request({
1397 url: `/person/paymentNew/${id}`, 1397 url: `/person/paymentNew/${id}`,
1398 method: 'delete' 1398 method: 'delete'
1399 }) 1399 })
1400 } 1400 }
1401 1401
1402 1402
1403 // 缴费单列表 1403 // 缴费单列表
1404 export function memberInsertPersons(data) { 1404 export function memberInsertPersons(data) {
1405 return request({ 1405 return request({
1406 url: `/person/paymentNew/memberInsertPersons/${data.rangeId}/${data.year}/${data.idcCode}`, 1406 url: `/person/paymentNew/memberInsertPersons/${data.rangeId}/${data.year}/${data.idcCode}`,
1407 method: 'post', 1407 method: 'post',
1408 data 1408 data
1409 }) 1409 })
1410 } 1410 }
1411 export function createMemberPayRange(data) { 1411 export function createMemberPayRange(data) {
1412 return request({ 1412 return request({
1413 url: `/person/paymentRangeNew/createMemberPayRange`, 1413 url: `/person/paymentRangeNew/createMemberPayRange`,
1414 method: 'post', 1414 method: 'post',
1415 data 1415 data
1416 }) 1416 })
1417 }
1418
1419 // 获取订单详情
1420 export function getOrderInfo(orderId) {
1421 return request({
1422 url: `/common/order/${orderId}`,
1423 method: 'get'
1424 })
1417 } 1425 }
...\ No newline at end of file ...\ No newline at end of file
......
1 { 1 {
2 "dependencies": { 2 "dependencies": {
3 "await-to-js": "^3.0.0",
3 "crypto-js": "^4.1.1", 4 "crypto-js": "^4.1.1",
4 "dayjs": "^1.11.6", 5 "dayjs": "^1.11.6",
5 "lodash": "^4.17.21", 6 "lodash": "^4.17.21",
......
1 <template> 1 <template>
2 <view class="success-container"> 2 <view class="success-container">
3 <!-- 成功图标(渐变圆形+动效) --> 3 <!-- 成功图标(渐变圆形+动效) -->
4 <view class="success-icon"> 4 <view class="success-icon">
5 <view class="icon-circle"> 5 <view class="icon-circle">
6 <text class="check-icon"></text> 6 <text class="check-icon"></text>
7 </view> 7 </view>
8 </view> 8 </view>
9 9
10 <!-- 支付成功标题(动画) --> 10 <!-- 支付成功标题(动画) -->
11 <view class="success-title">支付成功</view> 11 <view class="success-title">支付成功</view>
12 <view class="success-subtitle">支付成功,请等待审核</view> 12 <view class="success-subtitle">支付成功,请等待审核</view>
13 13
14 <!-- 订单信息卡片(带阴影) --> 14 <!-- 订单信息卡片(带阴影) -->
15 <view class="info-card"> 15 <view class="info-card">
16 <view class="info-item"> 16 <view class="info-item">
17 <text class="label">付款账户</text> 17 <text class="label">交易流水号</text>
18 <text class="value">(5437)</text> 18 <text class="value">{{ orderInfo.tradeNo }}</text>
19 </view> 19 </view>
20 <view class="info-item"> 20 <view class="info-item">
21 <text class="label">交易流水号</text> 21 <text class="label">商户名称</text>
22 <text class="value">2205051351076117833</text> 22 <text class="value">{{ orderInfo.merchantName || '中国跆拳道协会' }}</text>
23 </view> 23 </view>
24 <view class="info-item"> 24 <view class="info-item">
25 <text class="label">商户名称</text> 25 <text class="label">订单金额</text>
26 <text class="value">中国跆拳道协会</text> 26 <text class="value amount">{{ orderInfo.price ? orderInfo.price + '元' : '--' }}</text>
27 </view> 27 </view>
28 <view class="info-item"> 28 </view>
29 <text class="label">订单金额</text> 29
30 <text class="value amount">1500.00元</text> 30 <!-- 确定按钮(渐变+动效) -->
31 </view> 31 <view class="confirm-btn-area">
32 <view class="info-item"> 32 <button class="confirm-btn" @click="goBack">确定</button>
33 <text class="label">会员编号</text> 33 </view>
34 <text class="value">CTA00004</text> 34 </view>
35 </view> 35 </template>
36 <view class="info-item"> 36
37 <text class="label">会员有效期</text> 37 <script setup>
38 <text class="value">2028年1月25日</text> 38 import {
39 </view> 39 ref
40 </view> 40 } from 'vue'
41 41 import {
42 <!-- 确定按钮(渐变+动效) --> 42 onLoad
43 <view class="confirm-btn-area"> 43 } from '@dcloudio/uni-app'
44 <button class="confirm-btn" @click="goBack">确定</button> 44 import to from 'await-to-js'
45 </view> 45 import * as api from '@/common/api.js'
46 </view> 46
47 </template> 47 const orderInfo = ref({
48 48 id: '',
49 <script setup> 49 tradeNo: '',
50 import { onLoad } from '@dcloudio/uni-app' 50 merchantName: '中国跆拳道协会',
51 const goBack = () => { 51 price: ''
52 uni.navigateTo({ 52 })
53 url: `/personal/home` 53
54 }) 54 const goBack = () => {
55 } 55 uni.reLaunch({
56 56 url: '/login/login'
57 onLoad((option) => { 57 })
58 }) 58 }
59 </script> 59
60 60 onLoad(async (option) => {
61 <style scoped> 61 if (option.orderId) {
62 /* 全局容器 */ 62 const [err, res] = await to(api.getOrderInfo(option.orderId))
63 .success-container { 63 if (!err && res.data) {
64 display: flex; 64 orderInfo.value = res.data
65 flex-direction: column; 65 } else {
66 align-items: center; 66 orderInfo.value.id = option.orderId
67 padding: 100rpx 40rpx 60rpx; 67 }
68 min-height: 100vh; 68 }
69 background-color: #f8f9fa; 69 })
70 box-sizing: border-box; 70 </script>
71 } 71
72 72 <style scoped>
73 /* 成功图标容器 */ 73 /* 全局容器 */
74 .success-icon { 74 .success-container {
75 margin-bottom: 40rpx; 75 display: flex;
76 animation: fadeIn 0.6s ease-out; 76 flex-direction: column;
77 } 77 align-items: center;
78 78 padding: 100rpx 40rpx 60rpx;
79 /* 渐变圆形背景 */ 79 min-height: 100vh;
80 .icon-circle { 80 background-color: #f8f9fa;
81 width: 180rpx; 81 box-sizing: border-box;
82 height: 180rpx; 82 }
83 border-radius: 50%; 83
84 /* 青绿色渐变 */ 84 /* 成功图标容器 */
85 background: linear-gradient(135deg, #06c1ae, #04a896); 85 .success-icon {
86 display: flex; 86 margin-bottom: 40rpx;
87 align-items: center; 87 animation: fadeIn 0.6s ease-out;
88 justify-content: center; 88 }
89 box-shadow: 0 8rpx 30rpx rgba(6, 193, 174, 0.3); 89
90 /* 轻微上浮动效 */ 90 /* 渐变圆形背景 */
91 animation: scaleIn 0.8s ease-out; 91 .icon-circle {
92 } 92 width: 180rpx;
93 93 height: 180rpx;
94 /* 对勾图标 */ 94 border-radius: 50%;
95 .check-icon { 95 /* 青绿色渐变 */
96 font-size: 90rpx; 96 background: linear-gradient(135deg, #06c1ae, #04a896);
97 color: #ffffff; 97 display: flex;
98 font-weight: bold; 98 align-items: center;
99 } 99 justify-content: center;
100 100 box-shadow: 0 8rpx 30rpx rgba(6, 193, 174, 0.3);
101 /* 支付成功标题 */ 101 /* 轻微上浮动效 */
102 .success-title { 102 animation: scaleIn 0.8s ease-out;
103 font-size: 48rpx; 103 }
104 font-weight: 700; 104
105 color: #333333; 105 /* 对勾图标 */
106 margin-bottom: 12rpx; 106 .check-icon {
107 animation: slideUp 0.6s ease-out; 107 font-size: 90rpx;
108 } 108 color: #ffffff;
109 109 font-weight: bold;
110 /* 副标题 */ 110 }
111 .success-subtitle { 111
112 font-size: 28rpx; 112 /* 支付成功标题 */
113 color: #666666; 113 .success-title {
114 margin-bottom: 60rpx; 114 font-size: 48rpx;
115 animation: slideUp 0.8s ease-out; 115 font-weight: 700;
116 } 116 color: #333333;
117 117 margin-bottom: 12rpx;
118 /* 订单信息卡片 */ 118 animation: slideUp 0.6s ease-out;
119 .info-card { 119 }
120 width: 100%; 120
121 background: #ffffff; 121 /* 副标题 */
122 border-radius: 20rpx; 122 .success-subtitle {
123 padding: 40rpx 30rpx; 123 font-size: 28rpx;
124 box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.05); 124 color: #666666;
125 margin-bottom: 80rpx; 125 margin-bottom: 60rpx;
126 animation: fadeIn 1s ease-out; 126 animation: slideUp 0.8s ease-out;
127 } 127 }
128 128
129 /* 单个信息项 */ 129 /* 订单信息卡片 */
130 .info-item { 130 .info-card {
131 display: flex; 131 width: 100%;
132 justify-content: space-between; 132 background: #ffffff;
133 align-items: center; 133 border-radius: 20rpx;
134 padding: 24rpx 0; 134 padding: 40rpx 30rpx;
135 border-bottom: 1rpx solid #f5f5f5; 135 box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.05);
136 } 136 margin-bottom: 80rpx;
137 /* 最后一项去掉下划线 */ 137 animation: fadeIn 1s ease-out;
138 .info-item:last-child { 138 }
139 border-bottom: none; 139
140 } 140 /* 单个信息项 */
141 141 .info-item {
142 /* 标签样式 */ 142 display: flex;
143 .label { 143 justify-content: space-between;
144 font-size: 32rpx; 144 align-items: center;
145 color: #666666; 145 padding: 24rpx 0;
146 } 146 border-bottom: 1rpx solid #f5f5f5;
147 147 }
148 /* 值样式 */ 148
149 .value { 149 /* 最后一项去掉下划线 */
150 font-size: 32rpx; 150 .info-item:last-child {
151 color: #333333; 151 border-bottom: none;
152 text-align: right; 152 }
153 } 153
154 /* 金额特殊样式 */ 154 /* 标签样式 */
155 .amount { 155 .label {
156 color: #cd1e27; 156 font-size: 32rpx;
157 font-weight: 600; 157 color: #666666;
158 } 158 white-space: nowrap;
159 159 margin-right: 20rpx;
160 /* 确定按钮区域 */ 160 flex-shrink: 0;
161 .confirm-btn-area { 161 }
162 width: 100%; 162
163 padding: 0 20rpx; 163 /* 值样式 */
164 box-sizing: border-box; 164 .value {
165 } 165 font-size: 32rpx;
166 166 color: #333333;
167 /* 确定按钮(渐变+动效) */ 167 text-align: right;
168 .confirm-btn { 168 word-break: break-all;
169 width: 100%; 169 word-wrap: break-word;
170 height: 90rpx; 170 }
171 line-height: 90rpx; 171
172 /* 按钮渐变背景 */ 172 /* 金额特殊样式 */
173 background: #fff; 173 .amount {
174 color: #C4121B; 174 color: #cd1e27;
175 font-size: 36rpx; 175 font-weight: 600;
176 font-weight: 600; 176 }
177 border-radius: 45rpx; 177
178 border: 1px solid #C4121B; 178 /* 确定按钮区域 */
179 animation: slideUp 1s ease-out; 179 .confirm-btn-area {
180 /* 禁止默认样式 */ 180 width: 100%;
181 position: relative; 181 padding: 0 20rpx;
182 overflow: hidden; 182 box-sizing: border-box;
183 } 183 }
184 /* 按钮点击反馈 */ 184
185 .confirm-btn::after { 185 /* 确定按钮(渐变+动效) */
186 border: none; 186 .confirm-btn {
187 } 187 width: 100%;
188 .confirm-btn:active { 188 height: 90rpx;
189 transform: scale(0.98); 189 line-height: 90rpx;
190 box-shadow: 0 4rpx 10rpx rgba(6, 193, 174, 0.2); 190 /* 按钮渐变背景 */
191 } 191 background: #fff;
192 192 color: #C4121B;
193 /* 动画定义 */ 193 font-size: 36rpx;
194 @keyframes fadeIn { 194 font-weight: 600;
195 0% { opacity: 0; } 195 border-radius: 45rpx;
196 100% { opacity: 1; } 196 border: 1px solid #C4121B;
197 } 197 animation: slideUp 1s ease-out;
198 @keyframes scaleIn { 198 /* 禁止默认样式 */
199 0% { transform: scale(0); } 199 position: relative;
200 70% { transform: scale(1.1); } 200 overflow: hidden;
201 100% { transform: scale(1); } 201 }
202 } 202
203 @keyframes slideUp { 203 /* 按钮点击反馈 */
204 0% { opacity: 0; transform: translateY(30rpx); } 204 .confirm-btn::after {
205 100% { opacity: 1; transform: translateY(0); } 205 border: none;
206 } 206 }
207
208 .confirm-btn:active {
209 transform: scale(0.98);
210 box-shadow: 0 4rpx 10rpx rgba(6, 193, 174, 0.2);
211 }
212
213 /* 动画定义 */
214 @keyframes fadeIn {
215 0% {
216 opacity: 0;
217 }
218
219 100% {
220 opacity: 1;
221 }
222 }
223
224 @keyframes scaleIn {
225 0% {
226 transform: scale(0);
227 }
228
229 70% {
230 transform: scale(1.1);
231 }
232
233 100% {
234 transform: scale(1);
235 }
236 }
237
238 @keyframes slideUp {
239 0% {
240 opacity: 0;
241 transform: translateY(30rpx);
242 }
243
244 100% {
245 opacity: 1;
246 transform: translateY(0);
247 }
248 }
207 </style> 249 </style>
...\ No newline at end of file ...\ No newline at end of file
......
1 ## 2.1.6(2023-04-16)
2 * 修复 组件使用 v-show 指令会导致选择图片后初始位置严重偏位的问题
3 ## 2.1.5(2023-04-16)
4 * 新增 兼容APP平台
5
6 ## 2.1.4(2023-03-13)
7 * 新增 fileType 属性,用于指定生成文件的类型,只支持 'jpg' 或 'png',默认为 'png'
8 * 新增 delay 属性,微信小程序平台使用 `Canvas 2D` 绘制时控制图片从绘制到生成所需时间
9 * 优化 当生成图片的尺寸宽/高超过 Canvas 2D 最大限制(1365*1365)则将画布尺寸缩放在限制范围内绘制完成后输出目标尺寸
10 * 优化 旋转图标指示方向与实际旋转方向不符
11
12 ## 2.1.3(2023-02-06)
13 * 优化 vue3支持
14
15 ## 2.1.2(2023-02-03)
16 * 新增 navigation 属性,H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 "navigationStyle": "custom" 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差
17 * 修复 H5平台部分设备(已知iPhone11以下机型)拍照的图片缩放时会闪动的问题
18
19 ## 2.1.1(2022-12-06)
20 * 修复 横屏适配问题
21
22 ## 2.1.0(2022-12-06)
23 * 新增 兼容H5平台,使用 renderjs 响应手势事件
24
25 ## 2.0.0(2022-12-05)
26 * 重构 插件,使用 WXS 响应手势事件
27 * 新增 图片翻转
28 * 新增 拉伸裁剪框放大图片
29 * 新增 监听PC鼠标滚轮触发缩放
30 * 新增 圆形、圆角矩形的图片裁剪
31 * 优化 图片缩放,移动端以双指触摸中心点为缩放中心点,PC端以鼠标所在点为缩放中心点
32 * 优化 裁剪框样式
33 * 优化 图片位置拖动 支持边界回弹效果(滑动时可滑出边界,释放时回弹到边界)
34 * 优化 生成图片使用新版 Canvas 2D 接口
1 {
2 "id": "qf-image-cropper",
3 "displayName": "图片裁剪插件",
4 "version": "2.1.6",
5 "description": "图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。",
6 "keywords": [
7 "qf-image-cropper",
8 "图片裁剪",
9 "图片编辑",
10 "头像裁剪",
11 "小程序"
12 ],
13 "repository": "",
14 "engines": {
15 "HBuilderX": "^3.1.0"
16 },
17 "dcloudext": {
18 "type": "component-vue",
19 "sale": {
20 "regular": {
21 "price": "0.00"
22 },
23 "sourcecode": {
24 "price": "0.00"
25 }
26 },
27 "contact": {
28 "qq": ""
29 },
30 "declaration": {
31 "ads": "无",
32 "data": "插件不采集任何数据",
33 "permissions": "无"
34 },
35 "npmurl": ""
36 },
37 "uni_modules": {
38 "dependencies": [],
39 "encrypt": [],
40 "platforms": {
41 "client": {
42 "Vue": {
43 "vue2": "y",
44 "vue3": "y"
45 },
46 "App": {
47 "app-vue": "y",
48 "app-nvue": "n"
49 },
50 "H5-mobile": {
51 "Safari": "y",
52 "Android Browser": "y",
53 "微信浏览器(Android)": "y",
54 "QQ浏览器(Android)": "u"
55 },
56 "H5-pc": {
57 "Chrome": "u",
58 "IE": "u",
59 "Edge": "u",
60 "Firefox": "u",
61 "Safari": "u"
62 },
63 "小程序": {
64 "微信": "y",
65 "阿里": "n",
66 "百度": "n",
67 "字节跳动": "n",
68 "QQ": "u",
69 "钉钉": "n",
70 "快手": "n",
71 "飞书": "n",
72 "京东": "n"
73 },
74 "快应用": {
75 "华为": "n",
76 "联盟": "n"
77 }
78 }
79 }
80 }
81 }
...\ No newline at end of file ...\ No newline at end of file
1 # qf-image-cropper
2 ## 图片裁剪插件
3 uniapp微信小程序图片裁剪插件,支持自定义尺寸、定点等比例缩放、拖动、图片翻转、剪切圆形/圆角图片、定制样式,功能多性能高体验好注释全。
4
5 ### 平台支持:
6 1. 支持微信小程序:移动端、PC端、开发者工具
7 2. 支持H5平台(2.1.0版本起)
8 3. 支持APP平台(2.1.5版本起):Android、IOS
9 4. 其他平台暂未测试兼容性未知
10
11 ### 支持功能:
12 1. 自定义裁剪尺寸
13 2. 定点等比例缩放:移动端以双指触摸中心点为缩放中心点,PC端以鼠标所在点为缩放中心点
14 3. 自由拖动:支持限制滑出边界,也支持回弹效果(滑动时可滑出边界,释放时回弹到边界)
15 4. 图片翻转:在裁剪尺寸非 1:1 的情况下,翻转时宽高无法铺满裁剪区域时,图片会自动放大到合适尺寸
16 5. 裁剪生成新图片
17 6. 本地选择图片
18 7. 可定制样式:可自由选择是否渲染裁剪边框、可伸缩裁剪顶角、参考线
19 8. 裁剪圆角图片:圆形、圆角矩形
20
21 ### 属性说明
22 | 属性名 | 类型 | 默认值 | 说明 |
23 |:---|:---|:---|:---|
24 | src | String | | 图片资源地址 |
25 | width | Number | 300 | 裁剪宽度 |
26 | height | Number | 300 | 裁剪高度 |
27 | showBorder | Boolean | true | 是否绘制裁剪区域边框 |
28 | showGrid | Boolean | true | 是否绘制裁剪区域网格参考线 |
29 | showAngle | Boolean | true | 是否展示四个支持伸缩的角 |
30 | areaScale | Number | 0.3 | 裁剪区域最小缩放倍数 |
31 | maxScale | Number | 5 | 图片最大缩放倍数 |
32 | bounce | Boolean | true | 是否有回弹效果:拖动时可以拖出边界,释放时会弹回边界 |
33 | rotatable | Boolean | true | 是否支持翻转 |
34 | choosable | Boolean | true | 是否支持从本地选择素材 |
35 | angleSize | Number | 20 | 四个角尺寸,单位px |
36 | angleBorderWidth | Number | 2 | 四个角边框宽度,单位px |
37 | radius | Number | | 裁剪图片圆角半径,单位px |
38 | fileType | String | png | 生成文件的类型,只支持 'jpg' 或 'png'。默认为 'png' |
39 | delay | Number | 1000 | 图片从绘制到生成所需时间,单位ms<br>微信小程序平台使用 `Canvas 2D` 绘制时有效<br>如绘制大图或出现裁剪图片空白等情况应适当调大该值,因 `Canvas 2d` 采用同步绘制,需自己把控绘制完成时间 |
40 | navigation | Boolean | true | 页面是否是原生标题栏:<br>H5平台当 showAngle 为 true 时,使用插件的页面在 `page.json` 中配置了 `"navigationStyle": "custom"` 时,必须将此值设为 false ,否则四个可拉伸角的触发位置会有偏差。<br>注:因H5平台的窗口高度是包含标题栏的,而屏幕触摸点的坐标是不包含的 |
41 | @crop | EventHandle | | 剪裁完成后触发,event = { tempFilePath }。在H5平台下,tempFilePath 为 base64 |
42
43 ### 基本用法
44 ```
45 <template>
46 <div>
47 <qf-image-cropper :width="500" :height="500" :radius="30" @crop="handleCrop"></qf-image-cropper>
48 </div>
49 </template>
50
51 <script>
52 import QfImageCropper from '@/components/qf-image-cropper/qf-image-cropper.vue';
53 export default {
54 components: {
55 QfImageCropper
56 },
57 methods: {
58 handleCrop(e) {
59 uni.previewImage({
60 urls: [e.tempFilePath],
61 current: 0
62 });
63 }
64 }
65 }
66 </script>
67 ```
68 ### 使用说明
69 1.建议在`pages.json`中将引用插件的页面添加一下配置禁止下拉刷新和禁止页面滑动,防止出现性能或页面抖动等问题。
70 ```
71 {
72 "enablePullDownRefresh": false,
73 "disableScroll": true
74 }
75 ```
76 2.建议使用本插件不要设置过大宽高的目标图片尺寸,建议1365x1365以内,否则可能会导致如下问题:
77 ```
78 1.界面卡顿,内存占用过高
79 2.生成图片失真(模糊)
80 3.确定裁剪后一直显示 `裁剪中...`,该问题是由 `uni.canvasToTempFilePath` 无法回调导致,不同平台不同设备限制可能有所不同。
81 ```
82 3.如裁剪后的图片存在偏移的问题,请检查是否受自己项目中父组件或全局样式影响。
83 4.src属性设置网络图片时,图片资源必须是能触发 `getImageInfo` API 的 success 回调才可用于插件裁剪。因此小程序平台获取网络图片信息需先配置download域名白名单才能生效。
...\ No newline at end of file ...\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!