提交 539c605a 作者: 宇宙超人

合并

上级 e07d0d6f
[
{
"key": "ctrl+/",
"command": "editor.action.commentLine",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "shift+alt+a",
"command": "editor.action.blockComment",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+k ctrl+c",
"command": "editor.action.addCommentLine",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "ctrl+k ctrl+u",
"command": "editor.action.removeCommentLine",
"when": "editorTextFocus && !editorReadonly"
}
]
\ No newline at end of file
...@@ -15,6 +15,17 @@ export function bizCommonFileList(params = {}) { ...@@ -15,6 +15,17 @@ export function bizCommonFileList(params = {}) {
}) })
} }
/** /**
* 资源列表
* @param params
* @returns
*/
export function getResourceList(params = {}) {
return otherHttp.get({
url: '/resource/list',
params,
})
}
/**
* 添加资源 * 添加资源
* @param params * @param params
* @returns * @returns
...@@ -25,3 +36,14 @@ export function addResource(params = {}) { ...@@ -25,3 +36,14 @@ export function addResource(params = {}) {
params, params,
}) })
} }
/**
* 下载资源
* @param params
* @returns
*/
export function downloadResource(params = {}) {
return otherHttp.get({
url: '/resource/download',
params,
})
}
...@@ -135,6 +135,10 @@ ...@@ -135,6 +135,10 @@
flex-direction: column; flex-direction: column;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
/* #ifdef APP-PLUS */
position: relative;
z-index: 1;
/* #endif */
} }
.fui-swiper__dot { .fui-swiper__dot {
...@@ -146,7 +150,12 @@ ...@@ -146,7 +150,12 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
/* #ifdef APP-PLUS */
z-index: 998;
/* #endif */
/* #ifndef APP-PLUS */
z-index: 2; z-index: 2;
/* #endif */
overflow: hidden; overflow: hidden;
} }
......
...@@ -365,11 +365,11 @@ ...@@ -365,11 +365,11 @@
<view class="codefun-flex-col section"> <view class="codefun-flex-col section">
<view class="codefun-flex-col mt-52rpx"> <view class="codefun-flex-col mt-52rpx">
<text class="codefun-self-center font text">{{ pageData.header.title }}</text> <text class="codefun-self-center font text">{{ pageData.header.title }}</text>
<!-- <view class="codefun-flex-col codefun-self-stretch mt-19"> <view class="codefun-flex-col codefun-self-stretch mt-19">
<view class="codefun-flex-row codefun-items-center section_2"> <!-- <view class="codefun-flex-row codefun-items-center section_2">
<image class="image_5" src="/static/images/codefun/b8d30fcc0b08b881a41c8b3e35b7f8ac.png" /> <image class="image_5" src="/static/images/codefun/b8d30fcc0b08b881a41c8b3e35b7f8ac.png" />
<text class="codefun-ml-8 font_2 text_2">{{ pageData.header.searchPlaceholder }}</text> <text class="codefun-ml-8 font_2 text_2">{{ pageData.header.searchPlaceholder }}</text>
</view> </view> -->
<view class="codefun-mt-14 codefun-flex-row equal-division section_3"> <view class="codefun-mt-14 codefun-flex-row equal-division section_3">
<view <view
v-for="item in pageData.menuItems" v-for="item in pageData.menuItems"
...@@ -381,7 +381,7 @@ ...@@ -381,7 +381,7 @@
<text class="font_3 mt-13" :class="`text_${item.id + 2}`">{{ item.name }}</text> <text class="font_3 mt-13" :class="`text_${item.id + 2}`">{{ item.name }}</text>
</view> </view>
</view> </view>
</view> --> </view>
</view> </view>
</view> </view>
<view class="codefun-flex-col codefun-relative group_6"> <view class="codefun-flex-col codefun-relative group_6">
...@@ -755,42 +755,55 @@ ...@@ -755,42 +755,55 @@
.mt-19 { .mt-19 {
margin-top: 38rpx; margin-top: 38rpx;
} }
.ml-3 { .ml-3 {
margin-left: 6rpx; margin-left: 6rpx;
} }
.mt-7 { .mt-7 {
margin-top: 14rpx; margin-top: 14rpx;
} }
.ml-9 { .ml-9 {
margin-left: 18rpx; margin-left: 18rpx;
} }
.ml-7 { .ml-7 {
margin-left: 14rpx; margin-left: 14rpx;
} }
.ml-11 { .ml-11 {
margin-left: 22rpx; margin-left: 22rpx;
} }
.mt-17 { .mt-17 {
margin-top: 34rpx; margin-top: 34rpx;
} }
.mt-11 { .mt-11 {
margin-top: 22rpx; margin-top: 22rpx;
} }
.mt-5 { .mt-5 {
margin-top: 10rpx; margin-top: 10rpx;
} }
.mt-21 { .mt-21 {
margin-top: 42rpx; margin-top: 42rpx;
} }
.mt-13 { .mt-13 {
margin-top: 26rpx; margin-top: 26rpx;
} }
.ml-5 { .ml-5 {
margin-left: 10rpx; margin-left: 10rpx;
} }
.mt-3 { .mt-3 {
margin-top: 6rpx; margin-top: 6rpx;
} }
.page { .page {
background-color: #e6f5e8; background-color: #e6f5e8;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
...@@ -806,32 +819,39 @@ ...@@ -806,32 +819,39 @@
background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png'); background-image: url('/static/images/codefun/7a5dc4ee864fe55da98b41c14ee3b931.png');
background-size: 100% 100%; background-size: 100% 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
.group_2 { .group_2 {
padding-left: 16rpx; padding-left: 16rpx;
.image { .image {
border-radius: 64rpx; border-radius: 64rpx;
width: 108rpx; width: 108rpx;
height: 42rpx; height: 42rpx;
} }
.image_2 { .image_2 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 34rpx; width: 34rpx;
height: 22rpx; height: 22rpx;
} }
.image_3 { .image_3 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 30rpx; width: 30rpx;
height: 22rpx; height: 22rpx;
} }
.image_4 { .image_4 {
width: 48rpx; width: 48rpx;
height: 22rpx; height: 22rpx;
} }
} }
.text { .text {
color: #ffffffe6; color: #ffffffe6;
line-height: 29.28rpx; line-height: 29.28rpx;
} }
.section_2 { .section_2 {
padding: 16rpx 18rpx; padding: 16rpx 18rpx;
background-color: #ffffff4d; background-color: #ffffff4d;
...@@ -841,42 +861,53 @@ ...@@ -841,42 +861,53 @@
border-right: solid 1rpx #ffffff7d; border-right: solid 1rpx #ffffff7d;
border-top: solid 1rpx #ffffff7d; border-top: solid 1rpx #ffffff7d;
border-bottom: solid 1rpx #ffffff7d; border-bottom: solid 1rpx #ffffff7d;
.text_2 { .text_2 {
line-height: 25.5rpx; line-height: 25.5rpx;
} }
} }
.equal-division { .equal-division {
position: relative; position: relative;
.equal-division-item { .equal-division-item {
padding: 8rpx 0; padding: 8rpx 0;
width: 134rpx; width: 134rpx;
.text_3 { .text_3 {
line-height: 21.88rpx; line-height: 21.88rpx;
} }
} }
.group_3 { .group_3 {
margin-left: 0; margin-left: 0;
.text_4 { .text_4 {
line-height: 21.98rpx; line-height: 21.98rpx;
} }
.text_5 { .text_5 {
line-height: 21.98rpx; line-height: 21.98rpx;
} }
} }
.image_6 { .image_6 {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 96rpx;
} }
.font_3 { .font_3 {
font-size: 24rpx; font-size: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #1d2129; color: #1d2129;
} }
.equal-division-item_2 { .equal-division-item_2 {
padding: 8rpx 0; padding: 8rpx 0;
width: 134rpx; width: 134rpx;
} }
.group_4 { .group_4 {
// position: absolute; // position: absolute;
// right: 147rpx; // right: 147rpx;
...@@ -885,6 +916,7 @@ ...@@ -885,6 +916,7 @@
line-height: 22.06rpx; line-height: 22.06rpx;
} }
} }
.equal-division-item_3 { .equal-division-item_3 {
// position: absolute; // position: absolute;
// right: 13rpx; // right: 13rpx;
...@@ -893,11 +925,13 @@ ...@@ -893,11 +925,13 @@
line-height: 21.08rpx; line-height: 21.08rpx;
} }
} }
.group_5 { .group_5 {
padding: 8rpx 0; padding: 8rpx 0;
width: 134rpx; width: 134rpx;
} }
} }
.section_3 { .section_3 {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -908,20 +942,25 @@ ...@@ -908,20 +942,25 @@
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
} }
} }
.group_6 { .group_6 {
margin-top: -92rpx; margin-top: -92rpx;
padding-left: 28rpx; padding-left: 28rpx;
.section_4 { .section_4 {
margin-right: 28rpx; margin-right: 28rpx;
padding: 28rpx 28rpx 24rpx; padding: 28rpx 28rpx 24rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
.text_8 { .text_8 {
line-height: 29.88rpx; line-height: 29.88rpx;
} }
.group_7 { .group_7 {
margin-top: 16rpx; margin-top: 16rpx;
.text-wrapper { .text-wrapper {
display: flex; display: flex;
justify-content: center; justify-content: center;
...@@ -933,11 +972,13 @@ ...@@ -933,11 +972,13 @@
border-right: solid 2rpx #4f90f1; border-right: solid 2rpx #4f90f1;
border-top: solid 2rpx #4f90f1; border-top: solid 2rpx #4f90f1;
border-bottom: solid 2rpx #4f90f1; border-bottom: solid 2rpx #4f90f1;
.text_9 { .text_9 {
color: #4f90f1; color: #4f90f1;
line-height: 17.84rpx; line-height: 17.84rpx;
} }
} }
.text-wrapper_2 { .text-wrapper_2 {
display: flex; display: flex;
justify-content: center; justify-content: center;
...@@ -949,53 +990,65 @@ ...@@ -949,53 +990,65 @@
border-right: solid 2rpx #5db66f; border-right: solid 2rpx #5db66f;
border-top: solid 2rpx #5db66f; border-top: solid 2rpx #5db66f;
border-bottom: solid 2rpx #5db66f; border-bottom: solid 2rpx #5db66f;
.text_10 { .text_10 {
color: #5db66f; color: #5db66f;
line-height: 18.14rpx; line-height: 18.14rpx;
} }
} }
} }
.equal-division_2 { .equal-division_2 {
position: relative; position: relative;
align-self: flex-end; align-self: flex-end;
margin-top: 12rpx; margin-top: 12rpx;
.equal-division-item_4 { .equal-division-item_4 {
padding: 12rpx 0; padding: 12rpx 0;
width: 113.96rpx; width: 113.96rpx;
.text_11 { .text_11 {
color: #5db66f; color: #5db66f;
line-height: 24.62rpx; line-height: 24.62rpx;
} }
.text_14 { .text_14 {
line-height: 18.98rpx; line-height: 18.98rpx;
} }
} }
.group_8 { .group_8 {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
.text_12 { .text_12 {
color: #fc8145; color: #fc8145;
} }
.text_15 { .text_15 {
line-height: 18.5rpx; line-height: 18.5rpx;
} }
} }
.group_9 { .group_9 {
position: absolute; position: absolute;
right: 0; right: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
.text_13 { .text_13 {
color: #4f90f1; color: #4f90f1;
line-height: 20rpx; line-height: 20rpx;
} }
.text_16 { .text_16 {
line-height: 18.52rpx; line-height: 18.52rpx;
} }
} }
} }
.section_5 { .section_5 {
padding: 12rpx 0; padding: 12rpx 0;
background-color: #f2faf3; background-color: #f2faf3;
...@@ -1004,35 +1057,43 @@ ...@@ -1004,35 +1057,43 @@
width: 414rpx; width: 414rpx;
} }
} }
.group_10 { .group_10 {
margin-top: 44rpx; margin-top: 44rpx;
.text_17 { .text_17 {
margin-right: 28rpx; margin-right: 28rpx;
line-height: 21.86rpx; line-height: 21.86rpx;
} }
.section_6 { .section_6 {
margin-right: 28rpx; margin-right: 28rpx;
padding: 16rpx 0; padding: 16rpx 0;
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
.equal-division_3 { .equal-division_3 {
.equal-division-item_5 { .equal-division-item_5 {
flex: 1 1 207.64rpx; flex: 1 1 207.64rpx;
.image_7 { .image_7 {
width: 64rpx; width: 64rpx;
height: 64rpx; height: 64rpx;
} }
.text_18 { .text_18 {
margin-top: 20rpx; margin-top: 20rpx;
line-height: 25.42rpx; line-height: 25.42rpx;
} }
.font_7 { .font_7 {
font-size: 20rpx; font-size: 20rpx;
line-height: 32rpx; line-height: 32rpx;
color: #666666; color: #666666;
} }
.text_21 { .text_21 {
margin-left: 8rpx; margin-left: 8rpx;
margin-top: 16rpx; margin-top: 16rpx;
...@@ -1040,6 +1101,7 @@ ...@@ -1040,6 +1101,7 @@
width: 160rpx; width: 160rpx;
height: 60rpx; height: 60rpx;
} }
.text-wrapper_3 { .text-wrapper_3 {
margin-top: 36rpx; margin-top: 36rpx;
padding: 12rpx 0; padding: 12rpx 0;
...@@ -1047,88 +1109,109 @@ ...@@ -1047,88 +1109,109 @@
border-radius: 400rpx; border-radius: 400rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 136rpx; width: 136rpx;
.font_8 { .font_8 {
font-size: 24rpx; font-size: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #16a34a; color: #16a34a;
} }
.text_24 { .text_24 {
line-height: 22.08rpx; line-height: 22.08rpx;
} }
} }
.group_13 { .group_13 {
padding: 8rpx 0; padding: 8rpx 0;
.text_19 { .text_19 {
line-height: 25.62rpx; line-height: 25.62rpx;
} }
.text_23 { .text_23 {
line-height: 18.28rpx; line-height: 18.28rpx;
} }
} }
.text_20 { .text_20 {
margin-right: 12rpx; margin-right: 12rpx;
margin-top: 20rpx; margin-top: 20rpx;
line-height: 25.9rpx; line-height: 25.9rpx;
} }
.text_22 { .text_22 {
margin-top: 16rpx; margin-top: 16rpx;
text-align: center; text-align: center;
width: 138rpx; width: 138rpx;
} }
} }
.group_11 { .group_11 {
padding: 8rpx 12rpx 26rpx; padding: 8rpx 12rpx 26rpx;
} }
.section_7 { .section_7 {
margin: 10rpx 0; margin: 10rpx 0;
} }
.horiz-divider { .horiz-divider {
background-color: #fafafa; background-color: #fafafa;
width: 2rpx; width: 2rpx;
height: 288rpx; height: 288rpx;
} }
.group_12 { .group_12 {
padding: 0 20rpx 26rpx; padding: 0 20rpx 26rpx;
} }
.group_14 { .group_14 {
padding: 8rpx 8rpx 26rpx; padding: 8rpx 8rpx 26rpx;
} }
} }
} }
.section_8 { .section_8 {
margin-right: 28rpx; margin-right: 28rpx;
padding: 28rpx 28rpx 12rpx; padding: 28rpx 28rpx 12rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
.equal-division_4 { .equal-division_4 {
align-self: stretch; align-self: stretch;
.equal-division-item_6 { .equal-division-item_6 {
flex: 1 1 308rpx; flex: 1 1 308rpx;
.font_9 { .font_9 {
font-size: 32rpx; font-size: 32rpx;
line-height: 29.32rpx; line-height: 29.32rpx;
color: #1d2129; color: #1d2129;
} }
.text_25 { .text_25 {
line-height: 28.96rpx; line-height: 28.96rpx;
} }
.image_8 { .image_8 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 94rpx; width: 94rpx;
height: 106rpx; height: 106rpx;
} }
.text_26 { .text_26 {
line-height: 29.82rpx; line-height: 29.82rpx;
} }
.image_9 { .image_9 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 118rpx; width: 118rpx;
height: 98rpx; height: 98rpx;
} }
} }
.section_9 { .section_9 {
padding: 28rpx 32rpx 4rpx; padding: 28rpx 32rpx 4rpx;
background-color: #fff7ec; background-color: #fff7ec;
...@@ -1136,6 +1219,7 @@ ...@@ -1136,6 +1219,7 @@
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
height: 142rpx; height: 142rpx;
} }
.section_10 { .section_10 {
padding: 28rpx 16rpx 12rpx 36rpx; padding: 28rpx 16rpx 12rpx 36rpx;
background-color: #f5fcff; background-color: #f5fcff;
...@@ -1144,6 +1228,7 @@ ...@@ -1144,6 +1228,7 @@
height: 142rpx; height: 142rpx;
} }
} }
.text_27 { .text_27 {
color: #00000099; color: #00000099;
line-height: 40rpx; line-height: 40rpx;
...@@ -1151,108 +1236,135 @@ ...@@ -1151,108 +1236,135 @@
} }
} }
} }
.font_5 { .font_5 {
font-size: 26rpx; font-size: 26rpx;
line-height: 25.56rpx; line-height: 25.56rpx;
color: #333333; color: #333333;
} }
.group_15 { .group_15 {
margin-top: 44rpx; margin-top: 44rpx;
.text_28 { .text_28 {
color: #000000; color: #000000;
} }
.text_29 { .text_29 {
margin-right: 28rpx; margin-right: 28rpx;
line-height: 22.24rpx; line-height: 22.24rpx;
} }
.equal-division_5 { .equal-division_5 {
margin-right: 28rpx; margin-right: 28rpx;
.section_11 { .section_11 {
flex: 1 1 124rpx; flex: 1 1 124rpx;
.image_10 { .image_10 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
} }
.font_11 { .font_11 {
font-size: 24rpx; font-size: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #666666; color: #666666;
} }
.text_30 { .text_30 {
margin-top: 12rpx; margin-top: 12rpx;
line-height: 21.76rpx; line-height: 21.76rpx;
} }
.group_16 { .group_16 {
margin-left: 4rpx; margin-left: 4rpx;
margin-top: 28rpx; margin-top: 28rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
.text_35 { .text_35 {
line-height: 21.62rpx; line-height: 21.62rpx;
} }
} }
.text_31 { .text_31 {
margin-top: 12rpx; margin-top: 12rpx;
line-height: 21.98rpx; line-height: 21.98rpx;
} }
.group_17 { .group_17 {
margin-top: 24rpx; margin-top: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
.text_38 { .text_38 {
line-height: 21.76rpx; line-height: 21.76rpx;
} }
} }
.font_12 { .font_12 {
font-size: 28rpx; font-size: 28rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #000000; color: #000000;
} }
.text_32 { .text_32 {
margin-top: 12rpx; margin-top: 12rpx;
line-height: 22.12rpx; line-height: 22.12rpx;
} }
.group_18 { .group_18 {
margin-top: 28rpx; margin-top: 28rpx;
line-height: 22.2rpx; line-height: 22.2rpx;
.text_36 { .text_36 {
line-height: 22.2rpx; line-height: 22.2rpx;
} }
.text_39 { .text_39 {
line-height: 20.14rpx; line-height: 20.14rpx;
} }
} }
.text_33 { .text_33 {
margin-top: 12rpx; margin-top: 12rpx;
line-height: 21.74rpx; line-height: 21.74rpx;
} }
.group_19 { .group_19 {
margin-left: 4rpx; margin-left: 4rpx;
margin-top: 28rpx; margin-top: 28rpx;
line-height: 22.52rpx; line-height: 22.52rpx;
.text_37 { .text_37 {
line-height: 22.52rpx; line-height: 22.52rpx;
} }
.text_40 { .text_40 {
line-height: 21.46rpx; line-height: 21.46rpx;
} }
} }
.text_34 { .text_34 {
margin-left: 4rpx; margin-left: 4rpx;
margin-top: 12rpx; margin-top: 12rpx;
line-height: 22.04rpx; line-height: 22.04rpx;
} }
.group_20 { .group_20 {
margin-left: 4rpx; margin-left: 4rpx;
margin-top: 24rpx; margin-top: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
.text_41 { .text_41 {
line-height: 20.32rpx; line-height: 20.32rpx;
} }
} }
} }
.equal-division-item_7 { .equal-division-item_7 {
padding: 32rpx 12rpx 24rpx; padding: 32rpx 12rpx 24rpx;
background-color: #ffffff; background-color: #ffffff;
...@@ -1262,52 +1374,65 @@ ...@@ -1262,52 +1374,65 @@
} }
} }
} }
.font_6 { .font_6 {
font-size: 24rpx; font-size: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #5db66f; color: #5db66f;
} }
.font_10 { .font_10 {
font-size: 24rpx; font-size: 24rpx;
line-height: 22.84rpx; line-height: 22.84rpx;
color: #000000; color: #000000;
} }
.group_21 { .group_21 {
margin-top: 44rpx; margin-top: 44rpx;
.section_12 { .section_12 {
margin-right: 28rpx; margin-right: 28rpx;
padding: 0 24rpx 24rpx; padding: 0 24rpx 24rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
.group_23 { .group_23 {
padding-left: 8rpx; padding-left: 8rpx;
padding-top: 36rpx; padding-top: 36rpx;
.font_13 { .font_13 {
font-size: 24rpx; font-size: 24rpx;
font-family: Inter; font-family: Inter;
line-height: 18.3rpx; line-height: 18.3rpx;
color: #89909d; color: #89909d;
} }
.text_45 { .text_45 {
line-height: 17.94rpx; line-height: 17.94rpx;
} }
.text_46 { .text_46 {
line-height: 17.96rpx; line-height: 17.96rpx;
} }
.text_47 { .text_47 {
line-height: 17.94rpx; line-height: 17.94rpx;
} }
.text_48 { .text_48 {
line-height: 17.94rpx; line-height: 17.94rpx;
} }
.text_49 { .text_49 {
line-height: 17.94rpx; line-height: 17.94rpx;
} }
.group_24 { .group_24 {
padding: 48rpx 0; padding: 48rpx 0;
.divider { .divider {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
background-image: repeating-linear-gradient( background-image: repeating-linear-gradient(
...@@ -1320,35 +1445,42 @@ ...@@ -1320,35 +1445,42 @@
background-position: -4rpx 0rpx; background-position: -4rpx 0rpx;
height: 2rpx; height: 2rpx;
} }
.view_2 { .view_2 {
margin-top: 48rpx; margin-top: 48rpx;
} }
.view_3 { .view_3 {
margin-top: 48rpx; margin-top: 48rpx;
} }
.image-wrapper { .image-wrapper {
padding-bottom: 104rpx; padding-bottom: 104rpx;
background-image: url('/static/images/codefun/e18202eb8182b8d77c464523c2305fa3.png'); background-image: url('/static/images/codefun/e18202eb8182b8d77c464523c2305fa3.png');
background-size: 100% 100%; background-size: 100% 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
.image_11 { .image_11 {
margin-left: 8rpx; margin-left: 8rpx;
width: 564rpx; width: 564rpx;
height: 92rpx; height: 92rpx;
} }
} }
.pos_2 { .pos_2 {
position: absolute; position: absolute;
left: 17rpx; left: 17rpx;
right: 6.6rpx; right: 6.6rpx;
top: 0; top: 0;
} }
.pos { .pos {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
} }
.pos_3 { .pos_3 {
position: absolute; position: absolute;
left: 0; left: 0;
...@@ -1357,49 +1489,62 @@ ...@@ -1357,49 +1489,62 @@
} }
} }
} }
.group_25 { .group_25 {
overflow: hidden; overflow: hidden;
height: 142rpx; height: 142rpx;
.equal-division_6 { .equal-division_6 {
position: relative; position: relative;
margin-top: -16rpx; margin-top: -16rpx;
.section_13 { .section_13 {
flex: 1 1 201.34rpx; flex: 1 1 201.34rpx;
.image_12 { .image_12 {
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;
} }
.text-wrapper_4 { .text-wrapper_4 {
padding: 4rpx 0; padding: 4rpx 0;
overflow: hidden; overflow: hidden;
width: 96rpx; width: 96rpx;
.text_50 { .text_50 {
line-height: 22rpx; line-height: 22rpx;
} }
.text_53 { .text_53 {
color: #ef4444; color: #ef4444;
line-height: 22.16rpx; line-height: 22.16rpx;
} }
.text_51 { .text_51 {
line-height: 21.94rpx; line-height: 21.94rpx;
} }
.text_54 { .text_54 {
color: #eab308; color: #eab308;
line-height: 21.92rpx; line-height: 21.92rpx;
} }
} }
.text-wrapper_5 { .text-wrapper_5 {
padding: 4rpx 0; padding: 4rpx 0;
overflow: hidden; overflow: hidden;
.text_52 { .text_52 {
line-height: 22.2rpx; line-height: 22.2rpx;
} }
.text_55 { .text_55 {
color: #3b82f6; color: #3b82f6;
line-height: 22.22rpx; line-height: 22.22rpx;
} }
} }
} }
.equal-division-item_8 { .equal-division-item_8 {
padding: 24rpx 0; padding: 24rpx 0;
background-color: #f9fafb; background-color: #f9fafb;
...@@ -1407,6 +1552,7 @@ ...@@ -1407,6 +1552,7 @@
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
height: 176rpx; height: 176rpx;
} }
.section_14 { .section_14 {
padding: 24rpx 40rpx; padding: 24rpx 40rpx;
background-color: #f9fafb; background-color: #f9fafb;
...@@ -1418,16 +1564,20 @@ ...@@ -1418,16 +1564,20 @@
} }
} }
} }
.group_26 { .group_26 {
overflow-x: scroll; overflow-x: scroll;
padding-right: 14rpx; padding-right: 14rpx;
.text_56 { .text_56 {
line-height: 29.76rpx; line-height: 29.76rpx;
} }
.text_57 { .text_57 {
margin-right: 24rpx; margin-right: 24rpx;
line-height: 22.24rpx; line-height: 22.24rpx;
} }
.section_15 { .section_15 {
padding: 16rpx 0; padding: 16rpx 0;
background-color: #ffffff; background-color: #ffffff;
...@@ -1436,9 +1586,11 @@ ...@@ -1436,9 +1586,11 @@
box-shadow: 0rpx 8rpx 64rpx #15161a0a; box-shadow: 0rpx 8rpx 64rpx #15161a0a;
width: 300rpx; width: 300rpx;
height: 120rpx; height: 120rpx;
.text_58 { .text_58 {
line-height: 25.78rpx; line-height: 25.78rpx;
} }
.section_17 { .section_17 {
background-color: #13df00; background-color: #13df00;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
...@@ -1446,10 +1598,12 @@ ...@@ -1446,10 +1598,12 @@
width: 12rpx; width: 12rpx;
height: 12rpx; height: 12rpx;
} }
.text_59 { .text_59 {
color: #13e000; color: #13e000;
} }
} }
.section_16 { .section_16 {
padding: 16rpx 26rpx; padding: 16rpx 26rpx;
background-color: #ffffff; background-color: #ffffff;
...@@ -1458,8 +1612,10 @@ ...@@ -1458,8 +1612,10 @@
box-shadow: 0rpx 8rpx 64rpx #15161a0a; box-shadow: 0rpx 8rpx 64rpx #15161a0a;
width: 300rpx; width: 300rpx;
height: 120rpx; height: 120rpx;
.group_27 { .group_27 {
width: 140rpx; width: 140rpx;
.section_18 { .section_18 {
background-color: #d7d7d9; background-color: #d7d7d9;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
...@@ -1467,23 +1623,27 @@ ...@@ -1467,23 +1623,27 @@
width: 12rpx; width: 12rpx;
height: 12rpx; height: 12rpx;
} }
.text_60 { .text_60 {
color: #75777c; color: #75777c;
line-height: 18.04rpx; line-height: 18.04rpx;
} }
} }
} }
.image_13 { .image_13 {
border-radius: 24rpx; border-radius: 24rpx;
width: 92rpx; width: 92rpx;
height: 92rpx; height: 92rpx;
} }
.font_14 { .font_14 {
font-size: 28rpx; font-size: 28rpx;
line-height: 25.56rpx; line-height: 25.56rpx;
color: #15161a; color: #15161a;
} }
.image-wrapper_2 { .image-wrapper_2 {
padding: 16rpx 0; padding: 16rpx 0;
background-color: #ffffff; background-color: #ffffff;
...@@ -1492,6 +1652,7 @@ ...@@ -1492,6 +1652,7 @@
box-shadow: 0rpx 8rpx 64rpx #15161a0a; box-shadow: 0rpx 8rpx 64rpx #15161a0a;
width: 92rpx; width: 92rpx;
height: 120rpx; height: 120rpx;
.image_14 { .image_14 {
border-radius: 24rpx 0 0 24rpx; border-radius: 24rpx 0 0 24rpx;
width: 66rpx; width: 66rpx;
...@@ -1499,27 +1660,34 @@ ...@@ -1499,27 +1660,34 @@
} }
} }
} }
.view_4 { .view_4 {
margin-top: 520rpx; margin-top: 520rpx;
} }
.group_28 { .group_28 {
margin-top: 48rpx; margin-top: 48rpx;
.text_61 { .text_61 {
line-height: 29.4rpx; line-height: 29.4rpx;
} }
.section_19 { .section_19 {
margin-right: 28rpx; margin-right: 28rpx;
padding: 32rpx 64rpx; padding: 32rpx 64rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
.image_15 { .image_15 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 210rpx; width: 210rpx;
height: 210rpx; height: 210rpx;
} }
.group_29 { .group_29 {
width: 260rpx; width: 260rpx;
.text_62 { .text_62 {
margin-left: 72rpx; margin-left: 72rpx;
color: #ffaa1e; color: #ffaa1e;
...@@ -1527,22 +1695,26 @@ ...@@ -1527,22 +1695,26 @@
line-height: 28.56rpx; line-height: 28.56rpx;
} }
.text_63 { .text_63 {
margin-left: 8rpx; margin-left: 8rpx;
color: #000000; color: #000000;
line-height: 25.88rpx; line-height: 25.88rpx;
} }
.text_64 { .text_64 {
margin-left: 8rpx; margin-left: 8rpx;
color: #6b7280; color: #6b7280;
line-height: 22.24rpx; line-height: 22.24rpx;
} }
.text-wrapper_6 { .text-wrapper_6 {
padding: 16rpx 0; padding: 16rpx 0;
background-color: #5db66f; background-color: #5db66f;
border-radius: 19998rpx; border-radius: 19998rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 208rpx; width: 208rpx;
.text_65 { .text_65 {
line-height: 22.18rpx; line-height: 22.18rpx;
} }
...@@ -1550,8 +1722,10 @@ ...@@ -1550,8 +1722,10 @@
} }
} }
} }
.group_30 { .group_30 {
margin-top: 48rpx; margin-top: 48rpx;
.section_20 { .section_20 {
position: relative; position: relative;
margin-right: 28rpx; margin-right: 28rpx;
...@@ -1563,6 +1737,7 @@ ...@@ -1563,6 +1737,7 @@
background-color: #ffffff; background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
// background-image: url('/static/images/codefun/de7f2f0177d74c2b9c784b3825ea9832.png'); // background-image: url('/static/images/codefun/de7f2f0177d74c2b9c784b3825ea9832.png');
// background-size: 94%; // background-size: 94%;
// background-repeat: no-repeat; // background-repeat: no-repeat;
...@@ -1585,35 +1760,44 @@ ...@@ -1585,35 +1760,44 @@
} }
} }
} }
.describe { .describe {
width: 88%; width: 88%;
position: absolute; position: absolute;
bottom: 52rpx; bottom: 52rpx;
left: 40rpx; left: 40rpx;
.text_34 { .text_34 {
color: #ffffff; color: #ffffff;
} }
} }
.text_68 { .text_68 {
line-height: 26.58rpx; line-height: 26.58rpx;
} }
.group_31 { .group_31 {
margin-top: 20rpx; margin-top: 20rpx;
.image_16 { .image_16 {
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
border-radius: 50%; border-radius: 50%;
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;
} }
.text_69 { .text_69 {
line-height: 21.76rpx; line-height: 21.76rpx;
} }
.text_70 { .text_70 {
line-height: 23.04rpx; line-height: 23.04rpx;
} }
} }
.group_32 { .group_32 {
margin-top: 30rpx; margin-top: 30rpx;
.section_21 { .section_21 {
background-color: #5db66f; background-color: #5db66f;
border-radius: 12rpx; border-radius: 12rpx;
...@@ -1621,13 +1805,16 @@ ...@@ -1621,13 +1805,16 @@
width: 40rpx; width: 40rpx;
height: 12rpx; height: 12rpx;
} }
.image-wrapper_3 { .image-wrapper_3 {
width: 40rpx; width: 40rpx;
.image_17 { .image_17 {
width: 40rpx; width: 40rpx;
height: 12rpx; height: 12rpx;
} }
} }
.section_22 { .section_22 {
background-color: #5db66f33; background-color: #5db66f33;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
...@@ -1638,24 +1825,31 @@ ...@@ -1638,24 +1825,31 @@
} }
} }
} }
.group_22 { .group_22 {
padding-bottom: 32rpx; padding-bottom: 32rpx;
.text_42 { .text_42 {
line-height: 29.18rpx; line-height: 29.18rpx;
} }
.text_43 { .text_43 {
line-height: 22.24rpx; line-height: 22.24rpx;
} }
.text_44 { .text_44 {
margin-right: 28rpx; margin-right: 28rpx;
} }
.text_66 { .text_66 {
line-height: 29.48rpx; line-height: 29.48rpx;
} }
.text_67 { .text_67 {
margin-right: 24rpx; margin-right: 24rpx;
} }
} }
.font_15 { .font_15 {
font-size: 24rpx; font-size: 24rpx;
...@@ -1663,11 +1857,13 @@ ...@@ -1663,11 +1857,13 @@
color: #ffffff; color: #ffffff;
} }
} }
.font { .font {
font-size: 32rpx; font-size: 32rpx;
line-height: 29.32rpx; line-height: 29.32rpx;
color: #333333; color: #333333;
} }
.font_2 { .font_2 {
font-size: 28rpx; font-size: 28rpx;
...@@ -1675,22 +1871,27 @@ ...@@ -1675,22 +1871,27 @@
color: #ffffff; color: #ffffff;
} }
} }
.equal-division_7 { .equal-division_7 {
padding: 10rpx 8rpx 16rpx; padding: 10rpx 8rpx 16rpx;
background-color: #ffffff; background-color: #ffffff;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
border-top: solid 1rpx #e7e7e7; border-top: solid 1rpx #e7e7e7;
.group_33 { .group_33 {
flex: 1 1 146.82rpx; flex: 1 1 146.82rpx;
} }
.equal-division-item_9 { .equal-division-item_9 {
padding: 12rpx 0; padding: 12rpx 0;
} }
} }
.image_5 { .image_5 {
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
} }
.font_4 { .font_4 {
font-size: 20rpx; font-size: 20rpx;
......
<template> <template>
<u-modal :show="show" :title="dialogTitle" :showConfirmButton="false" :showCancelButton="false" @close="handleClose" <u-modal
:closeOnClickOverlay="false" > :show="show"
:title="dialogTitle"
:showConfirmButton="false"
:showCancelButton="false"
@close="handleClose"
:closeOnClickOverlay="false"
>
<view class="dialog-content"> <view class="dialog-content">
<u-form :model="formData" :rules="rules" ref="formRef" label-width="auto"> <u-form :model="formData" :rules="rules" ref="formRef" label-width="auto">
<!-- 资源基本信息 --> <!-- 资源基本信息 -->
...@@ -16,8 +22,7 @@ ...@@ -16,8 +22,7 @@
<u-form-item label="上传文件" prop="file" required> <u-form-item label="上传文件" prop="file" required>
<view class="file-upload"> <view class="file-upload">
<u-button v-if="!formData.file" @click="chooseFile" type="primary" <u-button v-if="!formData.file" @click="chooseFile" type="primary" class="ui-button">
class="ui-button">
<text class="font_10">选择文件</text> <text class="font_10">选择文件</text>
</u-button> </u-button>
<view v-else class="file-info"> <view v-else class="file-info">
...@@ -31,8 +36,14 @@ ...@@ -31,8 +36,14 @@
<!-- 操作按钮 --> <!-- 操作按钮 -->
<view class="dialog-buttons"> <view class="dialog-buttons">
<u-button type="primary" @click="handleSubmit" :loading="loading" size="normal" class="submit-btn" <u-button
color="var(--fui-color-success)"> type="primary"
@click="handleSubmit"
:loading="loading"
size="normal"
class="submit-btn"
color="var(--fui-color-success)"
>
{{ submitButtonText }} {{ submitButtonText }}
</u-button> </u-button>
<u-button @click="handleClose" size="normal" class="cancel-btn">取消</u-button> <u-button @click="handleClose" size="normal" class="cancel-btn">取消</u-button>
...@@ -43,37 +54,37 @@ ...@@ -43,37 +54,37 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, watch, computed } from 'vue' import { ref, reactive, watch, computed } from 'vue'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import { useGlobSetting } from '/@/hooks/setting' import { useGlobSetting } from '/@/hooks/setting'
import * as WodeAPI from '@/api/model/wode' import * as WodeAPI from '@/api/model/wode'
// 定义Props // 定义Props
interface Props { interface Props {
show: boolean show: boolean
editData?: any editData?: any
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
show: false, show: false,
editData: null editData: null,
}) })
// 定义Emits // 定义Emits
const emit = defineEmits<{ const emit = defineEmits<{
'update:show': [value: boolean] 'update:show': [value: boolean]
'submit': [data: any] submit: [data: any]
'close': [] close: []
'submitSuccess': [] submitSuccess: []
}>() }>()
// 表单引用 // 表单引用
const formRef = ref() const formRef = ref()
const loading = ref(false) const loading = ref(false)
const uploading = ref(false) const uploading = ref(false)
const showFileTypePicker = ref(false) const showFileTypePicker = ref(false)
// 文件类型选项 // 文件类型选项
const fileTypeOptions = [ const fileTypeOptions = [
{ value: 'doc', text: 'Word文档' }, { value: 'doc', text: 'Word文档' },
{ value: 'xls', text: 'Excel表格' }, { value: 'xls', text: 'Excel表格' },
{ value: 'ppt', text: 'PPT演示' }, { value: 'ppt', text: 'PPT演示' },
...@@ -82,36 +93,34 @@ const fileTypeOptions = [ ...@@ -82,36 +93,34 @@ const fileTypeOptions = [
{ value: 'video', text: '视频文件' }, { value: 'video', text: '视频文件' },
{ value: 'audio', text: '音频文件' }, { value: 'audio', text: '音频文件' },
{ value: 'zip', text: '压缩文件' }, { value: 'zip', text: '压缩文件' },
{ value: 'other', text: '其他文件' } { value: 'other', text: '其他文件' },
] ]
// 表单数据 // 表单数据
const formData = reactive({ const formData = reactive({
fileName: '', fileName: '',
fileType: '', fileType: '',
fileTypeText: '', fileTypeText: '',
file: null, file: null,
fileSrc: '', fileSrc: '',
}) })
// 计算属性 // 计算属性
const dialogTitle = computed(() => { const dialogTitle = computed(() => {
return props.editData ? '编辑资源' : '上传资源' return props.editData ? '编辑资源' : '上传资源'
}) })
const submitButtonText = computed(() => { const submitButtonText = computed(() => {
return props.editData ? '保存' : '上传' return props.editData ? '保存' : '上传'
}) })
// 表单验证规则 // 表单验证规则
const rules = { const rules = {
fileName: [ fileName: [
{ required: true, message: '请输入文件名称', trigger: 'blur' }, { required: true, message: '请输入文件名称', trigger: 'blur' },
{ min: 2, max: 50, message: '文件名称长度在2-50个字符之间', trigger: 'blur' } { min: 2, max: 50, message: '文件名称长度在2-50个字符之间', trigger: 'blur' },
],
fileType: [
{ required: true, message: '请选择文件类型', trigger: 'change' }
], ],
fileType: [{ required: true, message: '请选择文件类型', trigger: 'change' }],
file: [ file: [
{ {
required: true, required: true,
...@@ -123,13 +132,15 @@ const rules = { ...@@ -123,13 +132,15 @@ const rules = {
} else { } else {
callback() callback()
} }
},
},
],
} }
}
]
}
// 监听显示状态 // 监听显示状态
watch(() => props.show, (newVal) => { watch(
() => props.show,
(newVal) => {
if (newVal && props.editData) { if (newVal && props.editData) {
// 编辑模式,填充数据 // 编辑模式,填充数据
resetFormData() resetFormData()
...@@ -138,10 +149,11 @@ watch(() => props.show, (newVal) => { ...@@ -138,10 +149,11 @@ watch(() => props.show, (newVal) => {
// 添加模式,重置表单 // 添加模式,重置表单
resetFormData() resetFormData()
} }
}) },
)
// 重置表单数据 // 重置表单数据
const resetFormData = () => { const resetFormData = () => {
formData.fileName = '' formData.fileName = ''
formData.fileType = '' formData.fileType = ''
formData.fileTypeText = '' formData.fileTypeText = ''
...@@ -151,10 +163,10 @@ const resetFormData = () => { ...@@ -151,10 +163,10 @@ const resetFormData = () => {
if (formRef.value) { if (formRef.value) {
formRef.value.resetFields() formRef.value.resetFields()
} }
} }
// 加载编辑数据 // 加载编辑数据
const loadEditData = () => { const loadEditData = () => {
if (!props.editData) return if (!props.editData) return
formData.fileName = props.editData.fileName || '' formData.fileName = props.editData.fileName || ''
...@@ -163,10 +175,10 @@ const loadEditData = () => { ...@@ -163,10 +175,10 @@ const loadEditData = () => {
// 编辑模式不修改文件本身 // 编辑模式不修改文件本身
// formData.file = null // formData.file = null
} }
const uplpoadFile = ref(null) const uplpoadFile = ref(null)
// 选择文件 // 选择文件
const chooseFile = () => { const chooseFile = () => {
uni.chooseFile({ uni.chooseFile({
count: 1, count: 1,
extension: ['*'], extension: ['*'],
...@@ -198,50 +210,50 @@ const chooseFile = () => { ...@@ -198,50 +210,50 @@ const chooseFile = () => {
console.error('选择文件失败:', err) console.error('选择文件失败:', err)
uni.showToast({ title: '选择文件失败', icon: 'none' }) uni.showToast({ title: '选择文件失败', icon: 'none' })
uploading.value = false uploading.value = false
} },
}) })
} }
// 移除文件 // 移除文件
const removeFile = () => { const removeFile = () => {
formData.file = null formData.file = null
// 移除文件后触发验证 // 移除文件后触发验证
if (formRef.value) { if (formRef.value) {
formRef.value.validateField('file') formRef.value.validateField('file')
} }
} }
// 根据文件扩展名获取文件类型 // 根据文件扩展名获取文件类型
const getFileTypeByExt = (ext) => { const getFileTypeByExt = (ext) => {
const map = { const map = {
'doc': 'doc', doc: 'doc',
'docx': 'doc', docx: 'doc',
'xls': 'xls', xls: 'xls',
'xlsx': 'xls', xlsx: 'xls',
'ppt': 'ppt', ppt: 'ppt',
'pptx': 'ppt', pptx: 'ppt',
'pdf': 'pdf', pdf: 'pdf',
'jpg': 'img', jpg: 'img',
'jpeg': 'img', jpeg: 'img',
'png': 'img', png: 'img',
'gif': 'img', gif: 'img',
'mp4': 'video', mp4: 'video',
'avi': 'video', avi: 'video',
'mp3': 'audio', mp3: 'audio',
'wav': 'audio', wav: 'audio',
'zip': 'zip', zip: 'zip',
'rar': 'zip', rar: 'zip',
'7z': 'zip' '7z': 'zip',
} }
const type = map[ext] || 'other' const type = map[ext] || 'other'
return fileTypeOptions.find(item => item.value === type) || fileTypeOptions[8] return fileTypeOptions.find((item) => item.value === type) || fileTypeOptions[8]
} }
const userStore = useUserStore() const userStore = useUserStore()
const globSetting = useGlobSetting() const globSetting = useGlobSetting()
const toastRef = ref() const toastRef = ref()
// 提交表单 // 提交表单
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
console.log(formData) console.log(formData)
// 先进行表单验证 // 先进行表单验证
...@@ -255,7 +267,7 @@ const handleSubmit = async () => { ...@@ -255,7 +267,7 @@ const handleSubmit = async () => {
if (!formData.file) { if (!formData.file) {
uni.showToast({ uni.showToast({
title: '请选择文件', title: '请选择文件',
icon: 'none' icon: 'none',
}) })
return return
} }
...@@ -287,21 +299,24 @@ const handleSubmit = async () => { ...@@ -287,21 +299,24 @@ const handleSubmit = async () => {
if (res.statusCode === 200) { if (res.statusCode === 200) {
const data = JSON.parse(res.data) const data = JSON.parse(res.data)
if (data.code === 200 || data.code === 0) { if (data.code === 200 || data.code === 0) {
submitData.fileSrc = data.message; submitData.fileSrc = data.message
WodeAPI.addResource(submitData).then(res => { WodeAPI.addResource(submitData)
.then((res) => {
toastRef.value.show({ toastRef.value.show({
type: 'success', type: 'success',
text: `上传成功`, text: `上传成功`,
}) })
emit('update:show', false) // emit('update:show', false)
emit('submitSuccess') emit('submitSuccess')
}).catch(error => { })
.catch((error) => {
uni.showToast({ uni.showToast({
title: error.message || '提交失败,请重试', title: error.message || '提交失败,请重试',
icon: 'none', icon: 'none',
duration: 2000 duration: 2000,
})
}) })
}).finally(() => { .finally(() => {
loading.value = false loading.value = false
}) })
} }
...@@ -320,60 +335,59 @@ const handleSubmit = async () => { ...@@ -320,60 +335,59 @@ const handleSubmit = async () => {
// emit('update:show', false) // emit('update:show', false)
// emit('submitSuccess') // emit('submitSuccess')
// }, 1500) // }, 1500)
} catch (error) { } catch (error) {
console.log('提交失败:', error) console.log('提交失败:', error)
uni.showToast({ uni.showToast({
title: '操作失败', title: '操作失败',
icon: 'none', icon: 'none',
duration: 2000 duration: 2000,
}) })
} finally { } finally {
loading.value = false loading.value = false
} }
} }
// 关闭弹窗 // 关闭弹窗
const handleClose = () => { const handleClose = () => {
emit('update:show', false) emit('update:show', false)
emit('close') emit('close')
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.dialog-content { .dialog-content {
padding: 10rpx 30rpx; padding: 10rpx 30rpx;
width: 90%; width: 90%;
max-height: 80vh; max-height: 80vh;
overflow-y: auto; overflow-y: auto;
} }
.section-title { .section-title {
font-size: 32rpx; font-size: 32rpx;
font-weight: bold; font-weight: bold;
color: #333; color: #333;
margin-bottom: 30rpx; margin-bottom: 30rpx;
border-left: 6rpx solid #5DB66F; border-left: 6rpx solid #5db66f;
padding-left: 12rpx; padding-left: 12rpx;
} }
.dialog-buttons { .dialog-buttons {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-top: 50rpx; margin-top: 50rpx;
gap: 20rpx; gap: 20rpx;
} }
.submit-btn, .submit-btn,
.cancel-btn { .cancel-btn {
flex: 1; flex: 1;
} }
.file-upload { .file-upload {
width: 100%; width: 100%;
} }
.file-info { .file-info {
padding: 20rpx; padding: 20rpx;
background-color: #f5f5f5; background-color: #f5f5f5;
border-radius: 8rpx; border-radius: 8rpx;
...@@ -414,10 +428,10 @@ const handleClose = () => { ...@@ -414,10 +428,10 @@ const handleClose = () => {
border-radius: 50%; border-radius: 50%;
} }
} }
} }
// 模态框样式调整 // 模态框样式调整
::v-deep .u-modal { ::v-deep .u-modal {
background: linear-gradient(0deg, rgba(93, 182, 111, 0) 50%, rgba(93, 182, 111, 0.25) 100%); background: linear-gradient(0deg, rgba(93, 182, 111, 0) 50%, rgba(93, 182, 111, 0.25) 100%);
.u-modal__content { .u-modal__content {
...@@ -435,9 +449,9 @@ const handleClose = () => { ...@@ -435,9 +449,9 @@ const handleClose = () => {
color: #333; color: #333;
} }
} }
} }
.ui-button { .ui-button {
padding: 16rpx 0; padding: 16rpx 0;
background-color: #5db66f26; background-color: #5db66f26;
border-radius: 10rpx; border-radius: 10rpx;
...@@ -449,5 +463,5 @@ const handleClose = () => { ...@@ -449,5 +463,5 @@ const handleClose = () => {
line-height: 24rpx; line-height: 24rpx;
color: #16a34a; color: #16a34a;
} }
} }
</style> </style>
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
<view class="codefun-flex-col group_3"> <view class="codefun-flex-col group_3">
<view class="codefun-flex-row codefun-items-center section_2"> <view class="codefun-flex-row codefun-items-center section_2">
<image class="image_6" src="/static/images/codefun/6c5c5a3c082b8c60a307d3a7caee623c.png" /> <image class="image_6" src="/static/images/codefun/6c5c5a3c082b8c60a307d3a7caee623c.png" />
<u-input v-model="pageData.param.fileName" placeholder="请输入文件名称搜索" border="none" <u-input
class="codefun-ml-8" @confirm="handleSearch" /> v-model="pageData.param.fileName"
placeholder="请输入文件名称搜索"
border="none"
class="codefun-ml-8"
@confirm="handleSearch"
/>
</view> </view>
<!-- 资源列表 - 根据图片样式修改 --> <!-- 资源列表 - 根据图片样式修改 -->
...@@ -15,15 +20,17 @@ ...@@ -15,15 +20,17 @@
<view class="resource-main"> <view class="resource-main">
<view class="resource-name">{{ item.fileName }}</view> <view class="resource-name">{{ item.fileName }}</view>
<view class="resource-meta"> <view class="resource-meta">
<text class="resource-size">{{ formatFileSize(item.fileSize) }}</text> <text class="resource-size">{{ item.fileSize }}</text>
<text class="separator">|</text> <text class="separator">|</text>
<text class="download-count">已下载{{ item.downloadCount || 25 }}</text> <text class="download-count">已下载{{ item.downloadCount || 0 }}</text>
<text class="separator">|</text> <text class="separator">|</text>
<text class="upload-time">{{ formatTime(item.createTime) }}</text> <text class="upload-time">{{ formatTime(item.createTime) }}</text>
</view> </view>
</view> </view>
<view class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4" <view
@click.stop="handleDownload(item)"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4"
@click.stop="handleDownload(item)"
>
<text class="font_10">下载</text> <text class="font_10">下载</text>
</view> </view>
<!-- <view class="download-section"> <!-- <view class="download-section">
...@@ -36,221 +43,177 @@ ...@@ -36,221 +43,177 @@
</view> </view>
<!-- 空状态 --> <!-- 空状态 -->
<view class="empty-state" v-if="pageData.list.length === 0"> <!-- <view class="empty-state" v-if="pageData.list.length === 0">
<image class="empty-icon" src="/static/images/empty-file.png" mode="aspectFit"></image> <image class="empty-icon" src="/static/images/empty.png" mode="aspectFit"></image>
<text class="empty-text">暂无资源文件</text> <text class="empty-text">暂无资源</text>
</view> </view> -->
</view> </view>
</z-paging> </z-paging>
<!-- 弹窗组件 --> <!-- 弹窗组件 -->
<save-dialog :show="showDialog" :editData="currentEditData" @update:show="showDialog = $event" <save-dialog
@submitSuccess="handleSubmitSuccess" /> :show="showDialog"
:editData="currentEditData"
@update:show="showDialog = $event"
@submitSuccess="handleSubmitSuccess"
/>
</view> </view>
</template> </template>
<script setup> <script setup>
import { nextTick, reactive, ref } from 'vue' import { nextTick, reactive, ref } from 'vue'
import { onLoad, onNavigationBarButtonTap, onShow } from '@dcloudio/uni-app' import { onLoad, onNavigationBarButtonTap, onShow } from '@dcloudio/uni-app'
// import * as ResourceAPI from '@/api/model/resource' // API留空 import * as API from '@/api/model/wode'
import SaveDialog from './components/save-dialog.vue' import SaveDialog from './components/save-dialog.vue'
const isOnePage = ref(true) const isOnePage = ref(true)
const paging = ref(null) const paging = ref(null)
const pageData = reactive({ const pageData = reactive({
param: { param: {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
fileName: '', fileName: '',
}, },
list: [], list: [],
}) })
function getList() { function getList() {
if (!paging.value) return if (!paging.value) return
// API留空,使用模拟数据 - 根据图片内容调整 // API留空,使用模拟数据 - 根据图片内容调整
setTimeout(() => { API.getResourceList(pageData.param).then((res) => {
const mockData = [ paging.value.complete(res.records)
{ })
id: 1, }
fileName: '水稻种植合同模版',
fileType: 'PDF', function queryList(pageNo, pageSize) {
fileSize: 128000, // 125kb
downloadCount: 25,
createTime: '2025-11-02 14:00'
},
{
id: 2,
fileName: '农药使用指南',
fileType: 'PDF',
fileSize: 128000,
downloadCount: 25,
createTime: '2025-11-02 14:00'
},
{
id: 3,
fileName: '农业补贴列表说明',
fileType: 'PDF',
fileSize: 128000,
downloadCount: 25,
createTime: '2025-11-02 14:00'
},
{
id: 4,
fileName: '小麦种植合同模版',
fileType: 'PDF',
fileSize: 128000,
downloadCount: 25,
createTime: '2025-11-02 14:00'
},
{
id: 5,
fileName: '化肥使用指南',
fileType: 'PDF',
fileSize: 128000,
downloadCount: 25,
createTime: '2025-11-02 14:00'
},
{
id: 6,
fileName: '油茶种植补贴列表说明',
fileType: 'PDF',
fileSize: 128000,
downloadCount: 25,
createTime: '2025-11-02 14:00'
}
]
pageData.total = mockData.length
paging.value.complete(mockData)
}, 500)
}
function queryList(pageNo, pageSize) {
pageData.param.pageNo = pageNo pageData.param.pageNo = pageNo
pageData.param.pageSize = pageSize pageData.param.pageSize = pageSize
getList() getList()
} }
function handleSearch() { function handleSearch() {
pageData.param.pageNo = 1 pageData.param.pageNo = 1
if (paging.value) { if (paging.value) {
paging.value.reload() paging.value.reload()
} }
} }
const showDialog = ref(false) const showDialog = ref(false)
const currentEditData = ref(null) const currentEditData = ref(null)
onNavigationBarButtonTap((_) => { onNavigationBarButtonTap((_) => {
showAddDialog() showAddDialog()
}) })
const showAddDialog = () => { const showAddDialog = () => {
currentEditData.value = null currentEditData.value = null
showDialog.value = true showDialog.value = true
} }
// 格式化时间显示 // 格式化时间显示
const formatTime = (time) => { const formatTime = (time) => {
if (!time) return '' if (!time) return ''
// 如果是完整的时间字符串,可以格式化为图片中的样式 // 如果是完整的时间字符串,可以格式化为图片中的样式
return time.includes(' ') ? time : `${time} 14:00` return time.includes(' ') ? time : `${time} 14:00`
} }
// 下载资源
// 下载资源 const handleDownload = async (resource) => {
const handleDownload = (resource) => { await API.downloadResource({ id: resource.id })
console.log('下载资源:', resource)
uni.showToast({
title: '开始下载',
icon: 'success',
duration: 2000
})
// 模拟下载逻辑
setTimeout(() => {
// 更新下载次数 // 更新下载次数
const index = pageData.list.findIndex(item => item.id === resource.id) const index = pageData.list.findIndex((item) => item.id === resource.id)
if (index !== -1) { if (index !== -1) {
pageData.list[index].downloadCount = (pageData.list[index].downloadCount || 0) + 1 pageData.list[index].downloadCount = (pageData.list[index].downloadCount || 0) + 1
} }
}, 1000) const { downloadResource } = await import('@/utils')
}
// 使用封装的下载方法
const result = await downloadResource(resource)
if (!result.success) {
console.error('下载失败:', result.error)
}
}
// 格式化文件大小 // 格式化文件大小
const formatFileSize = (bytes) => { const formatFileSize = (bytes) => {
if (!bytes) return '125kb' if (!bytes) return '125kb'
const k = 1024 const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB'] const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k)) const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(0)) + sizes[i].toLowerCase() return parseFloat((bytes / Math.pow(k, i)).toFixed(0)) + sizes[i].toLowerCase()
} }
const handleSubmitSuccess = () => { const handleSubmitSuccess = () => {
showDialog.value = false
// 重新加载数据
handleSearch() handleSearch()
} }
</script> </script>
<style lang="scss"> <style lang="scss">
body { body {
background-color: #f8f9fa; background: #e6f5e8;
} }
.page { .page {
background-color: #f8f9fa; background: #e6f5e8;
width: 100%; width: 100%;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
height: 100%; height: 100%;
} }
.group_3 { .group_3 {
padding: 28rpx 24rpx; padding: 28rpx 24rpx;
} }
.section_2 { .section_2 {
padding: 16rpx 20rpx; padding: 16rpx 20rpx;
background-color: #ffffff; background-color: #ffffff;
border-radius: 1998rpx; border-radius: 1998rpx;
margin-bottom: 30rpx; margin-bottom: 30rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06); box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
} }
.image_6 { .image_6 {
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
} }
/* 资源列表样式 - 根据图片样式重写 */ /* 资源列表样式 - 根据图片样式重写 */
.resource-list { .resource-list {
margin-top: 0; margin-top: 0;
}
.resource-item {
background-color: #ffffff;
border-radius: 16rpx; border-radius: 16rpx;
margin-bottom: 20rpx; background-color: #ffffff;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
padding: 0 20rpx;
}
.resource-item {
// border-radius: 16rpx;
// margin-bottom: 20rpx;
overflow: hidden; overflow: hidden;
transition: all 0.3s ease; transition: all 0.3s ease;
border-bottom: 1px solid #e3e3e3;
&:active { &:active {
transform: translateY(2rpx); transform: translateY(2rpx);
box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
} }
} }
.resource-content { .resource-content {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 30rpx 24rpx; padding: 30rpx 24rpx;
} }
.resource-main { .resource-main {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
} }
.resource-name { .resource-name {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
...@@ -261,35 +224,35 @@ body { ...@@ -261,35 +224,35 @@ body {
-webkit-line-clamp: 1; -webkit-line-clamp: 1;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.resource-meta { .resource-meta {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 24rpx; font-size: 20rpx;
color: #999999; color: #999999;
gap: 12rpx; gap: 10rpx;
flex-wrap: wrap; flex-wrap: wrap;
} }
.separator { .separator {
color: #dddddd; color: #dddddd;
font-size: 20rpx; font-size: 20rpx;
} }
.resource-size, .resource-size,
.download-count, .download-count,
.upload-time { .upload-time {
color: #666666; color: #666666;
} }
.download-section { .download-section {
margin-left: 30rpx; margin-left: 30rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.download-btn { .download-btn {
background-color: #5DB66F; background-color: #5db66f;
border: none; border: none;
border-radius: 20rpx; border-radius: 20rpx;
padding: 12rpx 30rpx; padding: 12rpx 30rpx;
...@@ -304,50 +267,49 @@ body { ...@@ -304,50 +267,49 @@ body {
background-color: #4ca85c; background-color: #4ca85c;
transform: scale(0.95); transform: scale(0.95);
} }
} }
.text-wrapper_4 { .text-wrapper_4 {
padding: 16rpx 0; padding: 16rpx 0;
background-color: #5db66f26; background-color: #5db66f26;
border-radius: 400rpx; border-radius: 400rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 136rpx; width: 136rpx;
.font_10 { .font_10 {
font-size: 24rpx; font-size: 24rpx;
line-height: 24rpx; line-height: 24rpx;
color: #16a34a; color: #16a34a;
} }
} }
.btn-text { .btn-text {
color: #ffffff; color: #ffffff;
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
} }
.empty-state { .empty-state {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 120rpx 0; padding: 120rpx 0;
color: #999999; color: #999999;
} }
.empty-icon { .empty-icon {
width: 160rpx; width: 160rpx;
height: 160rpx; height: 160rpx;
margin-bottom: 30rpx; margin-bottom: 30rpx;
opacity: 0.6; opacity: 0.6;
} }
.empty-text { .empty-text {
font-size: 28rpx; font-size: 28rpx;
color: #999999; color: #999999;
} }
/* 响应式调整 */ /* 响应式调整 */
@media (max-width: 375px) { @media (max-width: 375px) {
.resource-content { .resource-content {
padding: 24rpx 20rpx; padding: 24rpx 20rpx;
} }
...@@ -368,5 +330,5 @@ body { ...@@ -368,5 +330,5 @@ body {
.btn-text { .btn-text {
font-size: 26rpx; font-size: 26rpx;
} }
} }
</style> </style>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue' import { reactive, ref } from 'vue'
import { onPullDownRefresh } from '@dcloudio/uni-app' import { onPullDownRefresh } from '@dcloudio/uni-app'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { closeSplashscreenAndChechUpgrade } from '@/utils/upgrade' import { closeSplashscreenAndChechUpgrade } from '@/utils/upgrade'
import * as WeatherAPI from '@/api/model/weather' import * as WeatherAPI from '@/api/model/weather'
import * as HomeAPI from '@/api/model/home' import * as HomeAPI from '@/api/model/home'
import { useDictStore } from '@/store/modules/dict' import * as UserAPI from '@/api/model/userInfo'
import { useDictStore } from '@/store/modules/dict'
const dictStore = useDictStore()
const model = reactive({ const dictStore = useDictStore()
const model = reactive({
// 湖南省人民政府 // 湖南省人民政府
location: '112.982931,28.116698', location: '112.982931,28.116698',
}) })
// 位置获取频率控制
const lastLocationTime = ref(0)
const LOCATION_CACHE_TIME = 5 * 60 * 1000 // 5分钟缓存时间
onLoad(() => { onLoad(() => {
// 关闭启动页并检查更新 // 关闭启动页并检查更新
closeSplashscreenAndChechUpgrade() closeSplashscreenAndChechUpgrade()
}) })
onShow(() => { onShow(() => {
// 检查是否需要重新获取位置(5分钟缓存)
const currentTime = Date.now()
const cachedLocation = uni.getStorageSync('location')
// 添加延迟调用,避免频繁触发
setTimeout(() => {
if (
cachedLocation &&
cachedLocation.lon &&
cachedLocation.lat &&
currentTime - lastLocationTime.value < LOCATION_CACHE_TIME
) {
// 使用缓存的位置数据
console.log('使用缓存的位置数据')
pageData.weather.lon = cachedLocation.lon
pageData.weather.lat = cachedLocation.lat
model.location = `${cachedLocation.lon},${cachedLocation.lat}`
// 更新详细地址(仅在缓存存在时)
if (cachedLocation.lat && cachedLocation.lon) {
UserAPI.location({ lat: cachedLocation.lat, lon: cachedLocation.lon })
.then((res) => {
console.log('UserAPI.location', res)
pageData.weather.detailedLocation =
res.province +
'-' +
res.city +
'-' +
res.country +
'-' +
res.road +
'-' +
res.town +
'-' +
res.address
})
.catch(() => {
// 地址获取失败时使用默认显示
pageData.weather.detailedLocation = '获取中'
})
}
reloadWeather()
} else {
// 需要重新获取位置
uni.getLocation({ uni.getLocation({
type: 'wgs84', type: 'wgs84',
success(res) { success(res) {
...@@ -26,9 +76,40 @@ onShow(() => { ...@@ -26,9 +76,40 @@ onShow(() => {
console.log(`纬度:${res.latitude}`) console.log(`纬度:${res.latitude}`)
if (res.longitude === 0 || res.latitude === 0) { if (res.longitude === 0 || res.latitude === 0) {
console.log('无效的位置数据,使用缓存')
if (cachedLocation && cachedLocation.lon && cachedLocation.lat) {
pageData.weather.lon = cachedLocation.lon
pageData.weather.lat = cachedLocation.lat
model.location = `${cachedLocation.lon},${cachedLocation.lat}`
reloadWeather()
}
return return
} }
// 更新最后获取位置的时间
lastLocationTime.value = currentTime
UserAPI.location({ lat: res.latitude, lon: res.longitude })
.then((res) => {
console.log('UserAPI.location', res)
pageData.weather.detailedLocation =
res.province +
'-' +
res.city +
'-' +
res.country +
'-' +
res.road +
'-' +
res.town +
'-' +
res.address
})
.catch(() => {
// 地址获取失败时使用默认显示
pageData.weather.detailedLocation = '获取中'
})
pageData.weather.lon = res.longitude pageData.weather.lon = res.longitude
pageData.weather.lat = res.latitude pageData.weather.lat = res.latitude
uni.setStorageSync('location', { uni.setStorageSync('location', {
...@@ -41,13 +122,25 @@ onShow(() => { ...@@ -41,13 +122,25 @@ onShow(() => {
}, },
fail(res) { fail(res) {
console.log('获取位置失败:', res) console.log('获取位置失败:', res)
// 即使失败也尝试使用缓存数据
if (cachedLocation && cachedLocation.lon && cachedLocation.lat) {
console.log('获取位置失败,使用缓存数据')
pageData.weather.lon = cachedLocation.lon
pageData.weather.lat = cachedLocation.lat
model.location = `${cachedLocation.lon},${cachedLocation.lat}`
reloadWeather()
} else {
reloadWeather() reloadWeather()
uni.showToast({ uni.showToast({
title: '获取地址失败,将导致部分功能不可用', title: '获取地址失败,将导致部分功能不可用',
icon: 'none', icon: 'none',
}) })
}
}, },
}) })
}
}, 300) // 延迟300毫秒执行,避免频繁触发
// 获取字典列表 // 获取字典列表
dictStore.setDictList() dictStore.setDictList()
...@@ -63,17 +156,17 @@ onShow(() => { ...@@ -63,17 +156,17 @@ onShow(() => {
getServiceStatsList() getServiceStatsList()
// 农技课堂 // 农技课堂
getAgricultureClassList() getAgricultureClassList()
}) })
// 下拉刷新 // 下拉刷新
onPullDownRefresh(() => { onPullDownRefresh(() => {
setTimeout(function () { setTimeout(function () {
uni.stopPullDownRefresh() uni.stopPullDownRefresh()
Message.toast('刷新成功') Message.toast('刷新成功')
}, 1000) }, 1000)
}) })
function getWeatherRecommend(weather: string) { function getWeatherRecommend(weather: string) {
switch (weather) { switch (weather) {
case '晴': case '晴':
return '宜喷药' return '宜喷药'
...@@ -86,10 +179,10 @@ function getWeatherRecommend(weather: string) { ...@@ -86,10 +179,10 @@ function getWeatherRecommend(weather: string) {
default: default:
return '无建议' return '无建议'
} }
} }
// 刷新天气信息 // 刷新天气信息
function reloadWeather() { function reloadWeather() {
WeatherAPI.now(model.location).then((res) => { WeatherAPI.now(model.location).then((res) => {
console.log('WeatherAPI.now', res) console.log('WeatherAPI.now', res)
...@@ -109,10 +202,10 @@ function reloadWeather() { ...@@ -109,10 +202,10 @@ function reloadWeather() {
} }
}) })
}) })
} }
// 页面数据 // 页面数据
const pageData = reactive({ const pageData = reactive({
// 顶部标题和搜索 // 顶部标题和搜索
header: { header: {
title: $app.name, title: $app.name,
...@@ -123,6 +216,7 @@ const pageData = reactive({ ...@@ -123,6 +216,7 @@ const pageData = reactive({
weather: { weather: {
icon: '100', icon: '100',
location: '长沙', location: '长沙',
detailedLocation: '获取中', // 详细位置信息
date: `${dayjs().format('MM-DD')} ${dayjs().toLunarDay().getName()}`, date: `${dayjs().format('MM-DD')} ${dayjs().toLunarDay().getName()}`,
temperature: '-°C', temperature: '-°C',
condition: '晴|适宜喷药', condition: '晴|适宜喷药',
...@@ -144,8 +238,12 @@ const pageData = reactive({ ...@@ -144,8 +238,12 @@ const pageData = reactive({
// 新闻资讯 // 新闻资讯
newsItems: [ newsItems: [
{ id: 1, type: '最新', title: '积极防范持续高温对农作物的影响', date: '2025-08-29' }, {
{ id: 2, type: '预警', title: '', date: '2025-08-29' }, id: 1,
type: '最新预警',
title: '积极防范持续高温对农作物的影响',
date: dayjs().format('YYYY-MM-DD'),
},
], ],
// 农产品行情 // 农产品行情
...@@ -213,9 +311,9 @@ const pageData = reactive({ ...@@ -213,9 +311,9 @@ const pageData = reactive({
videoList: [], videoList: [],
}, },
current: 0, current: 0,
}) })
function getServiceItems() { function getServiceItems() {
HomeAPI.zoneList({ HomeAPI.zoneList({
pageNo: 1, pageNo: 1,
pageSize: 4, pageSize: 4,
...@@ -226,8 +324,8 @@ function getServiceItems() { ...@@ -226,8 +324,8 @@ function getServiceItems() {
pageData.serviceItems = [] pageData.serviceItems = []
pageData.serviceItems = records pageData.serviceItems = records
}) })
} }
function getMenuItems() { function getMenuItems() {
HomeAPI.zoneList({ HomeAPI.zoneList({
pageNo: 1, pageNo: 1,
pageSize: 4, pageSize: 4,
...@@ -238,8 +336,8 @@ function getMenuItems() { ...@@ -238,8 +336,8 @@ function getMenuItems() {
pageData.menuItems = [] pageData.menuItems = []
pageData.menuItems = records pageData.menuItems = records
}) })
} }
function getWarningInfo() { function getWarningInfo() {
if (!pageData.weather.lon || !pageData.weather.lat) { if (!pageData.weather.lon || !pageData.weather.lat) {
return return
} }
...@@ -250,8 +348,8 @@ function getWarningInfo() { ...@@ -250,8 +348,8 @@ function getWarningInfo() {
}).then((res) => { }).then((res) => {
pageData.weather.warning = res[0].criteria pageData.weather.warning = res[0].criteria
}) })
} }
function getProductMarketList() { function getProductMarketList() {
HomeAPI.productMarketList({ HomeAPI.productMarketList({
status: 1, status: 1,
}).then((res) => { }).then((res) => {
...@@ -269,16 +367,16 @@ function getProductMarketList() { ...@@ -269,16 +367,16 @@ function getProductMarketList() {
} }
}) })
}) })
} }
function getServiceStatsList() { function getServiceStatsList() {
HomeAPI.serviceStatsList({ HomeAPI.serviceStatsList({
status: 1, status: 1,
}).then((res) => { }).then((res) => {
const { records } = res const { records } = res
pageData.serviceStats = records pageData.serviceStats = records
}) })
} }
function getAgricultureClassList() { function getAgricultureClassList() {
HomeAPI.agricultureClassList({ HomeAPI.agricultureClassList({
status: 1, status: 1,
}).then((res) => { }).then((res) => {
...@@ -286,46 +384,46 @@ function getAgricultureClassList() { ...@@ -286,46 +384,46 @@ function getAgricultureClassList() {
pageData.agricultureClass.videoList = records pageData.agricultureClass.videoList = records
pageData.agricultureClass.title = records[0]?.title pageData.agricultureClass.title = records[0]?.title
}) })
} }
// 菜单点击事件 // 菜单点击事件
function onMenuItemClick(item: any) { function onMenuItemClick(item: any) {
console.log('点击菜单项:', item) console.log('点击菜单项:', item)
// 在这里添加具体的菜单点击逻辑 // 在这里添加具体的菜单点击逻辑
} }
// 农产品关注点击事件 // 农产品关注点击事件
function onProductFollowClick(product: any) { function onProductFollowClick(product: any) {
console.log('点击关注农产品:', product) console.log('点击关注农产品:', product)
// 在这里添加具体的关注逻辑 // 在这里添加具体的关注逻辑
} }
// 查看更多农技课堂 // 查看更多农技课堂
function onViewMoreClass() { function onViewMoreClass() {
console.log('查看全部农技课堂') console.log('查看全部农技课堂')
// 在这里添加具体的查看逻辑 // 在这里添加具体的查看逻辑
} }
// 轮播视频切换的时候触发 // 轮播视频切换的时候触发
function handleChangeVideo(e: any) { function handleChangeVideo(e: any) {
// console.log('切换视频', e.detail.current) // console.log('切换视频', e.detail.current)
pageData.current = e.detail.current pageData.current = e.detail.current
pageData.agricultureClass.title = pageData.agricultureClass.videoList[pageData.current]?.title pageData.agricultureClass.title = pageData.agricultureClass.videoList[pageData.current]?.title
} }
// 获取视频时长 // 获取视频时长
function handleMetadataLoaded(e: any) { function handleMetadataLoaded(e: any) {
pageData.agricultureClass.time = e.target.duration pageData.agricultureClass.time = e.target.duration
} }
// 解决轮播视频切换时,上一个视频不停止播放的问题 // 解决轮播视频切换时,上一个视频不停止播放的问题
function handleVideoPlay(currentIndex) { function handleVideoPlay(currentIndex) {
pageData.agricultureClass.videoList.forEach((_, index) => { pageData.agricultureClass.videoList.forEach((_, index) => {
if (index !== currentIndex) { if (index !== currentIndex) {
const videoContext = uni.createVideoContext(`video${index}`) const videoContext = uni.createVideoContext(`video${index}`)
videoContext.pause() videoContext.pause()
} }
}) })
} }
</script> </script>
<template> <template>
...@@ -342,14 +440,37 @@ function handleVideoPlay(currentIndex) { ...@@ -342,14 +440,37 @@ function handleVideoPlay(currentIndex) {
<view class="codefun-flex-col"> <view class="codefun-flex-col">
<view class="codefun-flex-col codefun-self-stretch group_4"> <view class="codefun-flex-col codefun-self-stretch group_4">
<view class="codefun-flex-col section_3"> <view class="codefun-flex-col section_3">
<view class="codefun-flex-row codefun-justify-between"> <view class="codefun-flex-row codefun-justify-between" style="align-items: center">
<view class="codefun-flex-row codefun-items-center"> <view
class="codefun-flex-row codefun-items-center codefun-relative codefun-overflow-hidden"
>
<!-- 定位图标 -->
<image
class="codefun-shrink-0 image_13 codefun-mr-4"
src="/static/images/local-address.png"
/>
<!-- 滚动位置信息 -->
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper"> class="codefun-flex-row codefun-items-center codefun-overflow-hidden text-wrapper_2"
<text class="font_2 text_4">{{ pageData.weather.location }}</text> style="width: 400rpx"
>
<up-notice-bar
v-if="pageData.weather.detailedLocation != '获取中'"
icon="false"
bgColor="#FFFFFF00"
color="#5db66f"
class="text_3"
:text="pageData.weather.detailedLocation"
scrollable
:speed="50"
style="width: 100%; height: auto"
></up-notice-bar>
<view v-else class="text_3">{{ pageData.weather.detailedLocation }}</view>
</view> </view>
<image class="image_6 codefun-ml-6" <!-- <image
src="/static/images/codefun/a2f290fb1b65d093b844e73ddae1aed9.png" /> class="image_6 codefun-ml-6"
src="/static/images/codefun/a2f290fb1b65d093b844e73ddae1aed9.png"
/> -->
</view> </view>
<view class="codefun-flex-col codefun-justify-start codefun-items-start text-wrapper_2"> <view class="codefun-flex-col codefun-justify-start codefun-items-start text-wrapper_2">
<text class="text_3">{{ pageData.weather.date }}</text> <text class="text_3">{{ pageData.weather.date }}</text>
...@@ -357,8 +478,10 @@ function handleVideoPlay(currentIndex) { ...@@ -357,8 +478,10 @@ function handleVideoPlay(currentIndex) {
</view> </view>
<view class="codefun-flex-row group_5"> <view class="codefun-flex-row group_5">
<view class="codefun-flex-row codefun-items-center group_8"> <view class="codefun-flex-row codefun-items-center group_8">
<image class="codefun-shrink-0 image_8" <image
:src="`/static/images/weather/${pageData.weather.icon}.svg`" /> class="codefun-shrink-0 image_8"
:src="`/static/images/weather/${pageData.weather.icon}.svg`"
/>
<view class="codefun-flex-col codefun-items-start codefun-flex-1 codefun-ml-10"> <view class="codefun-flex-col codefun-items-start codefun-flex-1 codefun-ml-10">
<text class="text_5">{{ pageData.weather.temperature }}</text> <text class="text_5">{{ pageData.weather.temperature }}</text>
<text class="font_2 text_8 !text-24rpx codefun-mt-16">{{ <text class="font_2 text_8 !text-24rpx codefun-mt-16">{{
...@@ -378,58 +501,78 @@ function handleVideoPlay(currentIndex) { ...@@ -378,58 +501,78 @@ function handleVideoPlay(currentIndex) {
src="/static/images/codefun/c785818f2c08b7682aa5188542b2dede.png" src="/static/images/codefun/c785818f2c08b7682aa5188542b2dede.png"
/> --> /> -->
<image class="image_7" :src="`/static/images/weather/${forecast.icon}.svg`" <image
v-for="forecast in pageData.weather.forecast" :key="forecast.day" /> class="image_7"
:src="`/static/images/weather/${forecast.icon}.svg`"
v-for="forecast in pageData.weather.forecast"
:key="forecast.day"
/>
</view> </view>
<view class="codefun-flex-row codefun-justify-between codefun-items-center group_9"> <view class="codefun-flex-row codefun-justify-between codefun-items-center group_9">
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_9"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_9"
>
<text class="font_3 text_6">{{ pageData.weather.forecast[0].day }}</text> <text class="font_3 text_6">{{ pageData.weather.forecast[0].day }}</text>
</view> </view>
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_3"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_3"
>
<text class="font_3 text_52">{{ pageData.weather.forecast[1].day }}</text> <text class="font_3 text_52">{{ pageData.weather.forecast[1].day }}</text>
</view> </view>
<text class="font_3 text_7">{{ pageData.weather.forecast[2].day }}</text> <text class="font_3 text_7">{{ pageData.weather.forecast[2].day }}</text>
</view> </view>
<view class="codefun-flex-row codefun-justify-center"> <view class="codefun-flex-row codefun-justify-center">
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4"
>
<text class="font_4 text_9">{{ pageData.weather.forecast[0].temp }}</text> <text class="font_4 text_9">{{ pageData.weather.forecast[0].temp }}</text>
</view> </view>
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_1 ml-17"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_1 ml-17"
>
<text class="font_4 text_10">{{ pageData.weather.forecast[1].temp }}</text> <text class="font_4 text_10">{{ pageData.weather.forecast[1].temp }}</text>
</view> </view>
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4 ml-17"> class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_4 ml-17"
>
<text class="font_4 text_9">{{ pageData.weather.forecast[2].temp }}</text> <text class="font_4 text_9">{{ pageData.weather.forecast[2].temp }}</text>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="codefun-flex-row section_4" v-if="pageData.weather.warning"> <view class="codefun-flex-row section_4" v-if="pageData.weather.warning">
<image class="codefun-shrink-0 image_10" <image
src="/static/images/codefun/344155285176a7ac7ccd670a2a1daf19.png" /> class="codefun-shrink-0 image_10"
src="/static/images/codefun/344155285176a7ac7ccd670a2a1daf19.png"
/>
<view <view
class="codefun-flex-col codefun-justify-start codefun-shrink-0 text-wrapper_5 codefun-ml-6"> class="codefun-flex-col codefun-justify-start codefun-shrink-0 text-wrapper_5 codefun-ml-6"
>
<text class="text_12">{{ pageData.weather.warning }}</text> <text class="text_12">{{ pageData.weather.warning }}</text>
</view> </view>
</view> </view>
</view> </view>
<view class="codefun-flex-col codefun-relative section_5"> <view class="codefun-flex-col codefun-relative section_5">
<view class="codefun-flex-row"> <view class="codefun-flex-row">
<view v-show="item.status" v-for="item in pageData.menuItems" :key="item.id" <view
v-show="item.status"
v-for="item in pageData.menuItems"
:key="item.id"
class="codefun-flex-col codefun-items-center group_10" class="codefun-flex-col codefun-items-center group_10"
@click="onMenuItemClick(item)"> @click="onMenuItemClick(item)"
>
<image class="image_11" :src="item.icon_url" /> <image class="image_11" :src="item.icon_url" />
<text class="font_2 mt-11">{{ item.name }}</text> <text class="font_2 mt-11">{{ item.name }}</text>
</view> </view>
</view> </view>
<view class="codefun-flex-row codefun-mt-20"> <view class="codefun-flex-row codefun-mt-20">
<view v-show="item.status" v-for="item in pageData.serviceItems" :key="item.id" <view
v-show="item.status"
v-for="item in pageData.serviceItems"
:key="item.id"
class="codefun-flex-col codefun-items-center group_10" class="codefun-flex-col codefun-items-center group_10"
@click="onMenuItemClick(item)"> @click="onMenuItemClick(item)"
>
<image class="image_11" :src="item.icon_url" /> <image class="image_11" :src="item.icon_url" />
<text class="font_2 mt-11">{{ item.name }}</text> <text class="font_2 mt-11">{{ item.name }}</text>
</view> </view>
...@@ -437,13 +580,17 @@ function handleVideoPlay(currentIndex) { ...@@ -437,13 +580,17 @@ function handleVideoPlay(currentIndex) {
</view> </view>
<view class="codefun-flex-row codefun-justify-between codefun-items-center section_6"> <view class="codefun-flex-row codefun-justify-between codefun-items-center section_6">
<view class="codefun-flex-col"> <view class="codefun-flex-col">
<view class="codefun-flex-row codefun-items-baseline"> <view class="codefun-flex-row codefun-items-baseline" style="align-items: center">
<text class="font_5 text_17">{{ pageData.newsItems[0].type }}</text> <view class="font_5 text_17">{{ pageData.newsItems[0].type }}</view>
<text class="font_2 text_18 ml-11">{{ pageData.newsItems[0].title }}</text> <view
class="codefun-flex-row"
style="flex-flow: column; justify-content: space-around; height: 90rpx"
>
<view class="font_2 text_18 ml-11">{{ pageData.newsItems[0].title }}</view>
<text class="text-26 text_20 text_21 ml-11">{{
pageData.newsItems[0].date
}}</text>
</view> </view>
<view class="codefun-flex-row codefun-items-baseline">
<text class="font_5 text_19">{{ pageData.newsItems[1].type }}</text>
<text class="text-26 text_20 text_21 ml-11">{{ pageData.newsItems[1].date }}</text>
</view> </view>
</view> </view>
<image class="image_13" src="/static/images/codefun/64d85a99ca3de5fab9ce0e8dc71aa791.png" /> <image class="image_13" src="/static/images/codefun/64d85a99ca3de5fab9ce0e8dc71aa791.png" />
...@@ -456,32 +603,47 @@ function handleVideoPlay(currentIndex) { ...@@ -456,32 +603,47 @@ function handleVideoPlay(currentIndex) {
<!-- <text class="font_7 text_22">{{ pageData.productMarket.updateTime }}</text> --> <!-- <text class="font_7 text_22">{{ pageData.productMarket.updateTime }}</text> -->
</view> </view>
<view class="codefun-flex-row equal-division section_8"> <view class="codefun-flex-row equal-division section_8">
<view v-for="(product, index) in pageData.productMarket.products" :key="product.id" <view
class="codefun-flex-col group_13" :class="{ v-for="(product, index) in pageData.productMarket.products"
:key="product.id"
class="codefun-flex-col group_13"
:class="{
group_17: index === 0, group_17: index === 0,
group_39: index === 1, group_39: index === 1,
group_21: index === 2, group_21: index === 2,
}"> }"
>
<view <view
class="codefun-flex-col codefun-justify-start codefun-items-start codefun-self-center codefun-relative group_1"> class="codefun-flex-col codefun-justify-start codefun-items-start codefun-self-center codefun-relative group_1"
>
<text class="font_8 text_23">{{ product.name }}</text> <text class="font_8 text_23">{{ product.name }}</text>
<text class="font_9 text_23" :class="`pos${index > 0 ? `_${index + 1}` : ''}`">{{ <text class="font_9 text_23" :class="`pos${index > 0 ? `_${index + 1}` : ''}`"
product.current_price >¥{{ product.current_price }}</text
}}</text> >
</view> </view>
<view class="codefun-flex-row codefun-items-center codefun-self-stretch" :class="{ <view
class="codefun-flex-row codefun-items-center codefun-self-stretch"
:class="{
section_10: product.isUp, section_10: product.isUp,
section_11: !product.isUp, section_11: !product.isUp,
}"> }"
<image class="codefun-shrink-0 image_14" :src="product.isUp >
<image
class="codefun-shrink-0 image_14"
:src="
product.isUp
? '/static/images/codefun/c6f953be58ac3e9752ab9475a2a53c14.png' ? '/static/images/codefun/c6f953be58ac3e9752ab9475a2a53c14.png'
: '/static/images/codefun/c7e797cc626699dcc8999a72145e9f8b.png' : '/static/images/codefun/c7e797cc626699dcc8999a72145e9f8b.png'
" /> "
<text class="font_10 ml-3" :class="{ />
<text
class="font_10 ml-3"
:class="{
text_25: product.isUp, text_25: product.isUp,
text_24: !product.isUp, text_24: !product.isUp,
text_26: !product.isUp, text_26: !product.isUp,
}"> }"
>
{{ `${product.isUp ? '' : '-'}${product.percent}%` }} {{ `${product.isUp ? '' : '-'}${product.percent}%` }}
</text> </text>
</view> </view>
...@@ -497,14 +659,20 @@ function handleVideoPlay(currentIndex) { ...@@ -497,14 +659,20 @@ function handleVideoPlay(currentIndex) {
<!-- <text class="font_7 text_20 text_29">实时数据</text> --> <!-- <text class="font_7 text_20 text_29">实时数据</text> -->
</view> </view>
<view class="codefun-flex-row equal-division_2 group_16"> <view class="codefun-flex-row equal-division_2 group_16">
<view v-for="stat in pageData.serviceStats" :key="stat.id"
class="codefun-flex-col section_12 section_19">
<view <view
class="codefun-flex-row codefun-justify-center codefun-items-center codefun-self-stretch codefun-relative group_27"> v-for="stat in pageData.serviceStats"
:key="stat.id"
class="codefun-flex-col section_12 section_19"
>
<view
class="codefun-flex-row codefun-justify-center codefun-items-center codefun-self-stretch codefun-relative group_27"
>
<image class="image_5 mr-1" :class="`pos_${stat.id}`" :src="stat.icon" /> <image class="image_5 mr-1" :class="`pos_${stat.id}`" :src="stat.icon" />
<text class="font_13" <text
:class="`text_${stat.id === 1 ? 30 : stat.id === 2 ? 1 : stat.id > 4 ? 46 : 37}`">{{ class="font_13"
stat.name }}</text> :class="`text_${stat.id === 1 ? 30 : stat.id === 2 ? 1 : stat.id > 4 ? 46 : 37}`"
>{{ stat.name }}</text
>
</view> </view>
<view class="codefun-flex-row codefun-justify-center codefun-items-baseline mt-11 group_30"> <view class="codefun-flex-row codefun-justify-center codefun-items-baseline mt-11 group_30">
<text class="font_12 text_37">{{ stat.num }}</text> <text class="font_12 text_37">{{ stat.num }}</text>
...@@ -517,26 +685,44 @@ function handleVideoPlay(currentIndex) { ...@@ -517,26 +685,44 @@ function handleVideoPlay(currentIndex) {
<!-- <text class="font_7 text_33" @click="onViewMoreClass">查看全部</text> --> <!-- <text class="font_7 text_33" @click="onViewMoreClass">查看全部</text> -->
</view> </view>
<view class="codefun-flex-col section_13"> <view class="codefun-flex-col section_13">
<fui-swiper-dot :items="pageData.agricultureClass.videoList" :current="pageData.current" :styles="{ <fui-swiper-dot
:items="pageData.agricultureClass.videoList"
:current="pageData.current"
:styles="{
height: 10, height: 10,
activeWidth: 40, activeWidth: 40,
background: '#dff0e2', background: '#dff0e2',
activeBackground: '#5db66f', activeBackground: '#5db66f',
bottom: 10, bottom: 10,
}"> }"
<swiper class="fui-banner__wrap" circular :indicator-dots="false" autoplay :interval="4000" >
:duration="150" @change="handleChangeVideo"> <swiper
class="fui-banner__wrap"
circular
:indicator-dots="false"
autoplay
:interval="4000"
:duration="150"
@change="handleChangeVideo"
>
<swiper-item v-for="(video, index) in pageData.agricultureClass.videoList" :key="index"> <swiper-item v-for="(video, index) in pageData.agricultureClass.videoList" :key="index">
<video :id="`video${index}`" :src="video.media_video" :poster="video.cover_image" <video
:controls="false" style="width: 654rpx; height: 358rpx" :id="`video${index}`"
@loadedmetadata="handleMetadataLoaded" @play="handleVideoPlay(index)"></video> :src="video.media_video"
:poster="video.cover_image"
:controls="false"
style="width: 654rpx; height: 358rpx"
@loadedmetadata="handleMetadataLoaded"
@play="handleVideoPlay(index)"
></video>
</swiper-item> </swiper-item>
</swiper> </swiper>
</fui-swiper-dot> </fui-swiper-dot>
<view class="describe"> <view class="describe">
<text class="codefun-self-start font text_34">{{ pageData.agricultureClass.title }}</text> <text class="codefun-self-start font text_34">{{ pageData.agricultureClass.title }}</text>
<view <view
class="codefun-flex-row codefun-justify-between codefun-items-center codefun-self-stretch mt-13"> class="codefun-flex-row codefun-justify-between codefun-items-center codefun-self-stretch mt-13"
>
<!-- <view class="codefun-flex-row codefun-items-center"> <!-- <view class="codefun-flex-row codefun-items-center">
<image <image
class="codefun-shrink-0 image_15" class="codefun-shrink-0 image_15"
...@@ -554,43 +740,43 @@ function handleVideoPlay(currentIndex) { ...@@ -554,43 +740,43 @@ function handleVideoPlay(currentIndex) {
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.ml-17 { .ml-17 {
margin-left: 34rpx; margin-left: 34rpx;
} }
.ml-43 { .ml-43 {
margin-left: 86rpx; margin-left: 86rpx;
} }
.mt-13 { .mt-13 {
margin-top: 26rpx; margin-top: 26rpx;
} }
.ml-11 { .ml-11 {
margin-left: 22rpx; margin-left: 22rpx;
} }
.ml-3 { .ml-3 {
margin-left: 6rpx; margin-left: 6rpx;
} }
.ml-19 { .ml-19 {
margin-left: 38rpx; margin-left: 38rpx;
} }
.mt-11 { .mt-11 {
margin-top: 22rpx; margin-top: 22rpx;
} }
.ml-5 { .ml-5 {
margin-left: 10rpx; margin-left: 10rpx;
} }
.mt-3 { .mt-3 {
margin-top: 6rpx; margin-top: 6rpx;
} }
.page { .page {
background-color: #e6f5e8; background-color: #e6f5e8;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 100%; width: 100%;
...@@ -662,10 +848,10 @@ function handleVideoPlay(currentIndex) { ...@@ -662,10 +848,10 @@ function handleVideoPlay(currentIndex) {
padding-left: 28rpx; padding-left: 28rpx;
.group_4 { .group_4 {
// height: 864rpx; // height: 864rpx;
.section_3 { .section_3 {
margin-right: 28rpx; width: 694rpx;
// margin-right: 28rpx;
padding: 20rpx 28rpx 58rpx; padding: 20rpx 28rpx 58rpx;
background-image: linear-gradient(180deg, #dcfce7 0%, #f8fef9 100%); background-image: linear-gradient(180deg, #dcfce7 0%, #f8fef9 100%);
border-radius: 16rpx; border-radius: 16rpx;
...@@ -690,15 +876,13 @@ function handleVideoPlay(currentIndex) { ...@@ -690,15 +876,13 @@ function handleVideoPlay(currentIndex) {
.text-wrapper_2 { .text-wrapper_2 {
overflow: hidden; overflow: hidden;
width: 140rpx; // width: 140rpx;
height: 40rpx; // height: 40rpx;
.text_3 { .text_3 {
margin-left: 9.28rpx; margin-left: 9.28rpx;
color: #5db66f; color: #5db66f;
font-size: 24rpx; font-size: 28rpx;
line-height: 40rpx;
width: 164rpx;
} }
} }
...@@ -940,8 +1124,14 @@ function handleVideoPlay(currentIndex) { ...@@ -940,8 +1124,14 @@ function handleVideoPlay(currentIndex) {
} }
.text_17 { .text_17 {
width: 80rpx;
font-size: 30rpx; font-size: 30rpx;
font-family: alimamashuheiti; font-family: alimamashuheiti;
word-break: break-all;
white-space: normal;
line-height: 1.2;
display: block;
text-align: center;
} }
.text_18 { .text_18 {
...@@ -957,15 +1147,16 @@ function handleVideoPlay(currentIndex) { ...@@ -957,15 +1147,16 @@ function handleVideoPlay(currentIndex) {
.text_21 { .text_21 {
line-height: 17.18rpx; line-height: 17.18rpx;
} }
}
.image_13 { .image_13 {
border-radius: 16rpx; border-radius: 16rpx;
mix-blend-mode: NOTTHROUGH; mix-blend-mode: NOTTHROUGH;
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
} }
.codefun-mr-4 {
margin-right: 10rpx;
} }
.font_4 { .font_4 {
font-size: 20rpx; font-size: 20rpx;
line-height: 18.3rpx; line-height: 18.3rpx;
...@@ -1076,7 +1267,7 @@ function handleVideoPlay(currentIndex) { ...@@ -1076,7 +1267,7 @@ function handleVideoPlay(currentIndex) {
} }
.font_10 { .font_10 {
font-size: 20rpx; font-size: 24rpx;
line-height: 56rpx; line-height: 56rpx;
color: #f44336; color: #f44336;
} }
...@@ -1431,5 +1622,13 @@ function handleVideoPlay(currentIndex) { ...@@ -1431,5 +1622,13 @@ function handleVideoPlay(currentIndex) {
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
} }
} }
.u-notice-bar {
padding: unset !important;
font-size: 28rpx !important;
}
:v-deep .u-notice-bar {
padding: unset !important;
font-size: 28rpx;
}
</style> </style>
...@@ -248,118 +248,21 @@ function onResourceClick(resource: any) { ...@@ -248,118 +248,21 @@ function onResourceClick(resource: any) {
} }
// 资源下载点击事件 // 资源下载点击事件
function onDownloadClick(e, resource: any) { async function onDownloadClick(e, resource: any) {
// 阻止事件冒泡 // 阻止事件冒泡
e?.stopPropagation() e?.stopPropagation()
// 显示加载提示 const { downloadResource } = await import('@/utils')
uni.showLoading({
title: '下载中...',
mask: true,
})
// 判断是否为H5平台
/* #ifdef H5 */
downloadFileForWeb(resource)
/* #endif */
/* #ifndef H5 */
downloadFileForNative(resource)
/* #endif */
}
// H5平台下载文件函数
function downloadFileForWeb(resource: any) {
const url = resource.fileSrc
// 创建一个临时的a标签用于下载 // 使用封装的下载方法
const link = document.createElement('a') const result = await downloadResource(resource)
link.href = url
link.download = resource.fileName || 'download' // 设置下载文件名
link.style.display = 'none'
// 添加到文档并触发点击 if (!result.success) {
document.body.appendChild(link) console.error('下载失败:', result.error)
link.click() }
// 清理
document.body.removeChild(link)
uni.hideLoading()
uni.showToast({
title: '开始下载',
icon: 'success',
duration: 1500
})
} }
// 原生平台下载文件函数
function downloadFileForNative(resource: any) {
uni.downloadFile({
url: resource.fileSrc,
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
uni.hideLoading()
uni.showToast({
title: '下载成功',
icon: 'success',
duration: 1500
})
// 提示用户文件已保存
uni.showModal({
title: '下载完成',
content: `文件已保存至: ${saveRes.savedFilePath}\n是否立即打开?`,
success: (modalRes) => {
if (modalRes.confirm) {
uni.openDocument({
filePath: saveRes.savedFilePath,
fileType: resource.fileType?.toString() || '',
showMenu: true,
fail: () => {
uni.showToast({
title: '无法打开文件',
icon: 'error',
duration: 1500
})
},
})
}
},
})
},
fail: (err) => {
uni.hideLoading()
console.error('保存文件失败:', err)
uni.showToast({
title: '保存文件失败',
icon: 'error',
duration: 1500
})
},
})
} else {
uni.hideLoading()
uni.showToast({
title: `下载失败,状态码: ${res.statusCode}`,
icon: 'error',
duration: 1500
})
}
},
fail: (err) => {
uni.hideLoading()
console.error('下载失败:', err)
uni.showToast({
title: '网络错误,下载失败',
icon: 'error',
duration: 1500
})
},
})
}
// 查看所有资源 // 查看所有资源
function onViewAllResources() { function onViewAllResources() {
......
/**
* 下载工具类
* 提供跨平台的文件下载功能,支持H5和原生平台
*/
/**
* 文件下载选项接口
*/
export interface DownloadOptions {
/** 文件下载URL */
url: string
/** 文件名 */
fileName?: string
/** 文件类型 */
fileType?: string
/** 文件大小 */
fileSize?: string
/** 是否显示下载进度 */
showProgress?: boolean
}
/**
* 下载结果接口
*/
export interface DownloadResult {
/** 是否成功 */
success: boolean
/** 错误信息 */
error?: string
/** 文件保存路径(仅原生平台) */
savedFilePath?: string
}
/**
* H5平台下载文件
* @param options 下载选项
* @returns Promise<DownloadResult>
*/
export function downloadFileForWeb(options: DownloadOptions): Promise<DownloadResult> {
return new Promise((resolve) => {
const { url, fileName = 'download' } = options
try {
// 检查是否在浏览器环境
if (typeof document === 'undefined') {
resolve({
success: false,
error: 'H5下载功能仅支持浏览器环境',
})
return
}
// 创建一个临时的a标签用于下载
const link = document.createElement('a')
link.href = url
link.download = fileName
link.style.display = 'none'
// 添加到文档并触发点击
document.body.appendChild(link)
link.click()
// 清理
document.body.removeChild(link)
// 显示下载成功提示
uni.showToast({
title: '开始下载',
icon: 'success',
duration: 1500,
})
resolve({
success: true,
})
} catch (error) {
console.error('H5下载失败:', error)
resolve({
success: false,
error: 'H5下载失败',
})
}
})
}
/**
* 原生平台下载文件
* @param options 下载选项
* @returns Promise<DownloadResult>
*/
export function downloadFileForNative(options: DownloadOptions): Promise<DownloadResult> {
return new Promise((resolve) => {
const { url, fileName = 'download', fileType = '', showProgress = true } = options
if (showProgress) {
// 显示加载提示
uni.showLoading({
title: '下载中...',
mask: true,
})
}
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
if (showProgress) {
uni.hideLoading()
uni.showToast({
title: '下载成功',
icon: 'success',
duration: 1500,
})
}
// 提示用户文件已保存
uni.showModal({
title: '下载完成',
content: `文件已保存至: ${saveRes.savedFilePath}\n是否立即打开?`,
success: (modalRes) => {
if (modalRes.confirm) {
uni.openDocument({
filePath: saveRes.savedFilePath,
fileType: fileType?.toString() || '',
showMenu: true,
fail: () => {
uni.showToast({
title: '无法打开文件',
icon: 'none',
duration: 1500,
})
},
})
}
},
})
resolve({
success: true,
savedFilePath: saveRes.savedFilePath,
})
},
fail: (err) => {
if (showProgress) {
uni.hideLoading()
console.error('保存文件失败:', err)
uni.showToast({
title: '保存文件失败',
icon: 'none',
duration: 1500,
})
}
resolve({
success: false,
error: '保存文件失败',
})
},
})
} else {
if (showProgress) {
uni.hideLoading()
uni.showToast({
title: `下载失败,状态码: ${res.statusCode}`,
icon: 'none',
duration: 1500,
})
}
resolve({
success: false,
error: `下载失败,状态码: ${res.statusCode}`,
})
}
},
fail: (err) => {
if (showProgress) {
uni.hideLoading()
console.error('下载失败:', err)
uni.showToast({
title: '网络错误,下载失败',
icon: 'none',
duration: 1500,
})
}
resolve({
success: false,
error: '网络错误,下载失败',
})
},
})
})
}
/**
* 通用下载文件方法
* 自动判断平台并调用相应的下载方法
* @param options 下载选项
* @returns Promise<DownloadResult>
*/
export function downloadFile(options: DownloadOptions): Promise<DownloadResult> {
// 判断是否为H5平台
/* #ifdef H5 */
return downloadFileForWeb(options)
/* #endif */
// 其他平台使用原生下载
/* #ifndef H5*/
return downloadFileForNative(options)
/* #endif */
}
/**
* 便捷下载方法,支持资源对象
* @param resource 资源对象,包含 fileSrc、fileName、fileType 等属性
* @returns Promise<DownloadResult>
*/
export function downloadResource(resource: any): Promise<DownloadResult> {
const options: DownloadOptions = {
url: resource.fileSrc,
fileName: resource.fileName || 'download',
fileType: resource.fileType || '',
fileSize: resource.fileSize || '',
showProgress: true,
}
return downloadFile(options)
}
/**
* 检查下载链接是否有效
* @param url 下载链接
* @returns Promise<boolean>
*/
export function checkDownloadUrl(url: string): Promise<boolean> {
return new Promise((resolve) => {
// 在原生平台检查链接有效性
/* #ifndef H5 */
uni.request({
url,
method: 'HEAD',
success: (res) => {
resolve(res.statusCode === 200)
},
fail: () => {
resolve(false)
},
})
/* #endif */
// 在H5平台,直接返回true(浏览器会处理链接有效性)
/* #ifdef H5 */
resolve(true)
/* #endif */
})
}
...@@ -3,6 +3,8 @@ import type { App, Plugin } from 'vue' ...@@ -3,6 +3,8 @@ import type { App, Plugin } from 'vue'
import { unref } from 'vue' import { unref } from 'vue'
import { isObject } from '/@/utils/is' import { isObject } from '/@/utils/is'
export * from './download'
export function noop() {} export function noop() {}
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论