ea
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/index/index",
|
||||
"pages/myPackage/yjfk/index",
|
||||
"pages/my/my",
|
||||
"pages/history/history",
|
||||
"pages/myPackage/edit/index",
|
||||
"pages/myPackage/vip/index",
|
||||
"pages/myPackage/bzzx/index",
|
||||
"pages/myPackage/ysxy/index",
|
||||
"pages/myPackage/golb/index",
|
||||
"pages/historyPackage/historyDetail/index",
|
||||
"pages/aiPackage/preview/index",
|
||||
"pages/aiPackage/record/index",
|
||||
"pages/aiPackage/bg/index",
|
||||
"pages/aiPackage/gen/index"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "Weixin",
|
||||
"navigationBarBackgroundColor": "#ffffff"
|
||||
},
|
||||
"style": "v2",
|
||||
"componentFramework": "glass-easel",
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
"tabBar": {
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/history/history",
|
||||
"text": "创作记录"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/my/my",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { customEvent } from "./utils/event";
|
||||
import { event } from "./utils/util";
|
||||
|
||||
// app.ts
|
||||
App<IAppOption>({
|
||||
globalData: {},
|
||||
onLaunch(op) {
|
||||
// 展示本地存储能力
|
||||
wx.setStorageSync('scene', +op.scene);
|
||||
|
||||
customEvent.on('update:user:info', event.user.update);
|
||||
customEvent.emmit('update:user:info', null);
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
/**app.wxss**/
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 200rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
image.icon-placeholder {
|
||||
display: block !important;
|
||||
flex-shrink: 0 !important;
|
||||
background: none !important;
|
||||
border: 0 !important;
|
||||
box-shadow: none !important;
|
||||
transform: none !important;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { resetuserinfocache, sign, userInfo } from "../../utils/request"
|
||||
|
||||
Component({
|
||||
properties: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
reward: {
|
||||
type: Number,
|
||||
value: 30,
|
||||
},
|
||||
streakDays: {
|
||||
type: Number,
|
||||
value: 7,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
days: [
|
||||
{ day: 1, label: '1天', today: false },
|
||||
{ day: 2, label: '2天', today: false },
|
||||
{ day: 3, label: '3天', today: false },
|
||||
{ day: 4, label: '4天', today: false },
|
||||
{ day: 5, label: '5天', today: false },
|
||||
{ day: 6, label: '6天', today: false },
|
||||
{ day: 7, label: '今天', today: true },
|
||||
],
|
||||
userInfo: null as any,
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.setData({ userInfo: wx.getStorageSync('userInfo') })
|
||||
},
|
||||
detached() {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
noop() { },
|
||||
handleOverlayTap() {
|
||||
this.handleClose()
|
||||
},
|
||||
handleClose() {
|
||||
this.triggerEvent('close')
|
||||
},
|
||||
sign() {
|
||||
if (this.data.userInfo.is_sign) {
|
||||
return;
|
||||
}
|
||||
sign().then((res: any) => {
|
||||
if (!res.code) {
|
||||
this.triggerEvent('close')
|
||||
resetuserinfocache(this);
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: res.message });
|
||||
}
|
||||
})
|
||||
},
|
||||
handleRule() {
|
||||
this.triggerEvent('rule')
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
<view wx:if="{{visible}}" class="checkin-overlay" catchtap="handleOverlayTap">
|
||||
<view class="checkin-popup" catchtap="noop">
|
||||
<image class="popup-bg" src="/static/images/sign_bg.png" mode="widthFix"></image>
|
||||
|
||||
<view class="days-row">
|
||||
<view wx:for="{{days}}" wx:key="day" class="day-item {{item.today ? 'today' : ''}}">
|
||||
<text class="day-label">{{item.label}}</text>
|
||||
<image class="day-coin" src="/static/images/sign_glob_icon.png" mode="aspectFit"></image>
|
||||
<view class="day-check">
|
||||
<text></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="close-hotspot" bindtap="handleClose"></view>
|
||||
<view class="receive-hotspot {{userInfo.is_sign ? 'disabled': ''}}" bindtap="sign"></view>
|
||||
<view class="rule-hotspot" bindtap="handleRule"></view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,129 @@
|
||||
.checkin-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.checkin-popup {
|
||||
position: relative;
|
||||
width: 670rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 32rpx;
|
||||
}
|
||||
|
||||
.popup-bg {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.days-row {
|
||||
position: absolute;
|
||||
top: 700rpx;
|
||||
left: 70rpx;
|
||||
right: 56rpx;
|
||||
height: 140rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.day-item {
|
||||
position: relative;
|
||||
width: 58rpx;
|
||||
height: 132rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #4b4f5d;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.day-item.today {
|
||||
width: 72rpx;
|
||||
height: 136rpx;
|
||||
margin-top: -16rpx;
|
||||
padding-top: 16rpx;
|
||||
border-radius: 30rpx;
|
||||
color: #7a4cff;
|
||||
background: #e4cdfd;
|
||||
}
|
||||
|
||||
.day-label {
|
||||
height: 24rpx;
|
||||
line-height: 24rpx;
|
||||
font-size: 19rpx;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.day-coin {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-top: 17rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.day-check {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-top: -8rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #754cff;
|
||||
box-shadow: 0 2rpx 6rpx rgba(117, 76, 255, 0.24);
|
||||
}
|
||||
|
||||
.day-check text {
|
||||
width: 10rpx;
|
||||
height: 6rpx;
|
||||
border-left: 3rpx solid #ffffff;
|
||||
border-bottom: 3rpx solid #ffffff;
|
||||
transform: rotate(-45deg) translate(1rpx, -1rpx);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.close-hotspot,
|
||||
.receive-hotspot,
|
||||
.rule-hotspot {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.close-hotspot {
|
||||
top: 32rpx;
|
||||
right: 28rpx;
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.receive-hotspot {
|
||||
left: 44rpx;
|
||||
right: 44rpx;
|
||||
bottom: 100rpx;
|
||||
height: 104rpx;
|
||||
border-radius: 52rpx;
|
||||
}
|
||||
|
||||
.rule-hotspot {
|
||||
left: 190rpx;
|
||||
right: 190rpx;
|
||||
bottom: 22rpx;
|
||||
height: 62rpx;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
Component({
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
properties: {
|
||||
contentHeight: {
|
||||
type: Number,
|
||||
value: 44,
|
||||
},
|
||||
paddingX: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
value: 'transparent',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
statusBarHeight: 0,
|
||||
navHeight: 44,
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.updateNavMetrics()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateNavMetrics() {
|
||||
const systemInfo = wx.getSystemInfoSync()
|
||||
const statusBarHeight = systemInfo.statusBarHeight || 0
|
||||
const contentHeight = Number(this.data.contentHeight) || 44
|
||||
const navHeight = statusBarHeight + contentHeight
|
||||
|
||||
this.setData({
|
||||
statusBarHeight,
|
||||
navHeight,
|
||||
})
|
||||
|
||||
this.triggerEvent('ready', {
|
||||
statusBarHeight,
|
||||
contentHeight,
|
||||
navHeight,
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<view
|
||||
class="custom-nav"
|
||||
style="height: {{navHeight}}px; padding-top: {{statusBarHeight}}px; padding-left: {{paddingX}}rpx; padding-right: {{paddingX}}rpx; background: {{background}};"
|
||||
>
|
||||
<view class="custom-nav__content" style="height: {{contentHeight}}px;">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,15 @@
|
||||
.custom-nav {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.custom-nav__content {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import { updatesessionkey, userInfo, vips, vipVirtualPayment } from "../../utils/request"
|
||||
|
||||
interface VipPlan {
|
||||
id: number
|
||||
name: string
|
||||
price: number
|
||||
desc: string
|
||||
recommend?: boolean
|
||||
selected: boolean
|
||||
}
|
||||
|
||||
Component({
|
||||
properties: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
benefits: [
|
||||
{ title: '更低生成成本', desc: '享受更多优惠', iconClass: 'cost-icon' },
|
||||
{ title: '专属会员标识', desc: '尊享身份标识', iconClass: 'badge-icon' },
|
||||
{ title: '优先体验新功能', desc: '抢先体验特权', iconClass: 'flash-icon' },
|
||||
],
|
||||
plans: [
|
||||
{ id: 1, name: '月卡会员', price: 25, desc: '¥25/月', selected: false },
|
||||
{ id: 2, name: '半年卡会员', price: 98, desc: '¥16.3/月', selected: false },
|
||||
{ id: 3, name: '年卡会员', price: 168, desc: '¥14/月', recommend: true, selected: true },
|
||||
{ id: 4, name: '终身会员', price: 298, desc: '一次付费\n永久使用', selected: false },
|
||||
] as VipPlan[],
|
||||
selectedPackage: null as VipPlan | null
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached() {
|
||||
vips().then((res: any) => {
|
||||
if (!res.code) {
|
||||
let array = [];
|
||||
for (let q = 0; q < res.data.length; q++) {
|
||||
let item = res.data[q];
|
||||
item.price = (+item.price).toFixed(0);
|
||||
array.push(item);
|
||||
}
|
||||
this.setData({ plans: array });
|
||||
}
|
||||
})
|
||||
},
|
||||
detached() {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
attached() {
|
||||
vips().then((res: any) => {
|
||||
if (!res.code) {
|
||||
let array = [];
|
||||
for (let q = 0; q < res.data.length; q++) {
|
||||
let item = res.data[q];
|
||||
item.price = (+item.price).toFixed(0);
|
||||
array.push(item);
|
||||
}
|
||||
this.setData({ plans: array });
|
||||
}
|
||||
})
|
||||
},
|
||||
detached() {
|
||||
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
noop() { },
|
||||
handleOverlayTap() {
|
||||
this.handleClose()
|
||||
},
|
||||
handleClose() {
|
||||
this.triggerEvent('close')
|
||||
},
|
||||
handlePlanTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
|
||||
this.data.plans.forEach((value, i) => {
|
||||
if (id == value.id) {
|
||||
console.log(value);
|
||||
this.setData({
|
||||
selectedPackage: value,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleConfirm() {
|
||||
this.handleBuy()
|
||||
},
|
||||
|
||||
handleBuy() {
|
||||
const that = this;
|
||||
if (that.data.selectedPackage == null) {
|
||||
return;
|
||||
}
|
||||
wx.showLoading({ title: '处理中...', mask: true });
|
||||
wx.checkSession({
|
||||
success() {
|
||||
that.payment();
|
||||
},
|
||||
fail() {
|
||||
wx.login({
|
||||
success(login) {
|
||||
updatesessionkey(login.code).then((res: any) => {
|
||||
if (!res.code) {
|
||||
that.payment();
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: res.message,
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
wx.hideLoading();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
payment() {
|
||||
let that = this;
|
||||
vipVirtualPayment((that.data.selectedPackage || { id: 0 }).id).then((res: any) => {
|
||||
wx.requestVirtualPayment({
|
||||
signData: JSON.stringify(res.param.signData),
|
||||
paySig: res.param.paySig,
|
||||
signature: res.param.signature,
|
||||
mode: res.param.mode,
|
||||
success(result: any) {
|
||||
wx.hideLoading();
|
||||
console.log(result)
|
||||
|
||||
userInfo().then((res: any) => {
|
||||
if (!res.code) {
|
||||
wx.setStorageSync('userInfo', res.data);
|
||||
that.setData({ userInfo: res.data });
|
||||
}
|
||||
})
|
||||
},
|
||||
fail(error: any) {
|
||||
wx.hideLoading();
|
||||
console.log(error);
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '支付失败',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
wx.hideLoading();
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '系统繁忙, 请稍后再试',
|
||||
showCancel: false
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,64 @@
|
||||
<view wx:if="{{visible}}" class="vip-overlay" catchtap="handleOverlayTap">
|
||||
<view class="vip-popup" catchtap="noop">
|
||||
<image class="vip-bg" src="/static/images/my/vip_bg.png" mode="widthFix"></image>
|
||||
|
||||
<view class="close-hotspot" bindtap="handleClose"></view>
|
||||
|
||||
<view class="vip-content">
|
||||
<view class="gift-list">
|
||||
<view class="gift-copy">
|
||||
<text>立即赠送</text>
|
||||
<text class="highlight">300</text>
|
||||
<text>金币</text>
|
||||
</view>
|
||||
|
||||
<view class="gift-copy daily-copy">
|
||||
<text>平台每天赠送</text>
|
||||
<text class="highlight">30</text>
|
||||
<text>金币</text>
|
||||
<text class="orange-note">(仅当天有效)</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="plan-section">
|
||||
<scroll-view class="plan-scroll" scroll-x enhanced show-scrollbar="false">
|
||||
<view class="plan-track">
|
||||
<view
|
||||
wx:for="{{plans}}"
|
||||
wx:key="id"
|
||||
class="plan-card {{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected) ? 'selected' : ''}}"
|
||||
data-id="{{item.id}}"
|
||||
bindtap="handlePlanTap"
|
||||
>
|
||||
<image wx:if="{{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected)}}" class="plan-selected-bg" src="/static/images/my/vip_selected.png" mode="scaleToFill"></image>
|
||||
<view wx:if="{{item.recommend}}" class="recommend-ribbon">推荐</view>
|
||||
<text class="plan-name">{{item.title}}</text>
|
||||
<view class="price-row">
|
||||
<text class="currency">¥</text>
|
||||
<text class="price">{{item.price}}</text>
|
||||
</view>
|
||||
<text class="plan-desc">{{item.price}}/月</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="dots">
|
||||
<text
|
||||
wx:for="{{plans}}"
|
||||
wx:key="id"
|
||||
class="dot {{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected) ? 'active' : ''}}"
|
||||
></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="action-section">
|
||||
<image class="vip-btn" src="/static/images/my/vip_btn.png" mode="widthFix" bindtap="handleConfirm"></image>
|
||||
<view class="skip-btn" bindtap="handleClose">暂不需要</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
.vip-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.58);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vip-popup {
|
||||
position: relative;
|
||||
width: 706rpx;
|
||||
height: 1130rpx;
|
||||
max-height: 92vh;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vip-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: 706rpx;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.close-hotspot {
|
||||
position: absolute;
|
||||
top: 112rpx;
|
||||
right: 24rpx;
|
||||
z-index: 5;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
|
||||
.vip-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
padding-top: 284rpx;
|
||||
}
|
||||
|
||||
.gift-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 68rpx;
|
||||
padding-left: 208rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.gift-copy {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 9rpx;
|
||||
height: 58rpx;
|
||||
color: #321708;
|
||||
font-size: 27rpx;
|
||||
font-weight: 900;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #f18a0a;
|
||||
font-size: 42rpx;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.orange-note {
|
||||
color: #f18400;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.plan-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 220rpx;
|
||||
}
|
||||
|
||||
.plan-scroll {
|
||||
width: 706rpx;
|
||||
height: 218rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.plan-track {
|
||||
height: 218rpx;
|
||||
padding: 0 52rpx;
|
||||
display: flex;
|
||||
gap: 14rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.plan-card {
|
||||
position: relative;
|
||||
width: 142rpx;
|
||||
height: 214rpx;
|
||||
border-radius: 14rpx;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border: 1rpx solid #e7dcf2;
|
||||
background: linear-gradient(180deg, #fffefe, #fbf9ff);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.plan-card.selected {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.plan-selected-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.recommend-ribbon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.plan-name,
|
||||
.price-row,
|
||||
.plan-desc {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.plan-name {
|
||||
color: #25170d;
|
||||
font-size: 23rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.price-row {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
color: #7047ee;
|
||||
}
|
||||
|
||||
.selected .price-row {
|
||||
color: #f08d09;
|
||||
}
|
||||
|
||||
.currency {
|
||||
font-size: 24rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 48rpx;
|
||||
line-height: 1;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.plan-desc {
|
||||
margin-top: 18rpx;
|
||||
color: #7f7f86;
|
||||
font-size: 20rpx;
|
||||
line-height: 1.25;
|
||||
text-align: center;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.dots {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14rpx;
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #dedee2;
|
||||
}
|
||||
|
||||
.dot.active {
|
||||
width: 36rpx;
|
||||
background: #764ef7;
|
||||
}
|
||||
|
||||
.action-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.vip-btn {
|
||||
width: 590rpx;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.skip-btn {
|
||||
margin-top: 20rpx;
|
||||
color: #8e8e94;
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import { backgroundTemplates, updateTaskBackground } from "../../../utils/request"
|
||||
|
||||
type Category = {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
type BgTemplate = {
|
||||
id: number
|
||||
name: string
|
||||
scene: string
|
||||
category: string
|
||||
coverUrl?: string
|
||||
imageUrl?: string
|
||||
videoUrl?: string
|
||||
isRecommend?: number
|
||||
}
|
||||
|
||||
function filterTemplates(category: string, templates: BgTemplate[]) {
|
||||
if (category === 'all') return templates
|
||||
return templates.filter((item) => item.category === category)
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
taskId: '',
|
||||
categories: [] as Category[],
|
||||
activeCategory: 'all',
|
||||
selectedTemplate: 0,
|
||||
allTemplates: [] as BgTemplate[],
|
||||
templates: [] as BgTemplate[],
|
||||
loading: false,
|
||||
},
|
||||
|
||||
onLoad(options: any) {
|
||||
this.setData({ taskId: options.taskId || options.taskid || '' })
|
||||
this.loadBackgroundTemplates()
|
||||
},
|
||||
|
||||
loadBackgroundTemplates() {
|
||||
this.setData({ loading: true })
|
||||
backgroundTemplates().then((res: any) => {
|
||||
const categories = res && !res.code && res.data ? (res.data.categories || []) : []
|
||||
const templates = res && !res.code && res.data ? (res.data.templates || []) : []
|
||||
const selectedTemplate = templates.length ? Number(templates[0].id) : 0
|
||||
this.setData({
|
||||
categories,
|
||||
allTemplates: templates,
|
||||
templates: filterTemplates(this.data.activeCategory, templates),
|
||||
selectedTemplate,
|
||||
loading: false,
|
||||
})
|
||||
}).catch(() => {
|
||||
this.setData({ loading: false })
|
||||
wx.showModal({ title: '温馨提示', content: '背景模板加载失败,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.navigateTo({ url: '/pages/aiPackage/record/index' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleCategorySelect(e: WechatMiniprogram.TouchEvent) {
|
||||
const activeCategory = e.currentTarget.dataset.id
|
||||
if (!activeCategory) return
|
||||
|
||||
const templates = filterTemplates(activeCategory, this.data.allTemplates)
|
||||
this.setData({ activeCategory, templates })
|
||||
},
|
||||
|
||||
handleTemplateSelect(e: WechatMiniprogram.TouchEvent) {
|
||||
const selectedTemplate = Number(e.currentTarget.dataset.id || 0)
|
||||
if (selectedTemplate <= 0) return
|
||||
|
||||
this.setData({ selectedTemplate })
|
||||
},
|
||||
|
||||
handleConfirm() {
|
||||
if (!this.data.taskId) {
|
||||
wx.showModal({ title: '温馨提示', content: '创作记录不存在', showCancel: false })
|
||||
return
|
||||
}
|
||||
if (this.data.selectedTemplate <= 0) {
|
||||
wx.showModal({ title: '温馨提示', content: '请选择背景模板', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
wx.showLoading({ mask: true, title: '保存背景中' })
|
||||
updateTaskBackground(this.data.taskId, this.data.selectedTemplate).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (!res.code) {
|
||||
wx.redirectTo({ url: '/pages/aiPackage/gen/index?taskId=' + encodeURIComponent(this.data.taskId) })
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '背景保存失败', showCancel: false })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,44 @@
|
||||
<view class="bg-page">
|
||||
<custom-nav padding-x="34">
|
||||
<view class="bg-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<view class="nav-title-wrap">
|
||||
<text class="nav-title">选择背景模板</text>
|
||||
<text class="nav-subtitle">选择适合你视频内容的场景背景</text>
|
||||
</view>
|
||||
<view class="nav-space"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="bg-content">
|
||||
<scroll-view class="category-scroll" scroll-x="true" enhanced="true" show-scrollbar="false">
|
||||
<view class="category-list">
|
||||
<view wx:for="{{categories}}" wx:key="id"
|
||||
class="category-item {{activeCategory === item.id ? 'category-active' : ''}}" data-id="{{item.id}}"
|
||||
bindtap="handleCategorySelect">{{item.name}}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="template-grid">
|
||||
<scroll-view class="auto-flex" enable-flex="true" scroll-y="true">
|
||||
<view wx:for="{{templates}}" wx:key="id"
|
||||
class="template-card {{selectedTemplate === item.id ? 'template-active' : ''}}" data-id="{{item.id}}"
|
||||
bindtap="handleTemplateSelect">
|
||||
<view class="scene-preview scene-{{item.scene}}">
|
||||
<image class="scene-placeholder icon-placeholder" src="/static/images/my/image.png" mode="aspectFit">
|
||||
</image>
|
||||
<view class="select-circle top-circle {{selectedTemplate === item.id ? 'circle-active' : ''}}"><text></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="template-foot">
|
||||
<text>{{item.name}}</text>
|
||||
<!-- <view class="select-circle foot-circle {{selectedTemplate === item.id ? 'circle-active' : ''}}">
|
||||
<text></text></view> -->
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="confirm-action" bindtap="handleConfirm">确认背景,去生成</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,367 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8faff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.bg-page {
|
||||
width: 750rpx;
|
||||
height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 12% 0%, rgba(104, 126, 255, 0.08), transparent 34%),
|
||||
radial-gradient(circle at 88% 10%, rgba(130, 86, 255, 0.08), transparent 30%),
|
||||
linear-gradient(180deg, #fbfcff 0%, #f6f8ff 44%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.bg-nav {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-space {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
flex: 0 0 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title-wrap {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
color: #111827;
|
||||
font-size: 34rpx;
|
||||
line-height: 40rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.nav-subtitle {
|
||||
max-width: 560rpx;
|
||||
color: #6c7284;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bg-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow-y: hidden;
|
||||
flex-direction: column;
|
||||
padding: 20rpx 18rpx 34rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.category-scroll {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.auto-flex {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.category-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 2rpx 0 26rpx;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
height: 46rpx;
|
||||
padding: 0 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2rpx solid #e0e4f2;
|
||||
border-radius: 24rpx;
|
||||
background: #ffffff;
|
||||
color: #656d80;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 800;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.category-active {
|
||||
border-color: #7462ff;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #6b83ff 0%, #754df3 100%);
|
||||
box-shadow: 0 8rpx 18rpx rgba(101, 85, 246, 0.2);
|
||||
}
|
||||
|
||||
.template-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
justify-content: space-between;
|
||||
row-gap: 30rpx;
|
||||
padding: 0 0 34rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.template-card {
|
||||
width: 326rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 2rpx solid transparent;
|
||||
border-radius: 14rpx;
|
||||
margin-bottom: 20rpx;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 12rpx 30rpx rgba(83, 92, 151, 0.12);
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.template-active {
|
||||
border-color: #765eff;
|
||||
box-shadow: 0 12rpx 30rpx rgba(101, 85, 246, 0.22);
|
||||
}
|
||||
|
||||
.scene-preview {
|
||||
height: 166rpx;
|
||||
padding: 12rpx 14rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: space-between;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scene-window,
|
||||
.scene-light,
|
||||
.scene-plant,
|
||||
.scene-main {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.scene-window {
|
||||
width: 96rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 4rpx;
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.88) 0%, rgba(225, 238, 250, 0.72) 100%);
|
||||
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.scene-light {
|
||||
width: 54rpx;
|
||||
height: 66rpx;
|
||||
border-radius: 28rpx 28rpx 10rpx 10rpx;
|
||||
background: linear-gradient(180deg, rgba(255, 246, 210, 0.9), rgba(226, 170, 92, 0.35));
|
||||
}
|
||||
|
||||
.scene-plant {
|
||||
width: 44rpx;
|
||||
height: 62rpx;
|
||||
border-radius: 28rpx 28rpx 8rpx 8rpx;
|
||||
background:
|
||||
radial-gradient(circle at 30% 28%, #7db66d 0 10rpx, transparent 11rpx),
|
||||
radial-gradient(circle at 68% 36%, #679f5d 0 12rpx, transparent 13rpx),
|
||||
linear-gradient(180deg, transparent 0 42rpx, #b48354 43rpx 100%);
|
||||
}
|
||||
|
||||
.plant-right {
|
||||
transform: scale(0.82);
|
||||
}
|
||||
|
||||
.scene-main {
|
||||
width: 160rpx;
|
||||
height: 54rpx;
|
||||
border-radius: 10rpx 10rpx 4rpx 4rpx;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
box-shadow: inset 0 -8rpx 0 rgba(188, 158, 120, 0.18);
|
||||
}
|
||||
|
||||
.scene-live {
|
||||
background:
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.28) 0 2rpx, transparent 2rpx 100%),
|
||||
linear-gradient(180deg, #fff4df 0%, #f9ead4 48%, #dfc09a 100%);
|
||||
}
|
||||
|
||||
.scene-office {
|
||||
background:
|
||||
linear-gradient(90deg, rgba(150, 168, 184, 0.16) 0 2rpx, transparent 2rpx 64rpx),
|
||||
linear-gradient(180deg, #eff6fb 0%, #dfe7ec 52%, #c8d2d9 100%);
|
||||
}
|
||||
|
||||
.scene-office .scene-main {
|
||||
width: 178rpx;
|
||||
background: linear-gradient(180deg, #f8fbfd 0%, #cbd7df 100%);
|
||||
}
|
||||
|
||||
.scene-classroom {
|
||||
background: linear-gradient(180deg, #fff4df 0%, #f4dfbf 52%, #d6b98c 100%);
|
||||
}
|
||||
|
||||
.scene-classroom .scene-main {
|
||||
width: 184rpx;
|
||||
height: 58rpx;
|
||||
background:
|
||||
linear-gradient(180deg, #4d7555 0%, #315b3b 100%);
|
||||
box-shadow: 0 18rpx 0 rgba(140, 98, 56, 0.32);
|
||||
}
|
||||
|
||||
.scene-emotion {
|
||||
background: linear-gradient(180deg, #ffe2be 0%, #e5b379 52%, #b57945 100%);
|
||||
}
|
||||
|
||||
.scene-emotion .scene-main,
|
||||
.scene-life .scene-main {
|
||||
width: 178rpx;
|
||||
height: 52rpx;
|
||||
border-radius: 30rpx 30rpx 12rpx 12rpx;
|
||||
background: linear-gradient(180deg, #f5dfc9 0%, #d1a78a 100%);
|
||||
}
|
||||
|
||||
.scene-product {
|
||||
background: linear-gradient(180deg, #f8dbb5 0%, #dfb076 55%, #b9844f 100%);
|
||||
}
|
||||
|
||||
.scene-product .scene-main {
|
||||
width: 174rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 50% 34%, #fff1d7 0%, #c8965e 66%, #9e6e3c 100%);
|
||||
}
|
||||
|
||||
.scene-life {
|
||||
background: linear-gradient(180deg, #fff6e9 0%, #ead8bd 54%, #c9ab81 100%);
|
||||
}
|
||||
|
||||
.template-foot {
|
||||
height: 62rpx;
|
||||
padding: 0 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.template-foot text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: #222633;
|
||||
font-size: 25rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.template-active .template-foot text {
|
||||
color: #6559ff;
|
||||
}
|
||||
|
||||
.select-circle {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid #d4d8e8;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 34rpx;
|
||||
}
|
||||
|
||||
.top-circle {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.foot-circle {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.circle-active {
|
||||
border-color: #7363ff;
|
||||
background: linear-gradient(135deg, #7089ff 0%, #7a4df4 100%);
|
||||
}
|
||||
|
||||
.circle-active text {
|
||||
width: 14rpx;
|
||||
height: 8rpx;
|
||||
display: block;
|
||||
border-left: 4rpx solid #ffffff;
|
||||
border-bottom: 4rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.confirm-action {
|
||||
height: 86rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #4e84ff 0%, #7d3ff3 100%);
|
||||
box-shadow: 0 14rpx 28rpx rgba(91, 86, 245, 0.24);
|
||||
font-size: 29rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.scene-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.scene-preview {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.top-circle {
|
||||
position: absolute;
|
||||
top: 12rpx;
|
||||
right: 14rpx;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { taskinfo } from "../../../utils/request"
|
||||
|
||||
function createTaskId() {
|
||||
return `task_${Date.now()}`
|
||||
}
|
||||
|
||||
Page({
|
||||
|
||||
data: {
|
||||
taskinfo: null as any,
|
||||
userinfo: null,
|
||||
price: 40,
|
||||
start: false
|
||||
},
|
||||
|
||||
onLoad(ops: { taskId: string }) {
|
||||
this.setData({ userinfo: wx.getStorageSync('userInfo') })
|
||||
taskinfo(ops.taskId).then((res: any) => {
|
||||
console.log(res);
|
||||
if (!res.code) {
|
||||
this.setData({ taskinfo: res.data });
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.navigateTo({ url: '/pages/aiPackage/bg/index' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleViewScript() {
|
||||
wx.showToast({ title: '展示完整文案', icon: 'none' })
|
||||
},
|
||||
|
||||
handleGenerate() {
|
||||
if (!this.data.taskinfo) {
|
||||
return;
|
||||
}
|
||||
let task_no = this.data.taskinfo.task_no || '';
|
||||
const detailUrl = `/pages/historyPackage/historyDetail/index?status=processing&taskId=${encodeURIComponent(task_no)}`
|
||||
|
||||
let userinfo = wx.getStorageSync('userinfo');
|
||||
if (userinfo.diamond < this.data.price) {
|
||||
wx.showModal({ title: '温馨提示', content: '余额不足' })
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ start: true })
|
||||
|
||||
// wx.redirectTo({ url: detailUrl })
|
||||
},
|
||||
|
||||
handleDownload() {
|
||||
// wx.showToast({ title: '开始下载', icon: 'none' })
|
||||
wx.downloadFile({
|
||||
url: '',
|
||||
success(res) {
|
||||
wx.showModal({ title: '温馨提示', content: '下载成功' })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleRegenerate() {
|
||||
// wx.showToast({ title: '重新生成', icon: 'none' })
|
||||
},
|
||||
|
||||
handleHome() {
|
||||
wx.switchTab({
|
||||
url: '/pages/index/index',
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<view class="gen-page">
|
||||
<custom-nav content-height="62" padding-x="34">
|
||||
<view class="gen-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<text class="nav-title">生成视频</text>
|
||||
<view class="coin-pill">
|
||||
<!-- <image class="coin-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>金币</text>
|
||||
<text class="coin-count">128</text> -->
|
||||
</view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="gen-content">
|
||||
<view class="confirm-card">
|
||||
<text class="card-title">生成确认</text>
|
||||
<view class="info-list">
|
||||
<view class="info-row avatar-row">
|
||||
<text class="info-label">数字人形象</text>
|
||||
<image class="small-avatar icon-placeholder" src="{{ taskinfo.avatar.image_url }}" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">背景模板</text>
|
||||
<text class="info-value">清新直播间</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">音色</text>
|
||||
<view class="voice-value">
|
||||
<image class="voice-icon icon-placeholder" src="/static/images/yinse.png" mode="aspectFit"></image>
|
||||
<text>已上传专属音色</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row script-row">
|
||||
<text class="info-label">文案摘要</text>
|
||||
<view class="script-summary">
|
||||
<text>{{ taskinfo.script_text }}</text>
|
||||
<view class="view-script" bindtap="handleViewScript">
|
||||
<text>查看完整文案</text>
|
||||
<text class="right-arrow"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cost-card" wx:if="{{!start}}">
|
||||
<view class="cost-row">
|
||||
<text>本次生成消耗</text>
|
||||
<view class="amount"><text>{{price}}</text><text>金币</text></view>
|
||||
</view>
|
||||
<view class="cost-row">
|
||||
<text>当前余额</text>
|
||||
<view class="balance-line">
|
||||
<view class="amount"><text>{{userinfo.diamond}}</text><text>金币</text></view>
|
||||
<view class="{{ userinfo.diamond < price ?'enough-waring': 'enough'}}">
|
||||
<text></text><text>{{userinfo.diamond < price? '余额不足' : '余额充足'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="generate-action" bindtap="handleGenerate">
|
||||
<image class="sparkle icon-placeholder" src="/static/images/filter-3-filled.png" mode="aspectFit"></image>
|
||||
<text>一键生成数字人视频</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{start}}" style="display:flex;flex-direction: column;gap: 30rpx;">
|
||||
<view class="result-title">
|
||||
<image class="result-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>生成结果</text>
|
||||
</view>
|
||||
|
||||
<view class="video-preview">
|
||||
<view class="preview-bg">
|
||||
<image class="preview-plant plant-left icon-placeholder" src="/static/images/my/image.png" mode="aspectFit">
|
||||
</image>
|
||||
<image class="preview-plant plant-right icon-placeholder" src="/static/images/my/image.png" mode="aspectFit">
|
||||
</image>
|
||||
<image class="preview-avatar icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<image class="play-btn icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-actions">
|
||||
<view class="action-primary" bindtap="handleDownload">
|
||||
<image class="download-icon icon-placeholder" src="/static/images/download.png" mode="aspectFit"></image>
|
||||
<text>下载视频</text>
|
||||
</view>
|
||||
<view class="action-outline" bindtap="handleRegenerate">
|
||||
<image class="refresh-icon icon-placeholder" src="/static/images/currency-exchange.png" mode="aspectFit">
|
||||
</image>
|
||||
<text>重新生成</text>
|
||||
</view>
|
||||
<view class="action-outline" bindtap="handleHome">
|
||||
<image class="home-icon icon-placeholder" src="/static/images/to_index.png" mode="aspectFit"></image>
|
||||
<text>返回首页</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="save-tip">
|
||||
<image class="tip-icon icon-placeholder" src="/static/images/info-circle.png" mode="aspectFit"></image>
|
||||
<text>视频已为你自动保存到【创作记录】</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,590 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8faff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.gen-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 12% 0%, rgba(104, 126, 255, 0.08), transparent 34%),
|
||||
radial-gradient(circle at 88% 8%, rgba(130, 86, 255, 0.08), transparent 30%),
|
||||
linear-gradient(180deg, #fbfcff 0%, #f6f8ff 46%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.gen-nav {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 60rpx;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: #111827;
|
||||
font-size: 34rpx;
|
||||
line-height: 42rpx;
|
||||
font-weight: 900;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.coin-pill {
|
||||
height: 50rpx;
|
||||
padding: 0 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
/* border: 2rpx solid #eef0fb; */
|
||||
border-radius: 28rpx;
|
||||
/* background: rgba(255, 255, 255, 0.88); */
|
||||
/* box-shadow: 0 8rpx 18rpx rgba(93, 102, 158, 0.12); */
|
||||
color: #111827;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 800;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.coin-icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #ffd45d 0%, #ffa51f 100%);
|
||||
font-size: 17rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.coin-count {
|
||||
color: #6657ff;
|
||||
}
|
||||
|
||||
.gen-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.confirm-card,
|
||||
.cost-card {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 2rpx solid #e6e9ff;
|
||||
border-radius: 16rpx;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 14rpx 34rpx rgba(80, 92, 170, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.confirm-card {
|
||||
padding: 22rpx 28rpx 10rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
color: #111827;
|
||||
font-size: 27rpx;
|
||||
line-height: 34rpx;
|
||||
font-weight: 900;
|
||||
padding-bottom: 18rpx;
|
||||
border-bottom: 2rpx solid #edf0f8;
|
||||
}
|
||||
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
min-height: 62rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
border-bottom: 2rpx solid #edf0f8;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.avatar-row {
|
||||
min-height: 72rpx;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
flex: 0 0 160rpx;
|
||||
color: #303748;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.info-value,
|
||||
.voice-value,
|
||||
.script-summary {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: #41495b;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.small-avatar {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 10rpx;
|
||||
background:
|
||||
radial-gradient(circle at 50% 33%, #ffe1d2 0 17rpx, transparent 18rpx),
|
||||
radial-gradient(circle at 50% 34%, #33201b 0 24rpx, transparent 25rpx),
|
||||
linear-gradient(180deg, #eef4ff 0%, #ffffff 100%);
|
||||
flex: 0 0 58rpx;
|
||||
}
|
||||
|
||||
.voice-value {
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.voice-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #6d58ff;
|
||||
flex: 0 0 28rpx;
|
||||
}
|
||||
|
||||
.voice-icon::before,
|
||||
.voice-icon::after,
|
||||
.voice-icon text {
|
||||
content: '';
|
||||
width: 5rpx;
|
||||
border-radius: 5rpx;
|
||||
background: #6d58ff;
|
||||
}
|
||||
|
||||
.voice-icon::before { height: 18rpx; }
|
||||
.voice-icon text { height: 28rpx; margin: 0 4rpx; display: block; }
|
||||
.voice-icon::after { height: 20rpx; }
|
||||
|
||||
.script-row {
|
||||
align-items: flex-start;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
|
||||
.script-summary {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10rpx;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.view-script {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
color: #7062ff;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.right-arrow {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-right: 4rpx solid #7062ff;
|
||||
border-top: 4rpx solid #7062ff;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cost-card {
|
||||
padding: 12rpx 24rpx 22rpx;
|
||||
background: linear-gradient(100deg, rgba(255, 255, 255, 0.98) 0%, rgba(239, 255, 248, 0.92) 100%);
|
||||
margin-bottom: calc(10rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.cost-row {
|
||||
min-height: 52rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 2rpx solid rgba(224, 229, 242, 0.75);
|
||||
color: #303748;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.amount,
|
||||
.balance-line,
|
||||
.enough {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.amount {
|
||||
gap: 10rpx;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.amount text:first-child {
|
||||
font-size: 32rpx;
|
||||
line-height: 38rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.amount text:last-child {
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.balance-line {
|
||||
gap: 22rpx;
|
||||
}
|
||||
|
||||
.enough {
|
||||
gap: 8rpx;
|
||||
color: #40bf83;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.enough-waring {
|
||||
gap: 8rpx;
|
||||
color: red;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.enough text:first-child {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
border-radius: 50%;
|
||||
background: #42c982;
|
||||
}
|
||||
|
||||
.enough text:first-child::after {
|
||||
content: '';
|
||||
width: 11rpx;
|
||||
height: 7rpx;
|
||||
margin: 7rpx auto 0;
|
||||
display: block;
|
||||
border-left: 3rpx solid #ffffff;
|
||||
border-bottom: 3rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.generate-action {
|
||||
height: 66rpx;
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
border-radius: 12rpx;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #4e84ff 0%, #7d3ff3 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(91, 86, 245, 0.22);
|
||||
font-size: 27rpx;
|
||||
line-height: 34rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.sparkle {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
background:
|
||||
linear-gradient(90deg, transparent 42%, #ffffff 43% 57%, transparent 58%),
|
||||
linear-gradient(0deg, transparent 42%, #ffffff 43% 57%, transparent 58%);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.result-title {
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
color: #3f4dff;
|
||||
font-size: 25rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.result-icon {
|
||||
width: 25rpx;
|
||||
height: 25rpx;
|
||||
border: 4rpx solid #625aff;
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.video-preview {
|
||||
width: 100%;
|
||||
height: 274rpx;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 12rpx 30rpx rgba(83, 92, 151, 0.13);
|
||||
}
|
||||
|
||||
.preview-bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
background:
|
||||
linear-gradient(90deg, rgba(255,255,255,0.36) 0 3rpx, transparent 3rpx 64rpx),
|
||||
linear-gradient(180deg, #fff4e3 0%, #f1dcc3 58%, #d9b98f 100%);
|
||||
}
|
||||
|
||||
.preview-plant {
|
||||
width: 86rpx;
|
||||
height: 126rpx;
|
||||
margin-bottom: 18rpx;
|
||||
border-radius: 50rpx 50rpx 12rpx 12rpx;
|
||||
background:
|
||||
radial-gradient(circle at 30% 24%, #79ad65 0 22rpx, transparent 23rpx),
|
||||
radial-gradient(circle at 66% 32%, #6aa05f 0 24rpx, transparent 25rpx),
|
||||
radial-gradient(circle at 50% 50%, #7eb86a 0 25rpx, transparent 26rpx),
|
||||
linear-gradient(180deg, transparent 0 82rpx, #a9794d 83rpx 100%);
|
||||
}
|
||||
|
||||
.plant-left {
|
||||
margin-right: 76rpx;
|
||||
}
|
||||
|
||||
.plant-right {
|
||||
margin-left: 76rpx;
|
||||
}
|
||||
|
||||
.preview-avatar {
|
||||
width: 176rpx;
|
||||
height: 236rpx;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-head {
|
||||
width: 116rpx;
|
||||
height: 130rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
border-radius: 60rpx 60rpx 42rpx 42rpx;
|
||||
background: linear-gradient(160deg, #241a18 0%, #604038 60%, #8a6258 100%);
|
||||
}
|
||||
|
||||
.avatar-face {
|
||||
width: 78rpx;
|
||||
height: 92rpx;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
border-radius: 42rpx 42rpx 34rpx 34rpx;
|
||||
background: linear-gradient(180deg, #ffe6d9 0%, #ffd0c2 100%);
|
||||
}
|
||||
|
||||
.avatar-eyes {
|
||||
width: 48rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.avatar-eyes text {
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #241a18;
|
||||
}
|
||||
|
||||
.avatar-mouth {
|
||||
width: 26rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
background: #ca6975;
|
||||
}
|
||||
|
||||
.avatar-body {
|
||||
width: 160rpx;
|
||||
height: 106rpx;
|
||||
border-radius: 46rpx 46rpx 0 0;
|
||||
background: linear-gradient(120deg, #ffffff 0%, #f5f4f1 48%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
width: 74rpx;
|
||||
height: 74rpx;
|
||||
margin-left: -126rpx;
|
||||
margin-bottom: 54rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.82);
|
||||
border-radius: 50%;
|
||||
background: rgba(49, 43, 38, 0.48);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.play-btn text {
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 6rpx;
|
||||
border-top: 16rpx solid transparent;
|
||||
border-bottom: 16rpx solid transparent;
|
||||
border-left: 24rpx solid #ffffff;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
display: flex;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.action-primary,
|
||||
.action-outline {
|
||||
height: 82rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
border-radius: 14rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 31rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.action-primary {
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #5a80ff 0%, #764df3 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(91, 86, 245, 0.18);
|
||||
}
|
||||
|
||||
.action-outline {
|
||||
color: #625aff;
|
||||
border: 2rpx solid #dce0f5;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.download-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-left: 4rpx solid #ffffff;
|
||||
border-bottom: 4rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.refresh-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border: 4rpx solid #625aff;
|
||||
border-right-color: transparent;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.home-icon {
|
||||
width: 25rpx;
|
||||
height: 22rpx;
|
||||
border: 4rpx solid #625aff;
|
||||
border-top: 0;
|
||||
border-radius: 4rpx;
|
||||
box-sizing: border-box;
|
||||
transform: translateY(4rpx);
|
||||
}
|
||||
|
||||
.home-icon::before {
|
||||
content: '';
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
display: block;
|
||||
border-left: 4rpx solid #625aff;
|
||||
border-top: 4rpx solid #625aff;
|
||||
transform: rotate(45deg) translate(-4rpx, -13rpx);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.save-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
color: #8d94a5;
|
||||
font-size: 23rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: calc(10rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid #9aa1b2;
|
||||
border-radius: 50%;
|
||||
font-size: 16rpx;
|
||||
line-height: 18rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import { polishScript, saveScript, taskinfo } from "../../../utils/request"
|
||||
|
||||
type PolishStyle = {
|
||||
id: string
|
||||
name: string
|
||||
icon: string
|
||||
activeIcon: string
|
||||
}
|
||||
|
||||
const styles: PolishStyle[] = [
|
||||
{ id: 'natural', name: '自然口播', icon: '/static/images/Frame-15355646363.png', activeIcon: '/static/images/Frame-1561268387.png' },
|
||||
{ id: 'goods', name: '带货风格', icon: '/static/images/Frame-1561268385.png', activeIcon: '/static/images/Frame-1561268389.png' },
|
||||
{ id: 'emotion', name: '情感风格', icon: '/static/images/Frame-1561268384.png', activeIcon: '/static/images/Frame-1561268388.png' },
|
||||
{ id: 'teach', name: '专业讲解', icon: '/static/images/Frame-1561268383.png', activeIcon: '/static/images/Frame-1561268390.png' },
|
||||
{ id: 'viral', name: '爆款短视频', icon: '/static/images/Frame-1561268382.png', activeIcon: '/static/images/Frame-1561268386.png' },
|
||||
]
|
||||
|
||||
const styleMap: Record<string, string> = {
|
||||
natural: 'friendly',
|
||||
goods: 'product',
|
||||
emotion: 'rewrite',
|
||||
teach: 'professional',
|
||||
viral: 'rewrite',
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
styles,
|
||||
selectedStyle: 'natural',
|
||||
taskinfo: null as any,
|
||||
inEdit: false,
|
||||
},
|
||||
|
||||
onLoad(ops: any) {
|
||||
taskinfo(ops.taskId).then((res: any) => {
|
||||
if (!res.code) {
|
||||
this.setData({ taskinfo: res.data })
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '获取文案失败', showCancel: false })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/index/index' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleStyleSelect(e: WechatMiniprogram.TouchEvent) {
|
||||
const selectedStyle = e.currentTarget.dataset.id
|
||||
if (!selectedStyle) return
|
||||
|
||||
this.setData({ selectedStyle })
|
||||
},
|
||||
|
||||
handleEdit() {
|
||||
if (!this.data.taskinfo) return
|
||||
|
||||
this.setData({ inEdit: !this.data.inEdit })
|
||||
},
|
||||
|
||||
changeContent(e: any) {
|
||||
const taskinfo = this.data.taskinfo
|
||||
if (!taskinfo) return
|
||||
|
||||
taskinfo.script_text = e.detail.value
|
||||
this.setData({ taskinfo })
|
||||
},
|
||||
|
||||
handleRegenerate() {
|
||||
const taskinfo = this.data.taskinfo
|
||||
if (!taskinfo) return
|
||||
|
||||
const content = taskinfo.script_text || taskinfo.original_script || ''
|
||||
if (!content) {
|
||||
wx.showToast({ title: '暂无可润色文案', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
wx.showLoading({ title: '润色中' })
|
||||
polishScript(taskinfo.task_no, content, styleMap[this.data.selectedStyle] || 'optimize').then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '润色失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
taskinfo.script_text = res.data.scriptText
|
||||
this.setData({ taskinfo, inEdit: false })
|
||||
wx.showToast({ title: '已重新润色', icon: 'success' })
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
handleConfirm() {
|
||||
this.saveCurrentScript(true)
|
||||
},
|
||||
|
||||
saveCurrentScript(next: boolean) {
|
||||
const taskinfo = this.data.taskinfo
|
||||
if (!taskinfo) return
|
||||
|
||||
const content = (taskinfo.script_text || '').trim()
|
||||
if (!content) {
|
||||
wx.showToast({ title: '文案不能为空', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
wx.showLoading({ title: '保存中' })
|
||||
saveScript(taskinfo.task_no, content).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '保存失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
taskinfo.script_text = res.data.scriptText
|
||||
this.setData({ taskinfo, inEdit: false })
|
||||
if (next) {
|
||||
wx.redirectTo({
|
||||
url: '/pages/aiPackage/record/index?taskid=' + taskinfo.task_no,
|
||||
})
|
||||
} else {
|
||||
wx.showToast({ title: '已保存', icon: 'success' })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<view class="preview-page">
|
||||
<custom-nav content-height="86" padding-x="34">
|
||||
<view class="preview-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<view class="nav-title-wrap">
|
||||
<text class="nav-title">文案优化</text>
|
||||
<text class="nav-subtitle">让口播更自然,更适合短视频传播</text>
|
||||
</view>
|
||||
<view class="nav-space"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="preview-content">
|
||||
<view class="panel original-panel">
|
||||
<text class="panel-title">原文案</text>
|
||||
<view class="script-text original-text">
|
||||
<text>{{taskinfo.original_script}}</text>
|
||||
</view>
|
||||
<text class="count-text">共 {{taskinfo.original_script.length}} 字</text>
|
||||
</view>
|
||||
|
||||
<view class="panel ai-panel">
|
||||
<view class="panel-head">
|
||||
<view class="title-line">
|
||||
<text class="panel-title">AI 优化后文案</text>
|
||||
<text class="status-pill">已优化</text>
|
||||
</view>
|
||||
<view class="edit-btn" bindtap="handleEdit">
|
||||
<image class="edit-icon icon-placeholder" src="/static/images/edit.png" mode="aspectFit"></image>
|
||||
<text>{{inEdit?'保存':'编辑'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="optimized-box">
|
||||
<text wx:if="{{inEdit == false}}">{{taskinfo.script_text}}</text>
|
||||
<textarea bindinput="changeContent" wx:else value="{{taskinfo.script_text}}"></textarea>
|
||||
<text class="optimized-count">共 {{taskinfo.script_text.length}} 字</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="panel style-panel">
|
||||
<text class="panel-title">选择润色风格</text>
|
||||
<view class="style-list">
|
||||
<view
|
||||
wx:for="{{styles}}"
|
||||
wx:key="id"
|
||||
class="style-item {{selectedStyle === item.id ? 'style-item-active' : ''}}"
|
||||
data-id="{{item.id}}"
|
||||
bindtap="handleStyleSelect"
|
||||
>
|
||||
<image class="style-icon style-icon-{{item.id}} icon-placeholder" src="{{selectedStyle == item.id ? item.activeIcon :item.icon}}" mode="aspectFit"></image>
|
||||
<text>{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="action-row">
|
||||
<view class="outline-action" bindtap="handleRegenerate">重新润色</view>
|
||||
<view class="confirm-action" bindtap="handleConfirm">确认使用此文案</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-tip">
|
||||
<image class="tip-dot icon-placeholder" src="/static/images/info-circle.png" mode="aspectFit"></image>
|
||||
<text>新生成的视频将使用优化后的文案进行口播</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8faff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.preview-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 10% 0%, rgba(117, 93, 255, 0.08), transparent 32%),
|
||||
radial-gradient(circle at 92% 8%, rgba(74, 132, 255, 0.08), transparent 30%),
|
||||
linear-gradient(180deg, #fbfcff 0%, #f5f7ff 48%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.preview-nav {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-space {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
flex: 0 0 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title-wrap {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
line-height: 40rpx;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.nav-subtitle {
|
||||
max-width: 520rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #6d7484;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 26rpx;
|
||||
padding: 22rpx 34rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.panel {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
border: 2rpx solid #e8eaff;
|
||||
border-radius: 16rpx;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-shadow: 0 12rpx 34rpx rgba(80, 92, 170, 0.08);
|
||||
}
|
||||
|
||||
.original-panel {
|
||||
min-height: 326rpx;
|
||||
padding: 25rpx 32rpx 22rpx;
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
font-size: 28rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.script-text {
|
||||
margin-top: 22rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #252a35;
|
||||
font-size: 24rpx;
|
||||
line-height: 42rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.original-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.count-text,
|
||||
.optimized-count {
|
||||
align-self: flex-end;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #9ba1af;
|
||||
}
|
||||
|
||||
.ai-panel {
|
||||
padding: 20rpx 18rpx 18rpx;
|
||||
}
|
||||
|
||||
.panel-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
padding: 0 16rpx 16rpx;
|
||||
}
|
||||
|
||||
.title-line {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.status-pill {
|
||||
padding: 4rpx 18rpx;
|
||||
border-radius: 20rpx;
|
||||
background: #ece9ff;
|
||||
color: #7860ff;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
height: 48rpx;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
border: 2rpx solid #d8d1ff;
|
||||
border-radius: 14rpx;
|
||||
color: #7254f4;
|
||||
font-size: 23rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 800;
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 21rpx;
|
||||
height: 21rpx;
|
||||
border: 4rpx solid #7254f4;
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
transform: skew(-12deg) rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.optimized-box {
|
||||
min-height: 286rpx;
|
||||
padding: 20rpx 20rpx 18rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border: 2rpx solid #dcd9ff;
|
||||
border-radius: 14rpx;
|
||||
box-sizing: border-box;
|
||||
color: #252a35;
|
||||
font-size: 24rpx;
|
||||
line-height: 40rpx;
|
||||
font-weight: 700;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.style-panel {
|
||||
padding: 25rpx 18rpx 22rpx;
|
||||
gap: 22rpx;
|
||||
}
|
||||
|
||||
.style-list {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.style-item {
|
||||
width: 112rpx;
|
||||
height: 112rpx;
|
||||
padding: 12rpx 8rpx 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
border: 2rpx solid #e1e4f4;
|
||||
border-radius: 12rpx;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
color: #555d6f;
|
||||
font-size: 19rpx;
|
||||
line-height: 24rpx;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
flex: 0 0 112rpx;
|
||||
}
|
||||
|
||||
.style-item-active {
|
||||
border-color: #7461ff;
|
||||
background: linear-gradient(180deg, #806bff 0%, #5f55f5 100%);
|
||||
color: #ffffff;
|
||||
box-shadow: 0 10rpx 22rpx rgba(98, 85, 245, 0.26);
|
||||
}
|
||||
|
||||
.style-icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
font-size: 18rpx;
|
||||
line-height: 20rpx;
|
||||
font-weight: 900;
|
||||
color: #ffffff;
|
||||
background: #83cfff;
|
||||
}
|
||||
|
||||
.style-icon-natural { background: linear-gradient(135deg, #8c82ff 0%, #6b58ff 100%); }
|
||||
.style-icon-goods { background: linear-gradient(135deg, #a7e8ff 0%, #69bde8 100%); }
|
||||
.style-icon-emotion { background: linear-gradient(135deg, #ffd888 0%, #ffb750 100%); }
|
||||
.style-icon-teach { background: linear-gradient(135deg, #dca8ff 0%, #9f66ef 100%); }
|
||||
.style-icon-viral { background: linear-gradient(135deg, #ffbccd 0%, #ff7696 100%); }
|
||||
|
||||
.style-item-active .style-icon {
|
||||
background: rgba(255, 255, 255, 0.16);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.24);
|
||||
}
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
margin-top: 2rpx;
|
||||
}
|
||||
|
||||
.outline-action,
|
||||
.confirm-action {
|
||||
height: 76rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
font-size: 27rpx;
|
||||
line-height: 34rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.outline-action {
|
||||
flex: 0 0 278rpx;
|
||||
border: 2rpx solid #d9d4ff;
|
||||
background: rgba(255, 255, 255, 0.86);
|
||||
color: #7254f4;
|
||||
}
|
||||
|
||||
.confirm-action {
|
||||
flex: 1;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #4e84ff 0%, #7d3ff3 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(91, 86, 245, 0.24);
|
||||
}
|
||||
|
||||
.bottom-tip {
|
||||
margin-top: 4rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
color: #8d94a5;
|
||||
font-size: 23rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tip-dot {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid #8d94a5;
|
||||
border-radius: 50%;
|
||||
font-size: 16rpx;
|
||||
line-height: 18rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
import { taskinfo, uploadavatar, uploadrecord, checkavatar, checkvoice, saveHumanAssets } from "../../../utils/request"
|
||||
|
||||
const waveBars = [
|
||||
{ id: 'b1', cls: 'bar-22' },
|
||||
{ id: 'b2', cls: 'bar-34' },
|
||||
{ id: 'b3', cls: 'bar-48' },
|
||||
{ id: 'b4', cls: 'bar-34' },
|
||||
{ id: 'b5', cls: 'bar-62' },
|
||||
{ id: 'b6', cls: 'bar-42' },
|
||||
{ id: 'b7', cls: 'bar-70' },
|
||||
{ id: 'b8', cls: 'bar-52' },
|
||||
{ id: 'b9', cls: 'bar-38' },
|
||||
{ id: 'b10', cls: 'bar-58' },
|
||||
{ id: 'b11', cls: 'bar-46' },
|
||||
{ id: 'b12', cls: 'bar-30' },
|
||||
]
|
||||
const miniBars = [
|
||||
{ id: 'm1', cls: 'mini-bar-18' },
|
||||
{ id: 'm2', cls: 'mini-bar-30' },
|
||||
{ id: 'm3', cls: 'mini-bar-46' },
|
||||
{ id: 'm4', cls: 'mini-bar-28' },
|
||||
{ id: 'm5', cls: 'mini-bar-56' },
|
||||
{ id: 'm6', cls: 'mini-bar-36' },
|
||||
]
|
||||
|
||||
function formatRecordTime(totalSeconds: number) {
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
const seconds = totalSeconds % 60
|
||||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
Page({
|
||||
recordTimer: 0,
|
||||
voiceCheckTimer: 0,
|
||||
|
||||
data: {
|
||||
isRecording: false,
|
||||
recordingClass: 'recording-active',
|
||||
elapsedSeconds: 0,
|
||||
recordTime: '00:00',
|
||||
waveBars,
|
||||
miniBars,
|
||||
taskinfo: null as any,
|
||||
avatar: '/static/images/my/image.png',
|
||||
avatarUrl: '',
|
||||
avatarChecked: false,
|
||||
recordUrl: '',
|
||||
recordDurationMs: 0,
|
||||
voiceAsrTaskId: '',
|
||||
voiceChecked: false,
|
||||
voiceText: '',
|
||||
voiceStatusText: ''
|
||||
},
|
||||
|
||||
|
||||
onLoad(ops: any) {
|
||||
taskinfo(ops.taskid).then((res: any) => {
|
||||
if (!res.code) {
|
||||
this.setData({ taskinfo: res.data });
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (this.data.isRecording) {
|
||||
this.startRecordTimer()
|
||||
}
|
||||
},
|
||||
|
||||
onHide() {
|
||||
this.clearRecordTimer()
|
||||
this.clearVoiceCheckTimer()
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
this.clearRecordTimer()
|
||||
this.clearVoiceCheckTimer()
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.navigateTo({ url: '/pages/aiPackage/preview/index' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleUploadPhoto() {
|
||||
const that = this;
|
||||
wx.chooseImage({
|
||||
count: 1,
|
||||
success(res: any) {
|
||||
const file = res.tempFilePaths[0];
|
||||
wx.showLoading({ mask: true, title: '上传照片中' });
|
||||
uploadavatar(file, {}, '/api/upload/avatar').then((uploadRes: any) => {
|
||||
if (uploadRes.code) {
|
||||
wx.hideLoading();
|
||||
wx.showModal({ title: '温馨提示', content: uploadRes.message || '照片上传失败', showCancel: false })
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showLoading({ mask: true, title: '人脸检测中' });
|
||||
checkavatar(uploadRes.data.url).then((checkRes: any) => {
|
||||
wx.hideLoading();
|
||||
if (!checkRes.code) {
|
||||
that.setData({ avatar: uploadRes.data.url, avatarUrl: uploadRes.data.url, avatarChecked: true })
|
||||
wx.showToast({ title: '照片检测通过', icon: 'success' })
|
||||
} else {
|
||||
that.setData({ avatarUrl: '', avatarChecked: false })
|
||||
wx.showModal({ title: '温馨提示', content: checkRes.message || '未检测到人脸', showCancel: false })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading();
|
||||
that.setData({ avatarUrl: '', avatarChecked: false })
|
||||
wx.showModal({ title: '温馨提示', content: '人脸检测失败,请稍后再试', showCancel: false })
|
||||
})
|
||||
}).catch(() => {
|
||||
wx.hideLoading();
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleUseDefaultAvatar() {
|
||||
wx.showToast({ title: '暂未配置默认形象', icon: 'none' })
|
||||
},
|
||||
|
||||
handleRecord() {
|
||||
if (this.data.isRecording) return
|
||||
|
||||
if (this.recordTimer) {
|
||||
clearTimeout(this.recordTimer);
|
||||
clearInterval(this.recordTimer);
|
||||
}
|
||||
|
||||
this.clearVoiceCheckTimer()
|
||||
this.recordTimer = 0;
|
||||
|
||||
this.setData({
|
||||
isRecording: true,
|
||||
recordTime: '00:00',
|
||||
elapsedSeconds: 0,
|
||||
recordingClass: 'recording-active',
|
||||
recordUrl: '',
|
||||
recordDurationMs: 0,
|
||||
voiceAsrTaskId: '',
|
||||
voiceChecked: false,
|
||||
voiceText: '',
|
||||
voiceStatusText: ''
|
||||
})
|
||||
this.startRecordTimer()
|
||||
},
|
||||
|
||||
handleUseDefaultVoice() {
|
||||
this.clearRecordTimer()
|
||||
this.clearVoiceCheckTimer()
|
||||
this.setData({ isRecording: false, recordingClass: '' })
|
||||
wx.showToast({ title: '暂未配置默认音色', icon: 'none' })
|
||||
},
|
||||
|
||||
handleStopRecord() {
|
||||
this.clearRecordTimer()
|
||||
this.recordTimer = 0;
|
||||
this.setData({ isRecording: false, recordingClass: '' })
|
||||
wx.getRecorderManager().stop()
|
||||
},
|
||||
|
||||
handleNext() {
|
||||
if (!this.data.taskinfo || !this.data.taskinfo.task_no) {
|
||||
wx.showModal({ title: '温馨提示', content: '创作记录不存在', showCancel: false })
|
||||
return
|
||||
}
|
||||
if (!this.data.avatarChecked || !this.data.avatarUrl) {
|
||||
wx.showModal({ title: '温馨提示', content: '请先上传并通过数字人照片检测', showCancel: false })
|
||||
return
|
||||
}
|
||||
if (!this.data.voiceChecked || !this.data.recordUrl || !this.data.voiceText) {
|
||||
wx.showModal({ title: '温馨提示', content: '请先录制并通过音色检测', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
wx.showLoading({ mask: true, title: '保存中' })
|
||||
saveHumanAssets({
|
||||
taskId: this.data.taskinfo.task_no,
|
||||
avatarUrl: this.data.avatarUrl,
|
||||
voiceUrl: this.data.recordUrl,
|
||||
voiceText: this.data.voiceText,
|
||||
durationMs: this.data.recordDurationMs,
|
||||
asrTaskId: this.data.voiceAsrTaskId
|
||||
}).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (!res.code) {
|
||||
wx.redirectTo({ url: '/pages/aiPackage/bg/index?taskId=' + encodeURIComponent(this.data.taskinfo.task_no) })
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '保存失败', showCancel: false })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
startRecordTimer() {
|
||||
let that = this;
|
||||
that.clearRecordTimer()
|
||||
that.recordTimer = setInterval(() => {
|
||||
const elapsedSeconds = that.data.elapsedSeconds + 1
|
||||
that.setData({ elapsedSeconds, recordTime: formatRecordTime(elapsedSeconds) })
|
||||
}, 1000) as unknown as number
|
||||
|
||||
let recorder = wx.getRecorderManager();
|
||||
recorder.onError(that.onRecordError.bind(that));
|
||||
recorder.onStop(that.onRecordStop.bind(that))
|
||||
recorder.start({ duration: 10000, format: 'mp3' });
|
||||
},
|
||||
|
||||
onRecordError(err: any) {
|
||||
console.log(err)
|
||||
this.clearRecordTimer()
|
||||
this.setData({ isRecording: false, recordingClass: '' })
|
||||
wx.showModal({ title: '温馨提示', content: '录音失败,请重新录制', showCancel: false })
|
||||
},
|
||||
|
||||
onRecordStop(resource: { duration: number, fileSize: number, tempFilePath: string }) {
|
||||
this.clearRecordTimer()
|
||||
this.recordTimer = 0;
|
||||
this.setData({ isRecording: false, recordingClass: '', voiceStatusText: '录音上传中' })
|
||||
|
||||
wx.showLoading({ mask: true, title: '上传录音中' })
|
||||
uploadrecord(resource.tempFilePath).then((res: any) => {
|
||||
if (res.code) {
|
||||
wx.hideLoading()
|
||||
this.setData({ voiceStatusText: '', voiceChecked: false })
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '录音上传失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({
|
||||
recordUrl: res.data.url,
|
||||
recordDurationMs: res.data.durationMs || resource.duration || 0,
|
||||
voiceAsrTaskId: '',
|
||||
voiceChecked: false,
|
||||
voiceText: '',
|
||||
voiceStatusText: '录音识别中'
|
||||
})
|
||||
this.pollVoiceCheck('')
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
this.setData({ voiceStatusText: '', voiceChecked: false })
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
pollVoiceCheck(asrTaskId: string) {
|
||||
checkvoice(this.data.recordUrl, asrTaskId).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
wx.hideLoading()
|
||||
const nextTaskId = res.data && res.data.asrTaskId ? res.data.asrTaskId : asrTaskId
|
||||
this.setData({ voiceAsrTaskId: nextTaskId, voiceStatusText: '录音识别中' })
|
||||
this.clearVoiceCheckTimer()
|
||||
this.voiceCheckTimer = setTimeout(() => {
|
||||
this.pollVoiceCheck(nextTaskId)
|
||||
}, 1500) as unknown as number
|
||||
return
|
||||
}
|
||||
|
||||
wx.hideLoading()
|
||||
if (!res.code) {
|
||||
this.clearVoiceCheckTimer()
|
||||
this.setData({
|
||||
voiceAsrTaskId: res.data.asrTaskId,
|
||||
voiceText: res.data.recognizedText,
|
||||
voiceChecked: true,
|
||||
voiceStatusText: '录音检测通过'
|
||||
})
|
||||
wx.showToast({ title: '音色检测通过', icon: 'success' })
|
||||
} else {
|
||||
this.clearVoiceCheckTimer()
|
||||
this.setData({ voiceChecked: false, voiceStatusText: '' })
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '录音识别失败,请重新录制', showCancel: false })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
this.clearVoiceCheckTimer()
|
||||
this.setData({ voiceChecked: false, voiceStatusText: '' })
|
||||
wx.showModal({ title: '温馨提示', content: '录音识别失败,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
clearRecordTimer() {
|
||||
if (!this.recordTimer) return
|
||||
clearInterval(this.recordTimer)
|
||||
this.recordTimer = 0
|
||||
},
|
||||
|
||||
clearVoiceCheckTimer() {
|
||||
if (!this.voiceCheckTimer) return
|
||||
clearTimeout(this.voiceCheckTimer)
|
||||
this.voiceCheckTimer = 0
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<view class="record-page">
|
||||
<custom-nav content-height="86" padding-x="34">
|
||||
<view class="record-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<view class="nav-title-wrap">
|
||||
<text class="nav-title">设置数字人</text>
|
||||
<text class="nav-subtitle">上传照片和录音,生成你的专属数字人</text>
|
||||
</view>
|
||||
<view class="nav-space"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="record-content">
|
||||
<view class="panel photo-panel">
|
||||
<text class="panel-title">上传数字人照片</text>
|
||||
<view class="photo-body">
|
||||
<view class="photo-preview">
|
||||
<image class="portrait-bg icon-placeholder" src="{{ avatar }}" mode="aspectFit"></image>
|
||||
<view class="camera-badge"><image class="camera-icon icon-placeholder" style="width: 60%;height: 60%;" src="/static/images/carram_white.png" mode="aspectFit"></image></view>
|
||||
</view>
|
||||
|
||||
<view class="photo-actions">
|
||||
<view class="primary-small" bindtap="handleUploadPhoto">上传照片</view>
|
||||
<view class="ghost-small" bindtap="handleUseDefaultAvatar">使用默认形象</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="hint-row">
|
||||
<image class="hint-dot icon-placeholder" src="/static/images/zhuyi1.png" mode="aspectFit"></image>
|
||||
<text>建议上传清晰正脸照片,生成效果更自然</text>
|
||||
</view>
|
||||
<!-- <view wx:if="{{avatarChecked}}" class="asset-status success-status">照片检测通过</view> -->
|
||||
</view>
|
||||
|
||||
<view class="panel voice-panel">
|
||||
<text class="panel-title">录取专属音色</text>
|
||||
<view class="voice-body">
|
||||
<view class="voice-visual {{recordingClass}}">
|
||||
<view wx:if="{{isRecording}}" class="recording-pill"><text></text><text>录制中</text></view>
|
||||
<view class="wave-row wave-left">
|
||||
<text wx:for="{{waveBars}}" wx:key="id" class="{{item.cls}}"></text>
|
||||
</view>
|
||||
<view class="mic-wrap">
|
||||
<view class="pulse-ring ring-one"></view>
|
||||
<view class="pulse-ring ring-two"></view>
|
||||
<view class="pulse-ring ring-three"></view>
|
||||
<view class="mic-core">
|
||||
<image class="mic-icon icon-placeholder" style="width: 60%;height: 60%;" src="/static/images/mic.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="wave-row wave-right">
|
||||
<text wx:for="{{waveBars}}" wx:key="id" class="{{item.cls}}"></text>
|
||||
</view>
|
||||
<text class="record-time">{{recordTime}}</text>
|
||||
</view>
|
||||
|
||||
<view class="voice-actions">
|
||||
<view class="primary-small" wx:if="{{!isRecording}}" bindtap="handleRecord">录取音色</view>
|
||||
<view class="stop-small" wx:if="{{isRecording}}" bindtap="handleStopRecord">
|
||||
<image class="stop-dot icon-placeholder" style="width: 40rpx;height: 40rpx;" src="/static/images/stop.png" mode="aspectFit"></image>
|
||||
<text>停止录制</text>
|
||||
</view>
|
||||
<view class="ghost-small" bindtap="handleUseDefaultVoice">使用默认音色</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="hint-row voice-hint">
|
||||
<image class="hint-dot icon-placeholder" src="/static/images/zhuyi1.png" mode="aspectFit"></image>
|
||||
<text>建议录制 10 秒以上,环境安静效果更佳</text>
|
||||
</view>
|
||||
<!-- <view wx:if="{{voiceStatusText}}" class="asset-status {{voiceChecked ? 'success-status' : 'pending-status'}}">{{voiceStatusText}}</view> -->
|
||||
|
||||
<view class="script-section">
|
||||
<text class="script-title">朗读以下文案(约10秒)</text>
|
||||
<view class="script-card">
|
||||
<text>大家好,我是你的数字人口播助手。今天为大家带来一段精彩的内容介绍。</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="default-section">
|
||||
<text class="default-title">默认选项(可直接体验)</text>
|
||||
<view class="default-row">
|
||||
<view class="default-card">
|
||||
<image class="mini-avatar icon-placeholder" src="https://cdn.zhuangb123.com/chat-square/EB3D71A23725-6CD76-956EFD1DB-0C25B0.jpg" mode="aspectFit"></image>
|
||||
<text class="default-name">默认数字人</text>
|
||||
<text class="trial-pill">可直接体验</text>
|
||||
</view>
|
||||
<view class="default-card">
|
||||
<image class="mini-voice icon-placeholder" src="/static/images/ys.png" mode="aspectFit"></image>
|
||||
<text class="default-name">默认音色</text>
|
||||
<text class="trial-pill blue-pill">可直接体验</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="next-action" bindtap="handleNext">下一步:选择视频背景</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -0,0 +1,668 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8faff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.record-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 10% 0%, rgba(116, 98, 255, 0.08), transparent 34%),
|
||||
radial-gradient(circle at 88% 10%, rgba(73, 132, 255, 0.08), transparent 30%),
|
||||
linear-gradient(180deg, #fbfcff 0%, #f7f9ff 46%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.record-nav {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-space {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
flex: 0 0 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title-wrap {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
line-height: 40rpx;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.nav-subtitle {
|
||||
max-width: 560rpx;
|
||||
color: #687086;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.record-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 22rpx;
|
||||
padding: 20rpx 32rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.panel {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 2rpx solid #e6e9ff;
|
||||
border-radius: 18rpx;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 14rpx 34rpx rgba(80, 92, 170, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.photo-panel {
|
||||
padding: 24rpx 26rpx 24rpx;
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
color: #111827;
|
||||
font-size: 28rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.photo-body {
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 56rpx;
|
||||
}
|
||||
|
||||
.photo-preview {
|
||||
width: 306rpx;
|
||||
height: 224rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
border: 2rpx solid #dce1ff;
|
||||
border-radius: 14rpx;
|
||||
background: linear-gradient(180deg, #f8fbff 0%, #eef3ff 100%);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.portrait-bg {
|
||||
width: 190rpx;
|
||||
height: 218rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.portrait-head {
|
||||
width: 120rpx;
|
||||
height: 138rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
border-radius: 60rpx 60rpx 44rpx 44rpx;
|
||||
background: linear-gradient(160deg, #2e1e19 0%, #684235 56%, #9c6a58 100%);
|
||||
box-shadow: 0 4rpx 12rpx rgba(85, 50, 44, 0.18);
|
||||
}
|
||||
|
||||
.face {
|
||||
width: 78rpx;
|
||||
height: 98rpx;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
border-radius: 42rpx 42rpx 36rpx 36rpx;
|
||||
background: linear-gradient(180deg, #ffe8dc 0%, #ffd0c2 100%);
|
||||
}
|
||||
|
||||
.eye-row {
|
||||
width: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.eye-row text {
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #251918;
|
||||
}
|
||||
|
||||
.nose {
|
||||
width: 8rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 8rpx;
|
||||
background: rgba(196, 116, 101, 0.46);
|
||||
}
|
||||
|
||||
.mouth {
|
||||
width: 24rpx;
|
||||
height: 7rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
background: #ca6975;
|
||||
}
|
||||
|
||||
.hair,
|
||||
.hair-main {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.portrait-neck {
|
||||
width: 32rpx;
|
||||
height: 22rpx;
|
||||
background: #ffd3c4;
|
||||
}
|
||||
|
||||
.portrait-cloth {
|
||||
width: 178rpx;
|
||||
height: 68rpx;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
background: linear-gradient(120deg, #ffffff 0%, #f7f6f2 50%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.camera-badge {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
/* margin-bottom: 20rpx; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.88);
|
||||
border-radius: 50%;
|
||||
background: rgba(66, 56, 49, 0.72);
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 60rpx;
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
width: 28rpx;
|
||||
height: 21rpx;
|
||||
border: 4rpx solid #ffffff;
|
||||
border-radius: 5rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.camera-icon::after {
|
||||
content: '';
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
margin: 2rpx auto 0;
|
||||
display: block;
|
||||
border: 3rpx solid #ffffff;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.photo-actions,
|
||||
.voice-actions {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.primary-small,
|
||||
.ghost-small,
|
||||
.stop-small {
|
||||
height: 70rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.primary-small {
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #4e84ff 0%, #7d3ff3 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(91, 86, 245, 0.22);
|
||||
}
|
||||
|
||||
.ghost-small,
|
||||
.stop-small {
|
||||
border: 2rpx solid #d9dcf2;
|
||||
background: #fafbff;
|
||||
color: #596083;
|
||||
}
|
||||
|
||||
.hint-row {
|
||||
margin-top: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #7a8196;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hint-dot {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: #b9bfd2;
|
||||
color: #ffffff;
|
||||
font-size: 12rpx;
|
||||
line-height: 16rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.voice-panel {
|
||||
padding: 24rpx 26rpx 24rpx;
|
||||
}
|
||||
|
||||
.voice-body {
|
||||
margin-top: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.voice-visual {
|
||||
width: 340rpx;
|
||||
min-height: 240rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.recording-pill {
|
||||
width: 116rpx;
|
||||
height: 44rpx;
|
||||
margin-right: 224rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
border-radius: 22rpx;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(90deg, #7380ff 0%, #8a55ed 100%);
|
||||
box-shadow: 0 8rpx 18rpx rgba(117, 94, 239, 0.3);
|
||||
font-size: 21rpx;
|
||||
line-height: 26rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.recording-pill text:first-child {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.recording-active .recording-pill text:first-child {
|
||||
animation: blinkDot 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.wave-row {
|
||||
width: 118rpx;
|
||||
height: 82rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 7rpx;
|
||||
}
|
||||
|
||||
.wave-row text {
|
||||
width: 5rpx;
|
||||
border-radius: 6rpx;
|
||||
background: linear-gradient(180deg, #5f86ff 0%, #bd67f2 100%);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.recording-active .wave-row text:nth-child(2n) {
|
||||
animation: waveScaleA 0.78s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.recording-active .wave-row text:nth-child(2n + 1) {
|
||||
animation: waveScaleB 0.92s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.recording-active .wave-row text:nth-child(3n) {
|
||||
animation-delay: 0.18s;
|
||||
}
|
||||
|
||||
.mic-wrap {
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(139, 102, 255, 0.13) 0%, rgba(139, 102, 255, 0.05) 68%, transparent 70%);
|
||||
}
|
||||
|
||||
.pulse-ring {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
margin-right: -90rpx;
|
||||
border: 3rpx solid rgba(135, 98, 247, 0.28);
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.recording-active .ring-one { animation: pulseRing 1.5s ease-out infinite; }
|
||||
.recording-active .ring-two { animation: pulseRing 1.5s ease-out 0.3s infinite; }
|
||||
.recording-active .ring-three { animation: pulseRing 1.5s ease-out 0.6s infinite; }
|
||||
|
||||
.mic-core {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(160deg, #77a0ff 0%, #8346f5 100%);
|
||||
box-shadow: 0 10rpx 24rpx rgba(117, 86, 243, 0.32);
|
||||
}
|
||||
|
||||
.mic-icon {
|
||||
width: 32rpx;
|
||||
height: 45rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mic-icon::before {
|
||||
content: '';
|
||||
width: 24rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 14rpx;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.mic-icon text {
|
||||
width: 34rpx;
|
||||
height: 14rpx;
|
||||
display: block;
|
||||
border-bottom: 5rpx solid #ffffff;
|
||||
border-left: 5rpx solid #ffffff;
|
||||
border-right: 5rpx solid #ffffff;
|
||||
border-radius: 0 0 18rpx 18rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.record-time {
|
||||
width: 100%;
|
||||
margin-top: 2rpx;
|
||||
color: #586085;
|
||||
font-size: 31rpx;
|
||||
line-height: 38rpx;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stop-small {
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.stop-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 3rpx;
|
||||
background: #ff6b6b;
|
||||
}
|
||||
|
||||
.voice-hint {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.script-section {
|
||||
margin-top: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.script-title {
|
||||
color: #111827;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.script-card {
|
||||
min-height: 92rpx;
|
||||
padding: 18rpx 22rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 2rpx solid #dfe3ff;
|
||||
border-radius: 10rpx;
|
||||
background: linear-gradient(180deg, #fbfbff 0%, #f6f7ff 100%);
|
||||
box-sizing: border-box;
|
||||
color: #4d557d;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.default-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.default-title {
|
||||
color: #4f47ff;
|
||||
font-size: 23rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.default-row {
|
||||
display: flex;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.default-card {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
min-width: 0;
|
||||
padding: 10rpx 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
border: 2rpx solid #e4e7f6;
|
||||
border-radius: 14rpx;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-shadow: 0 10rpx 24rpx rgba(80, 92, 170, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mini-avatar {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 12rpx;
|
||||
background:
|
||||
radial-gradient(circle at 50% 32%, #ffe0d2 0 16rpx, transparent 17rpx),
|
||||
radial-gradient(circle at 50% 35%, #4b2d25 0 24rpx, transparent 25rpx),
|
||||
linear-gradient(180deg, #eef4ff 0%, #ffffff 100%);
|
||||
flex: 0 0 58rpx;
|
||||
}
|
||||
|
||||
.mini-voice {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #eef2ff;
|
||||
flex: 0 0 58rpx;
|
||||
}
|
||||
|
||||
.mini-voice text {
|
||||
width: 5rpx;
|
||||
border-radius: 5rpx;
|
||||
background: linear-gradient(180deg, #5f86ff 0%, #8550f2 100%);
|
||||
}
|
||||
|
||||
.default-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: #111827;
|
||||
font-size: 23rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 900;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.trial-pill {
|
||||
padding: 6rpx 12rpx;
|
||||
border-radius: 18rpx;
|
||||
background: #fff3db;
|
||||
color: #f4a326;
|
||||
font-size: 18rpx;
|
||||
line-height: 22rpx;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.blue-pill {
|
||||
background: #e9f3ff;
|
||||
color: #5a96f0;
|
||||
}
|
||||
|
||||
.next-action {
|
||||
height: 78rpx;
|
||||
margin-top: -2rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(100deg, #4e84ff 0%, #7d3ff3 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(91, 86, 245, 0.24);
|
||||
font-size: 31rpx;
|
||||
line-height: 38rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
@keyframes waveScaleA {
|
||||
0%, 100% { transform: scaleY(0.62); opacity: 0.62; }
|
||||
50% { transform: scaleY(1.18); opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes waveScaleB {
|
||||
0%, 100% { transform: scaleY(1); opacity: 0.88; }
|
||||
50% { transform: scaleY(0.55); opacity: 0.55; }
|
||||
}
|
||||
|
||||
@keyframes pulseRing {
|
||||
0% { transform: scale(0.72); opacity: 0.7; }
|
||||
100% { transform: scale(1.72); opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes blinkDot {
|
||||
0%, 100% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.38; transform: scale(0.72); }
|
||||
}
|
||||
|
||||
.bar-22 { height: 22rpx; }
|
||||
.bar-30 { height: 30rpx; }
|
||||
.bar-34 { height: 34rpx; }
|
||||
.bar-38 { height: 38rpx; }
|
||||
.bar-42 { height: 42rpx; }
|
||||
.bar-46 { height: 46rpx; }
|
||||
.bar-48 { height: 48rpx; }
|
||||
.bar-52 { height: 52rpx; }
|
||||
.bar-58 { height: 58rpx; }
|
||||
.bar-62 { height: 62rpx; }
|
||||
.bar-70 { height: 70rpx; }
|
||||
|
||||
.mini-bar-18 { height: 18rpx; }
|
||||
.mini-bar-28 { height: 28rpx; }
|
||||
.mini-bar-30 { height: 30rpx; }
|
||||
.mini-bar-36 { height: 36rpx; }
|
||||
.mini-bar-46 { height: 46rpx; }
|
||||
.mini-bar-56 { height: 56rpx; }
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.asset-status {
|
||||
margin-top: 14rpx;
|
||||
height: 44rpx;
|
||||
padding: 0 18rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
align-self: flex-start;
|
||||
border-radius: 22rpx;
|
||||
font-size: 21rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 800;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.success-status {
|
||||
color: #16854f;
|
||||
background: #e9f8f0;
|
||||
border: 2rpx solid #bdebd3;
|
||||
}
|
||||
|
||||
.pending-status {
|
||||
color: #5a5f89;
|
||||
background: #f1f3ff;
|
||||
border: 2rpx solid #dfe3ff;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import { historyDownload, historyList } from "../../utils/request"
|
||||
|
||||
type FilterKey = 'all' | 'done' | 'processing' | 'failed'
|
||||
type RecordStatus = 'done' | 'processing' | 'failed'
|
||||
|
||||
interface HistoryRecord {
|
||||
id: number
|
||||
taskId: string
|
||||
title: string
|
||||
scene: string
|
||||
avatar: string
|
||||
time: string
|
||||
duration: string
|
||||
status: RecordStatus
|
||||
statusText: string
|
||||
secondaryText: string
|
||||
sceneClass: string
|
||||
isDone: boolean
|
||||
isProcessing: boolean
|
||||
isFailed: boolean
|
||||
coverUrl: string
|
||||
coverImage: string
|
||||
videoUrl: string
|
||||
progress: number
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
filters: [
|
||||
{ key: 'all', label: '全部', active: true },
|
||||
{ key: 'done', label: '已完成', active: false },
|
||||
{ key: 'processing', label: '生成中', active: false },
|
||||
],
|
||||
activeFilter: 'all' as FilterKey,
|
||||
records: [] as HistoryRecord[],
|
||||
page: 1,
|
||||
limit: 10,
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadRecords(true)
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.loadRecords(true)
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadRecords(true).finally(() => wx.stopPullDownRefresh())
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.hasMore && !this.data.loading) {
|
||||
this.loadRecords(false)
|
||||
}
|
||||
},
|
||||
|
||||
loadRecords(reset = false) {
|
||||
if (this.data.loading) return Promise.resolve()
|
||||
|
||||
const page = reset ? 1 : this.data.page + 1
|
||||
this.setData({ loading: true })
|
||||
|
||||
return historyList(this.data.activeFilter, page, this.data.limit).then((res: any) => {
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message, showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
const list = (res.data.list as HistoryRecord[]).map((item) => ({
|
||||
...item,
|
||||
coverImage: item.coverUrl
|
||||
}))
|
||||
this.setData({
|
||||
records: reset ? list : this.data.records.concat(list),
|
||||
page,
|
||||
hasMore: res.data.hasMore,
|
||||
})
|
||||
}).catch(() => {
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
}).finally(() => {
|
||||
this.setData({ loading: false })
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/index/index' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleFilterTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const activeFilter = e.currentTarget.dataset.key as FilterKey
|
||||
this.setData({
|
||||
activeFilter,
|
||||
filters: this.data.filters.map((item) => ({
|
||||
...item,
|
||||
active: item.key === activeFilter,
|
||||
})),
|
||||
})
|
||||
this.loadRecords(true)
|
||||
},
|
||||
|
||||
handleFailedTap() {
|
||||
this.setData({
|
||||
activeFilter: 'failed',
|
||||
filters: this.data.filters.map((item) => ({ ...item, active: false })),
|
||||
})
|
||||
this.loadRecords(true)
|
||||
},
|
||||
|
||||
handleDetail(e: WechatMiniprogram.TouchEvent) {
|
||||
const rawStatus = String(e.currentTarget.dataset.status || '')
|
||||
const taskId = String(e.currentTarget.dataset.taskId || '')
|
||||
if (!taskId) return
|
||||
|
||||
const status = rawStatus === 'failed' ? 'failed' : rawStatus === 'processing' ? 'processing' : 'done'
|
||||
wx.navigateTo({
|
||||
url: '/pages/historyPackage/historyDetail/index?status=' + status + '&taskId=' + encodeURIComponent(taskId),
|
||||
})
|
||||
},
|
||||
|
||||
handleDownload(e: WechatMiniprogram.TouchEvent) {
|
||||
const taskId = String(e.currentTarget.dataset.taskId || '')
|
||||
if (!taskId) return
|
||||
|
||||
wx.showLoading({ title: '获取下载地址' })
|
||||
historyDownload(taskId).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '下载失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
const url = res.data.url
|
||||
if (url) {
|
||||
wx.setClipboardData({ data: url })
|
||||
} else {
|
||||
wx.showToast({ title: '暂无下载地址', icon: 'none' })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
handleMore(e: WechatMiniprogram.TouchEvent) {
|
||||
this.handleDetail(e)
|
||||
},
|
||||
|
||||
handleRetry() {
|
||||
wx.switchTab({ url: '/pages/index/index' })
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<view class="history-page">
|
||||
<custom-nav padding-x="52">
|
||||
<view class="history-nav">
|
||||
<text class="nav-title">创作记录</text>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="history-content">
|
||||
<view class="filter-row">
|
||||
<view class="filter-tabs">
|
||||
<view
|
||||
wx:for="{{filters}}"
|
||||
wx:key="key"
|
||||
class="filter-chip {{item.active ? 'active' : ''}}"
|
||||
data-key="{{item.key}}"
|
||||
bindtap="handleFilterTap"
|
||||
>{{item.label}}</view>
|
||||
</view>
|
||||
<view class="failed-btn {{activeFilter === 'failed' ? 'active' : ''}}" bindtap="handleFailedTap">
|
||||
<image class="filter-icon icon-placeholder" src="/static/images/filter.png" mode="aspectFit"></image>
|
||||
<text>失败记录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="record-list" wx:if="{{records.length}}">
|
||||
<view wx:for="{{records}}" wx:key="taskId" class="record-card">
|
||||
<view class="thumb {{item.sceneClass}}">
|
||||
<image class="thumb-placeholder icon-placeholder" src="{{item.coverImage}}" mode="aspectFill"></image>
|
||||
<view class="duration-badge">{{item.duration}}</view>
|
||||
</view>
|
||||
|
||||
<view class="record-main">
|
||||
<text class="record-title">{{item.title}}</text>
|
||||
<view class="tag-row">
|
||||
<text class="tag">{{item.scene}}</text>
|
||||
<text class="tag">{{item.avatar}}</text>
|
||||
</view>
|
||||
<text class="record-time">{{item.time}}</text>
|
||||
|
||||
<view class="status-line {{item.status}}">
|
||||
<text wx:if="{{item.isProcessing}}" class="progress-dot"></text>
|
||||
<text>{{item.statusText}}</text>
|
||||
</view>
|
||||
|
||||
<view class="action-row">
|
||||
<view class="secondary-btn" data-status="{{item.status}}" data-task-id="{{item.taskId}}" bindtap="handleDetail">{{item.secondaryText}}</view>
|
||||
<view wx:if="{{item.isDone}}" class="download-btn" data-task-id="{{item.taskId}}" bindtap="handleDownload">
|
||||
<image class="download-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>下载</text>
|
||||
</view>
|
||||
<view wx:elif="{{item.isProcessing}}" class="more-btn" data-status="{{item.status}}" data-task-id="{{item.taskId}}" bindtap="handleMore">
|
||||
<text></text>
|
||||
<text></text>
|
||||
<text></text>
|
||||
</view>
|
||||
<view wx:else class="retry-btn" data-task-id="{{item.taskId}}" bindtap="handleRetry">重新生成</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{!loading}}" class="empty-state">暂无创作记录</view>
|
||||
<view wx:if="{{loading}}" class="empty-state">加载中...</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #fbfcff;
|
||||
color: #161a26;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.history-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfcff 52%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.history-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-placeholder {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.back-line {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #11151e;
|
||||
border-bottom: 5rpx solid #11151e;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 31rpx;
|
||||
font-weight: 800;
|
||||
color: #11141f;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.history-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 26rpx 24rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 18rpx;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.filter-chip,
|
||||
.failed-btn {
|
||||
height: 52rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.filter-chip {
|
||||
min-width: 90rpx;
|
||||
padding: 0 24rpx;
|
||||
color: #727887;
|
||||
background: #f4f6fb;
|
||||
border: 1rpx solid #e8ebf4;
|
||||
box-shadow: inset 0 1rpx 5rpx rgba(72, 82, 124, 0.04);
|
||||
}
|
||||
|
||||
.filter-chip.active {
|
||||
color: #ffffff;
|
||||
border-color: transparent;
|
||||
background: linear-gradient(135deg, #5c7cff 0%, #7148f4 100%);
|
||||
box-shadow: 0 8rpx 16rpx rgba(91, 96, 255, 0.28);
|
||||
}
|
||||
|
||||
.failed-btn {
|
||||
width: 164rpx;
|
||||
gap: 12rpx;
|
||||
color: #3d4352;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid #e6e8f7;
|
||||
box-shadow: 0 6rpx 16rpx rgba(72, 82, 124, 0.05);
|
||||
}
|
||||
|
||||
.filter-icon {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border: 4rpx solid #676d85;
|
||||
border-bottom: 0;
|
||||
border-radius: 5rpx 5rpx 2rpx 2rpx;
|
||||
box-sizing: border-box;
|
||||
transform: skewX(-8deg);
|
||||
}
|
||||
|
||||
.filter-icon::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 7rpx;
|
||||
height: 14rpx;
|
||||
margin: 16rpx auto 0;
|
||||
background: #676d85;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.record-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.record-card {
|
||||
min-height: 206rpx;
|
||||
padding: 16rpx 18rpx;
|
||||
border-radius: 17rpx;
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border: 1rpx solid #edf0fb;
|
||||
box-shadow: 0 8rpx 22rpx rgba(74, 88, 148, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 278rpx;
|
||||
height: 172rpx;
|
||||
border-radius: 10rpx;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-start;
|
||||
padding: 12rpx;
|
||||
box-sizing: border-box;
|
||||
background: #ece6dc;
|
||||
}
|
||||
|
||||
.scene-layer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.scene-bg,
|
||||
.scene-subject {
|
||||
pointer-events: none;
|
||||
}
|
||||
/*
|
||||
.scene-live {
|
||||
background:
|
||||
linear-gradient(90deg, rgba(249, 243, 232, 0.92), rgba(240, 235, 222, 0.74)),
|
||||
linear-gradient(135deg, #e9dac9 0%, #fbf8f1 45%, #d3dcc1 100%);
|
||||
}
|
||||
|
||||
.scene-live::before,
|
||||
.scene-classroom::before {
|
||||
content: "";
|
||||
width: 76rpx;
|
||||
height: 118rpx;
|
||||
margin-left: 82rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border-radius: 36rpx 36rpx 10rpx 10rpx;
|
||||
background: linear-gradient(180deg, #20202a 0 24%, #fff7ef 24% 42%, #ffffff 42% 100%);
|
||||
box-shadow: 0 0 0 16rpx rgba(255, 255, 255, 0.34);
|
||||
} */
|
||||
|
||||
.scene-product {
|
||||
/* background:
|
||||
radial-gradient(circle at 80% 22%, rgba(126, 151, 102, 0.32), transparent 15%),
|
||||
radial-gradient(circle at 12% 28%, rgba(126, 151, 102, 0.25), transparent 16%),
|
||||
linear-gradient(135deg, #e9e2d4, #fbf8ef 48%, #d8c8ad);
|
||||
justify-content: center; */
|
||||
}
|
||||
|
||||
/* .scene-product::before {
|
||||
content: "";
|
||||
width: 56rpx;
|
||||
height: 96rpx;
|
||||
margin-bottom: 32rpx;
|
||||
border-radius: 11rpx 11rpx 7rpx 7rpx;
|
||||
background: linear-gradient(180deg, #1e1b18 0 18%, #5b2e1d 18% 100%);
|
||||
box-shadow: 0 22rpx 0 58rpx rgba(184, 151, 102, 0.22);
|
||||
}
|
||||
|
||||
.scene-living {
|
||||
background:
|
||||
radial-gradient(circle at 14% 16%, rgba(121, 151, 95, 0.26), transparent 17%),
|
||||
radial-gradient(circle at 88% 20%, rgba(121, 151, 95, 0.22), transparent 14%),
|
||||
linear-gradient(180deg, #eee1cf 0%, #d8c1a1 100%);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.scene-living::before {
|
||||
content: "";
|
||||
width: 160rpx;
|
||||
height: 58rpx;
|
||||
margin-bottom: 44rpx;
|
||||
border-radius: 18rpx 18rpx 10rpx 10rpx;
|
||||
background: linear-gradient(180deg, #f4eadf, #bf9d7c);
|
||||
box-shadow: 0 48rpx 0 -18rpx rgba(106, 76, 52, 0.28);
|
||||
} */
|
||||
|
||||
.duration-badge {
|
||||
height: 34rpx;
|
||||
min-width: 68rpx;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 20rpx;
|
||||
font-weight: 800;
|
||||
background: rgba(0, 0, 0, 0.56);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.record-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 8rpx;
|
||||
}
|
||||
|
||||
.record-title {
|
||||
font-size: 27rpx;
|
||||
line-height: 1.25;
|
||||
font-weight: 900;
|
||||
color: #111622;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
margin-top: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tag {
|
||||
height: 34rpx;
|
||||
padding: 0 14rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #858b9d;
|
||||
background: #f3f4f8;
|
||||
font-size: 19rpx;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.record-time {
|
||||
margin-top: 18rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.2;
|
||||
color: #777d92;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.status-line {
|
||||
min-height: 34rpx;
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8rpx;
|
||||
font-size: 21rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.status-line.done {
|
||||
color: #32b975;
|
||||
}
|
||||
|
||||
.status-line.done text {
|
||||
height: 34rpx;
|
||||
padding: 0 16rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #dcf8e9;
|
||||
}
|
||||
|
||||
.status-line.processing {
|
||||
color: #686dff;
|
||||
}
|
||||
|
||||
.progress-dot {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid currentColor;
|
||||
border-top-color: rgba(104, 109, 255, 0.18);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.status-line.failed {
|
||||
color: #f06d67;
|
||||
}
|
||||
|
||||
.status-line.failed text {
|
||||
height: 34rpx;
|
||||
padding: 0 16rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff0ed;
|
||||
}
|
||||
|
||||
.action-row {
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.secondary-btn,
|
||||
.download-btn,
|
||||
.more-btn,
|
||||
.retry-btn {
|
||||
height: 50rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 21rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
flex: 1;
|
||||
min-width: 128rpx;
|
||||
color: #555b6e;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid #dadcff;
|
||||
}
|
||||
|
||||
.download-btn,
|
||||
.retry-btn {
|
||||
width: 158rpx;
|
||||
color: #ffffff;
|
||||
gap: 10rpx;
|
||||
background: linear-gradient(135deg, #5a84ff, #763fee);
|
||||
box-shadow: 0 8rpx 14rpx rgba(97, 86, 241, 0.24);
|
||||
}
|
||||
|
||||
.download-icon {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-bottom: 4rpx solid currentColor;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.download-icon::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 4rpx;
|
||||
height: 22rpx;
|
||||
margin: 0 auto;
|
||||
background: currentColor;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.download-icon::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
margin: -12rpx auto 0;
|
||||
border-right: 4rpx solid currentColor;
|
||||
border-bottom: 4rpx solid currentColor;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.more-btn,
|
||||
.retry-btn {
|
||||
background: #ffffff;
|
||||
color: #50566c;
|
||||
border: 2rpx solid #e0e2ff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
width: 100rpx;
|
||||
gap: 7rpx;
|
||||
}
|
||||
|
||||
.more-btn text {
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
|
||||
.thumb-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.duration-badge {
|
||||
position: absolute;
|
||||
left: 12rpx;
|
||||
bottom: 12rpx;
|
||||
}
|
||||
|
||||
.failed-btn.active {
|
||||
color: #999999;
|
||||
/* border-color: transparent; */
|
||||
/* background: linear-gradient(135deg, #f06d67 0%, #ff8a62 100%); */
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
min-height: 360rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #8a91a3;
|
||||
font-size: 25rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
import { historyCancel, historyDelete, historyDetail, historyDownload } from "../../../utils/request"
|
||||
|
||||
type DetailStatus = 'done' | 'processing' | 'failed'
|
||||
|
||||
const emptyDetail = {
|
||||
taskId: '',
|
||||
title: '',
|
||||
status: 'done',
|
||||
statusText: '',
|
||||
progress: 0,
|
||||
pageTitle: '作品详情',
|
||||
pageClass: 'success-page',
|
||||
videoUrl: '',
|
||||
coverUrl: '',
|
||||
duration: '',
|
||||
createTime: '',
|
||||
finishTime: '',
|
||||
failureTime: '',
|
||||
failureStage: '',
|
||||
failureReason: '',
|
||||
scriptText: '',
|
||||
avatar: { name: '默认数字人', imageUrl: '' },
|
||||
voice: { name: '默认音色', audioUrl: '' },
|
||||
background: { name: '默认背景', coverUrl: '', imageUrl: '' },
|
||||
steps: [] as any[],
|
||||
avatarImage: '/static/images/my/image.png',
|
||||
backgroundImage: '/static/images/my/image.png',
|
||||
videoCover: '/static/images/my/image.png',
|
||||
failureMessage: '生成失败,请稍后重试',
|
||||
failureDisplayTime: '',
|
||||
successTime: '',
|
||||
taskDisplayId: '',
|
||||
scriptDisplayText: '暂无文案',
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
status: 'done' as DetailStatus,
|
||||
isFailed: false,
|
||||
isProcessing: false,
|
||||
pageTitle: '作品详情',
|
||||
pageClass: 'success-page',
|
||||
taskId: '',
|
||||
detail: emptyDetail as any,
|
||||
progressStyle: 'width: 0%;',
|
||||
},
|
||||
|
||||
onLoad(query: Record<string, string | undefined>) {
|
||||
const status: DetailStatus = query.status === 'failed'
|
||||
? 'failed'
|
||||
: query.status === 'processing'
|
||||
? 'processing'
|
||||
: 'done'
|
||||
|
||||
this.setStatus(status, query.taskId || '')
|
||||
if (query.taskId) {
|
||||
this.loadDetail(query.taskId)
|
||||
}
|
||||
},
|
||||
|
||||
loadDetail(taskId: string) {
|
||||
wx.showLoading({ title: '加载中' })
|
||||
historyDetail(taskId).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '获取详情失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
const data = res.data || {}
|
||||
const detail = { ...emptyDetail, ...data }
|
||||
detail.avatar = { ...emptyDetail.avatar, ...(data.avatar || {}) }
|
||||
detail.voice = { ...emptyDetail.voice, ...(data.voice || {}) }
|
||||
detail.background = { ...emptyDetail.background, ...(data.background || {}) }
|
||||
detail.avatarImage = detail.avatar.imageUrl || '/static/images/my/image.png'
|
||||
detail.backgroundImage = detail.background.coverUrl || detail.background.imageUrl || '/static/images/my/image.png'
|
||||
detail.videoCover = detail.coverUrl || detail.avatar.imageUrl || '/static/images/my/image.png'
|
||||
detail.failureMessage = detail.failureReason || '生成失败,请稍后重试'
|
||||
detail.failureDisplayTime = detail.failureTime || detail.finishTime || detail.createTime
|
||||
detail.successTime = detail.finishTime || detail.createTime
|
||||
detail.taskDisplayId = detail.taskId || taskId
|
||||
detail.scriptDisplayText = detail.scriptText || '暂无文案';
|
||||
|
||||
let status = '';
|
||||
if (detail.status === 'failed') {
|
||||
status = 'failed';
|
||||
} else {
|
||||
status = detail.status === 'processing' ? 'processing' : 'done';
|
||||
}
|
||||
this.setData({
|
||||
detail,
|
||||
progressStyle: 'width: ' + Math.max(0, Math.min(100, Number(+detail.progress))) + '%;',
|
||||
})
|
||||
this.setStatus(status as DetailStatus, detail.taskId || taskId)
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
setStatus(status: DetailStatus, taskId: string) {
|
||||
this.setData({
|
||||
status,
|
||||
isFailed: status === 'failed',
|
||||
isProcessing: status === 'processing',
|
||||
pageTitle: status === 'failed' ? '失败详情' : status === 'processing' ? '生成详情' : '作品详情',
|
||||
pageClass: status === 'failed' ? 'failed-page' : status === 'processing' ? 'processing-page' : 'success-page',
|
||||
taskId,
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/history/history' }),
|
||||
})
|
||||
},
|
||||
|
||||
handleDownload() {
|
||||
if (!this.data.taskId) return
|
||||
|
||||
wx.showLoading({ title: '获取下载地址' })
|
||||
historyDownload(this.data.taskId).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '下载失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
|
||||
const url = (res.data && res.data.url) || ''
|
||||
if (url) {
|
||||
wx.setClipboardData({ data: url })
|
||||
} else {
|
||||
wx.showToast({ title: '暂无下载地址', icon: 'none' })
|
||||
}
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
|
||||
handleRetry() {
|
||||
wx.switchTab({ url: '/pages/index/index' })
|
||||
},
|
||||
|
||||
handleEdit() {
|
||||
wx.switchTab({ url: '/pages/index/index' })
|
||||
},
|
||||
|
||||
handleViewCopy() {
|
||||
this.handleCopyText()
|
||||
},
|
||||
|
||||
handleCopyText() {
|
||||
const detail = this.data.detail || {}
|
||||
const text = detail.scriptText || ''
|
||||
if (!text) {
|
||||
wx.showToast({ title: '暂无文案', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.setClipboardData({ data: text })
|
||||
},
|
||||
|
||||
handleSame() {
|
||||
wx.switchTab({ url: '/pages/index/index' })
|
||||
},
|
||||
|
||||
handleRecordVoice() {
|
||||
wx.switchTab({ url: '/pages/index/index' })
|
||||
},
|
||||
|
||||
handleBackToHistory() {
|
||||
wx.switchTab({ url: '/pages/history/history' })
|
||||
},
|
||||
|
||||
handleCancel() {
|
||||
if (!this.data.taskId) return
|
||||
|
||||
wx.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定取消当前生成任务吗?',
|
||||
success: (modal) => {
|
||||
if (!modal.confirm) return
|
||||
historyCancel(this.data.taskId).then((res: any) => {
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '取消失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
wx.showToast({ title: '已取消', icon: 'success' })
|
||||
this.loadDetail(this.data.taskId)
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
handleDelete() {
|
||||
if (!this.data.taskId) return
|
||||
|
||||
wx.showModal({
|
||||
title: '确认删除',
|
||||
content: '删除后将不再展示该创作记录',
|
||||
success: (modal) => {
|
||||
if (!modal.confirm) return
|
||||
historyDelete(this.data.taskId).then((res: any) => {
|
||||
if (res.code) {
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '删除失败', showCancel: false })
|
||||
return
|
||||
}
|
||||
wx.showToast({ title: '已删除', icon: 'success' })
|
||||
setTimeout(() => this.handleBackToHistory(), 400)
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<view class="detail-page {{pageClass}}">
|
||||
<custom-nav padding-x="42">
|
||||
<view class="detail-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<text class="nav-title">{{pageTitle}}</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="detail-content">
|
||||
<block wx:if="{{isFailed}}">
|
||||
<view class="failure-alert">
|
||||
<view class="alert-icon">!</view>
|
||||
<view class="alert-copy">
|
||||
<text class="alert-title">本次生成失败</text>
|
||||
<text class="alert-desc">{{detail.failureMessage}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-card fail-info-card">
|
||||
<view class="info-row"><text class="info-label">失败时间</text><text class="info-value">{{detail.failureDisplayTime}}</text></view>
|
||||
<view class="info-row"><text class="info-label">数字人形象</text><view class="value-with-thumb"><image class="mini-avatar icon-placeholder" src="{{detail.avatarImage}}" mode="aspectFit"></image><text>{{detail.avatar.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">背景模板</text><view class="value-with-thumb"><image class="mini-scene living-scene icon-placeholder" src="{{detail.backgroundImage}}" mode="aspectFit"></image><text>{{detail.background.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">音色状态</text><view class="voice-error"><text class="error-dot">未</text><text>{{detail.voice.name}}</text></view></view>
|
||||
<view class="info-row reason-row"><text class="info-label">失败原因</text><text class="reason-text">{{detail.failureMessage}}</text></view>
|
||||
</view>
|
||||
|
||||
<view class="advice-card"><view class="advice-head"><image class="bulb-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>建议</text></view><text class="advice-text">建议检查数字人形象、音色和口播文案后重新生成。</text></view>
|
||||
<view class="primary-action" bindtap="handleRetry">重新生成</view>
|
||||
<view class="outline-action" bindtap="handleRecordVoice"><image class="voice-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>重新录取音色</text></view>
|
||||
<view class="delete-link" bindtap="handleDelete">删除记录</view>
|
||||
</block>
|
||||
|
||||
<block wx:elif="{{isProcessing}}">
|
||||
<view class="processing-card">
|
||||
<view class="processing-head">
|
||||
<view class="ai-visual"><view class="ai-box">AI</view><view class="ai-base"></view></view>
|
||||
<view class="processing-copy">
|
||||
<text class="processing-title">AI 正在生成中</text>
|
||||
<text class="processing-desc">请耐心等待,精彩内容即将呈现</text>
|
||||
<view class="progress-row"><view class="progress-track"><view class="progress-fill" style="{{progressStyle}}"></view></view><text>{{detail.progress}}%</text></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stage-row">
|
||||
<view wx:for="{{detail.steps}}" wx:key="code" class="stage-item {{item.status === 2 ? 'done' : item.status === 1 ? 'active' : ''}}"><view class="stage-dot {{item.status === 1 ? 'loading' : item.status === 0 ? 'empty' : ''}}"><text wx:if="{{item.status === 2}}"></text></view><text>{{item.name}}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-card processing-info-card">
|
||||
<view class="info-row"><text class="info-label">任务ID</text><text class="info-value">{{detail.taskDisplayId}}</text></view>
|
||||
<view class="info-row"><text class="info-label">数字人形象</text><view class="value-with-thumb"><image class="mini-avatar icon-placeholder" src="{{detail.avatarImage}}" mode="aspectFit"></image><text>{{detail.avatar.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">背景模板</text><view class="value-with-thumb"><image class="mini-scene product-scene icon-placeholder" src="{{detail.backgroundImage}}" mode="aspectFit"></image><text>{{detail.background.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">音色</text><view class="value-with-thumb"><image class="audio-thumb icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>{{detail.voice.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">创建时间</text><view class="value-with-thumb"><image class="clock-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>{{detail.createTime}}</text></view></view>
|
||||
</view>
|
||||
|
||||
<view class="primary-action" bindtap="handleBackToHistory">返回创作记录</view>
|
||||
<view class="outline-action" bindtap="handleCancel">取消任务</view>
|
||||
<view class="bottom-tip"><image class="bulb-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>生成完成后会自动保存到创作记录</text></view>
|
||||
</block>
|
||||
|
||||
<block wx:else>
|
||||
<view class="video-card scene-live"><image class="speaker-avatar icon-placeholder" src="{{detail.videoCover}}" mode="aspectFit"></image><image class="play-circle icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><view class="duration-badge">{{detail.duration}}</view></view>
|
||||
|
||||
<view class="info-card work-info-card">
|
||||
<view class="info-row"><text class="info-label">创作状态</text><text class="status-done">{{detail.statusText}}</text></view>
|
||||
<view class="info-row"><text class="info-label">生成时间</text><text class="info-value">{{detail.successTime}}</text></view>
|
||||
<view class="info-row"><text class="info-label">数字人形象</text><view class="value-with-thumb"><image class="mini-avatar icon-placeholder" src="{{detail.avatarImage}}" mode="aspectFit"></image><text>{{detail.avatar.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">背景模板</text><view class="value-with-thumb"><image class="mini-scene live-scene icon-placeholder" src="{{detail.backgroundImage}}" mode="aspectFit"></image><text>{{detail.background.name}}</text></view></view>
|
||||
<view class="info-row"><text class="info-label">音色</text><view class="value-with-thumb"><image class="audio-thumb icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>{{detail.voice.name}}</text></view></view>
|
||||
<view class="info-row copy-row"><text class="info-label">口播文案</text><view class="copy-content"><text>{{detail.scriptDisplayText}}</text><view class="view-copy" bindtap="handleViewCopy">复制文案 <text></text></view></view></view>
|
||||
</view>
|
||||
|
||||
<view class="action-buttons"><view class="download-action" bindtap="handleDownload"><image class="download-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>下载视频</text></view><view class="outline-action small" bindtap="handleRetry"><image class="refresh-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>重新生成</text></view><view class="outline-action small" bindtap="handleEdit"><image class="edit-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>继续编辑</text></view></view>
|
||||
<view class="related-card"><text class="related-title">相关操作</text><view class="related-item" bindtap="handleCopyText"><image class="copy-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>复制文案</text><text class="item-arrow"></text></view><view class="related-item" bindtap="handleSame"><image class="refresh-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>再次生成同款</text><text class="item-arrow"></text></view><view class="related-item danger" bindtap="handleDelete"><image class="trash-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image><text>删除记录</text><text class="item-arrow"></text></view></view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,732 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #fbfcff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.detail-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfcff 58%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.detail-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-placeholder {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 31rpx;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18rpx;
|
||||
padding: 24rpx 20rpx 34rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.video-card {
|
||||
height: 332rpx;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background:
|
||||
radial-gradient(circle at 12% 30%, rgba(111, 139, 78, 0.34), transparent 15%),
|
||||
radial-gradient(circle at 88% 30%, rgba(111, 139, 78, 0.26), transparent 13%),
|
||||
linear-gradient(90deg, #e7d9c7 0%, #faf2e8 52%, #d8c4a9 100%);
|
||||
}
|
||||
|
||||
.speaker-avatar {
|
||||
width: 150rpx;
|
||||
height: 230rpx;
|
||||
border-radius: 75rpx 75rpx 24rpx 24rpx;
|
||||
background:
|
||||
radial-gradient(circle at 38% 36%, #17131a 0 6rpx, transparent 7rpx),
|
||||
radial-gradient(circle at 62% 36%, #17131a 0 6rpx, transparent 7rpx),
|
||||
radial-gradient(circle at 50% 50%, #df7f87 0 8rpx, transparent 9rpx),
|
||||
linear-gradient(180deg, #17131a 0 28%, #ffe0cd 28% 50%, #ffffff 50% 100%);
|
||||
}
|
||||
|
||||
.play-circle {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
margin-left: -126rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.38);
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.76);
|
||||
}
|
||||
|
||||
.play-circle text {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 24rpx solid transparent;
|
||||
border-bottom: 24rpx solid transparent;
|
||||
border-left: 34rpx solid #ffffff;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.duration-badge {
|
||||
align-self: flex-end;
|
||||
margin-left: -310rpx;
|
||||
margin-bottom: 18rpx;
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #ffffff;
|
||||
font-size: 20rpx;
|
||||
font-weight: 900;
|
||||
background: rgba(0, 0, 0, 0.56);
|
||||
}
|
||||
|
||||
.info-card,
|
||||
.related-card,
|
||||
.failure-alert,
|
||||
.advice-card {
|
||||
border-radius: 15rpx;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border: 1rpx solid #eef1fb;
|
||||
box-shadow: 0 6rpx 18rpx rgba(82, 90, 146, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
padding: 18rpx 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
min-height: 54rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
border-bottom: 1rpx solid #eef0f6;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 150rpx;
|
||||
flex-shrink: 0;
|
||||
color: #596072;
|
||||
font-size: 22rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.info-value,
|
||||
.value-with-thumb {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 16rpx;
|
||||
color: #33394b;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.status-done {
|
||||
color: #32c07a;
|
||||
font-size: 22rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.mini-avatar {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 10rpx;
|
||||
background: linear-gradient(180deg, #1e1b20 0 35%, #ffd8c8 35% 62%, #ffffff 62% 100%);
|
||||
}
|
||||
|
||||
.mini-scene {
|
||||
width: 50rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 5rpx;
|
||||
}
|
||||
|
||||
.live-scene {
|
||||
background: linear-gradient(135deg, #eadfcc, #ffffff 52%, #bbc99d);
|
||||
}
|
||||
|
||||
.living-scene {
|
||||
background: linear-gradient(135deg, #e0c6a6, #fff4e9 52%, #b28b68);
|
||||
}
|
||||
|
||||
.audio-thumb {
|
||||
width: 50rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f1efff;
|
||||
}
|
||||
|
||||
.audio-thumb text,
|
||||
.voice-icon,
|
||||
.refresh-icon,
|
||||
.copy-icon,
|
||||
.edit-icon,
|
||||
.download-icon,
|
||||
.trash-icon {
|
||||
display: block;
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
.audio-thumb text {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
border-left: 5rpx solid #665cff;
|
||||
border-right: 5rpx solid #665cff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.copy-row {
|
||||
align-items: flex-start;
|
||||
padding: 14rpx 0;
|
||||
}
|
||||
|
||||
.copy-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 12rpx;
|
||||
color: #33394b;
|
||||
font-size: 21rpx;
|
||||
line-height: 1.45;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.view-copy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #665cff;
|
||||
font-size: 21rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.view-copy text,
|
||||
.item-arrow {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-top: 4rpx solid currentColor;
|
||||
border-right: 4rpx solid currentColor;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 22rpx;
|
||||
}
|
||||
|
||||
.download-action,
|
||||
.outline-action,
|
||||
.primary-action {
|
||||
height: 66rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
font-size: 23rpx;
|
||||
font-weight: 900;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.download-action,
|
||||
.primary-action {
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #4f85ff 0%, #7d42f0 100%);
|
||||
box-shadow: 0 8rpx 18rpx rgba(91, 83, 244, 0.18);
|
||||
}
|
||||
|
||||
.outline-action {
|
||||
color: #665cff;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid #dcdcff;
|
||||
}
|
||||
|
||||
.download-icon {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
border-bottom: 4rpx solid currentColor;
|
||||
}
|
||||
|
||||
.refresh-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
border-left-color: transparent;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
border-left: 5rpx solid currentColor;
|
||||
border-bottom: 5rpx solid currentColor;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.related-card {
|
||||
padding: 22rpx 24rpx;
|
||||
}
|
||||
|
||||
.related-title {
|
||||
display: block;
|
||||
padding-bottom: 18rpx;
|
||||
color: #121722;
|
||||
font-size: 25rpx;
|
||||
font-weight: 900;
|
||||
border-bottom: 1rpx solid #edf0f6;
|
||||
}
|
||||
|
||||
.related-item {
|
||||
min-height: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
color: #4b5262;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
border-bottom: 1rpx solid #edf0f6;
|
||||
}
|
||||
|
||||
.related-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.related-item text:nth-child(2) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.related-item.danger {
|
||||
color: #ff5d59;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 4rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.trash-icon {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
border-top: 0;
|
||||
border-radius: 0 0 5rpx 5rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.failure-alert {
|
||||
min-height: 146rpx;
|
||||
padding: 28rpx 36rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30rpx;
|
||||
background: #fff4f2;
|
||||
border-color: #ffd2ce;
|
||||
}
|
||||
|
||||
.alert-icon {
|
||||
width: 80rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 42rpx;
|
||||
font-weight: 900;
|
||||
background: #f05a52;
|
||||
transform: perspective(120rpx) rotateX(8deg);
|
||||
}
|
||||
|
||||
.alert-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.alert-title {
|
||||
color: #e64038;
|
||||
font-size: 29rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.alert-desc {
|
||||
color: #7d5d5d;
|
||||
font-size: 23rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.fail-info-card .info-row {
|
||||
min-height: 66rpx;
|
||||
}
|
||||
|
||||
.voice-error {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10rpx;
|
||||
color: #ef514c;
|
||||
font-size: 24rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.error-dot {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 17rpx;
|
||||
background: #ef514c;
|
||||
}
|
||||
|
||||
.reason-row {
|
||||
align-items: flex-start;
|
||||
padding: 18rpx 0;
|
||||
}
|
||||
|
||||
.reason-text {
|
||||
flex: 1;
|
||||
color: #505668;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.45;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.advice-card {
|
||||
padding: 24rpx 28rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18rpx;
|
||||
background: #fff9ea;
|
||||
border-color: #f6d99e;
|
||||
}
|
||||
|
||||
.advice-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
color: #4b2a0d;
|
||||
font-size: 25rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.bulb-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border: 4rpx solid #ad7b2b;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.advice-text {
|
||||
color: #5a6274;
|
||||
font-size: 23rpx;
|
||||
line-height: 1.65;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.failed-page .primary-action,
|
||||
.failed-page .outline-action {
|
||||
height: 84rpx;
|
||||
border-radius: 13rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.failed-page .outline-action {
|
||||
border-color: #dcdcff;
|
||||
}
|
||||
|
||||
.voice-icon {
|
||||
width: 24rpx;
|
||||
height: 28rpx;
|
||||
border-left: 5rpx solid currentColor;
|
||||
border-right: 5rpx solid currentColor;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.delete-link {
|
||||
height: 72rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #f05a52;
|
||||
font-size: 28rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.processing-page .detail-content {
|
||||
gap: 26rpx;
|
||||
padding-left: 32rpx;
|
||||
padding-right: 32rpx;
|
||||
}
|
||||
|
||||
.processing-card {
|
||||
border-radius: 17rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #ffffff;
|
||||
border: 1rpx solid #e6e9fb;
|
||||
box-shadow: 0 8rpx 22rpx rgba(82, 90, 146, 0.06);
|
||||
}
|
||||
|
||||
.processing-head {
|
||||
min-height: 226rpx;
|
||||
padding: 28rpx 28rpx 26rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30rpx;
|
||||
background: linear-gradient(100deg, #f4f6ff, #ffffff);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ai-visual {
|
||||
width: 178rpx;
|
||||
height: 158rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ai-box {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(135deg, #7d74ff, #3c93f4);
|
||||
box-shadow: 22rpx 10rpx 0 rgba(86, 204, 255, 0.26), 0 14rpx 26rpx rgba(77, 83, 234, 0.24);
|
||||
}
|
||||
|
||||
.ai-base {
|
||||
width: 150rpx;
|
||||
height: 42rpx;
|
||||
margin-top: -2rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(90deg, #6d55f3, #ffffff 50%, #8a78ff);
|
||||
box-shadow: 0 10rpx 18rpx rgba(96, 116, 255, 0.18);
|
||||
}
|
||||
|
||||
.processing-copy {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.processing-title {
|
||||
color: #101522;
|
||||
font-size: 34rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.processing-desc {
|
||||
margin-top: 16rpx;
|
||||
color: #6d7385;
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
margin-top: 34rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
color: #4a4e63;
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.progress-track {
|
||||
flex: 1;
|
||||
height: 16rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #e5e6fb;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
width: 78%;
|
||||
height: 100%;
|
||||
border-radius: 999rpx;
|
||||
background: linear-gradient(90deg, #4d82ff, #7d42f0);
|
||||
}
|
||||
|
||||
.stage-row {
|
||||
min-height: 150rpx;
|
||||
padding: 28rpx 28rpx 22rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
border-top: 1rpx solid #edf0f7;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.stage-item {
|
||||
width: 104rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
color: #575e70;
|
||||
font-size: 21rpx;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stage-dot {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 4rpx solid #d5d4ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.stage-item.done .stage-dot {
|
||||
background: #5d6dff;
|
||||
border-color: #5d6dff;
|
||||
}
|
||||
|
||||
.stage-dot text {
|
||||
width: 17rpx;
|
||||
height: 9rpx;
|
||||
border-left: 4rpx solid #ffffff;
|
||||
border-bottom: 4rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.stage-dot.loading {
|
||||
border-color: #6d5fff;
|
||||
border-top-color: rgba(109, 95, 255, 0.16);
|
||||
}
|
||||
|
||||
.stage-line {
|
||||
width: 78rpx;
|
||||
height: 4rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #d8d8ff;
|
||||
}
|
||||
|
||||
.stage-line.dashed {
|
||||
background: repeating-linear-gradient(90deg, #d8d8ff 0 10rpx, transparent 10rpx 18rpx);
|
||||
}
|
||||
|
||||
.processing-info-card .info-row {
|
||||
min-height: 74rpx;
|
||||
}
|
||||
|
||||
.product-scene {
|
||||
background: linear-gradient(135deg, #eadfcc, #fff8ef 52%, #c8b089);
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid #665cff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.processing-page .primary-action,
|
||||
.processing-page .outline-action {
|
||||
height: 84rpx;
|
||||
border-radius: 13rpx;
|
||||
font-size: 29rpx;
|
||||
}
|
||||
|
||||
.bottom-tip {
|
||||
height: 72rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14rpx;
|
||||
color: #6d69c9;
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
background: #f4f5ff;
|
||||
border: 1rpx solid #e2e5ff;
|
||||
}
|
||||
|
||||
.bottom-tip .bulb-icon {
|
||||
border-color: #75a4ff;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav",
|
||||
"checkin-popup": "/components/checkin-popup/checkin-popup"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import { analysis, tasksearch, polishScript, createTask } from "../../utils/request"
|
||||
|
||||
const sampleText = '解析中...'
|
||||
const checkinStorageKey = 'lastCheckinDate'
|
||||
|
||||
function getTodayKey() {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
Component({
|
||||
data: {
|
||||
parsed: false,
|
||||
videoLink: '',
|
||||
scriptText: sampleText,
|
||||
showCheckinPopup: false,
|
||||
taskId: '',
|
||||
parseId: '',
|
||||
polishing: false
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
const today = getTodayKey()
|
||||
const lastCheckinDate = wx.getStorageSync(checkinStorageKey)
|
||||
|
||||
if (lastCheckinDate !== today) {
|
||||
this.setData({ showCheckinPopup: true })
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleInput(e: any) {
|
||||
this.setData({
|
||||
videoLink: e.detail.value,
|
||||
})
|
||||
},
|
||||
onUnload() {
|
||||
this.setData({ videoLink: '', parsed: false, scriptText: '' })
|
||||
},
|
||||
handlePaste() {
|
||||
wx.getClipboardData({
|
||||
success: (res) => {
|
||||
this.setData({
|
||||
videoLink: res.data || '0.58 J@i.cN 08/24 :0pm ULw:/ # 新到 # 国五排放 # 货车出售转让 https://v.douyin.com/tHoCmTcQT2Q/ 复制此链接,打开Dou音搜索,直接观看视频!',
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
this.setData({
|
||||
videoLink: '0.58 J@i.cN 08/24 :0pm ULw:/ # 新到 # 国五排放 # 货车出售转让 https://v.douyin.com/tHoCmTcQT2Q/ 复制此链接,打开Dou音搜索,直接观看视频!',
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
handleParse() {
|
||||
if (this.data.videoLink == '') {
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '解析链接不能为空',
|
||||
showCancel: false
|
||||
})
|
||||
return;
|
||||
}
|
||||
wx.showLoading({ title: '解析中.' });
|
||||
analysis(this.data.videoLink).then((res: any) => {
|
||||
console.log(res);
|
||||
wx.hideLoading();
|
||||
if (!res.code) {
|
||||
this.setData({
|
||||
parsed: true,
|
||||
taskId: '',
|
||||
parseId: String(res.data.parseId || res.data.taskId || '')
|
||||
})
|
||||
wx.showLoading({ title: '等待结果中...', mask: true });
|
||||
this.tasksearch(String(res.data.parseId || res.data.taskId || ''))
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '解析失败,请确认链接的有效性',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
wx.hideLoading();
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '解析失败,请重试',
|
||||
showCancel: false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
tasksearch(taskId: string) {
|
||||
let that = this;
|
||||
tasksearch(taskId).then((res: any) => {
|
||||
if (!res.code) {
|
||||
wx.hideLoading();
|
||||
|
||||
this.setData({ scriptText: (res.data && res.data.scriptText) || '' })
|
||||
} else {
|
||||
setTimeout(() => that.tasksearch(taskId), 500);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleReset() {
|
||||
this.setData({
|
||||
parsed: false,
|
||||
scriptText: '',
|
||||
})
|
||||
this.handleParse();
|
||||
},
|
||||
handleCopy() {
|
||||
wx.setClipboardData({
|
||||
data: this.data.scriptText,
|
||||
fail(err) {
|
||||
console.log(err);
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '您还未授于剪切板权限'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handlePolish() {
|
||||
if (!(this.data.parseId || this.data.taskId) || !this.data.scriptText) {
|
||||
wx.showToast({ title: '暂无可润色文案', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (this.data.polishing) return
|
||||
|
||||
this.setData({ polishing: true })
|
||||
wx.showLoading({ title: '润色中...', mask: true })
|
||||
polishScript(this.data.parseId || this.data.taskId, this.data.scriptText, 'optimize').then((res: any) => {
|
||||
wx.hideLoading()
|
||||
this.setData({ polishing: false })
|
||||
if (!res.code) {
|
||||
this.setData({ scriptText: res.data.scriptText })
|
||||
wx.showToast({ title: '已润色', icon: 'success' })
|
||||
return
|
||||
}
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '润色失败,请稍后再试', showCancel: false })
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
wx.hideLoading()
|
||||
this.setData({ polishing: false })
|
||||
wx.showModal({ title: '温馨提示', content: '润色失败,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
handleGoCreate() {
|
||||
const parseId = this.data.parseId || this.data.taskId
|
||||
if (!parseId || !this.data.scriptText) {
|
||||
wx.showToast({ title: '请先完成文案提取', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
wx.showLoading({ title: '创建任务中', mask: true })
|
||||
createTask(parseId, this.data.scriptText).then((res: any) => {
|
||||
wx.hideLoading()
|
||||
if (!res.code && res.data && res.data.taskId) {
|
||||
this.setData({ taskId: res.data.taskId })
|
||||
wx.navigateTo({
|
||||
url: '/pages/aiPackage/preview/index?taskId=' + res.data.taskId,
|
||||
})
|
||||
return
|
||||
}
|
||||
wx.showModal({ title: '温馨提示', content: res.message || '创建任务失败,请稍后再试', showCancel: false })
|
||||
}).catch(() => {
|
||||
wx.hideLoading()
|
||||
wx.showModal({ title: '温馨提示', content: '网络异常,请稍后再试', showCancel: false })
|
||||
})
|
||||
},
|
||||
handleExperience() {
|
||||
this.setData({
|
||||
videoLink: 'https://v.douyin.com/example/',
|
||||
parsed: true,
|
||||
})
|
||||
},
|
||||
handleCheckinClose() {
|
||||
wx.setStorageSync(checkinStorageKey, getTodayKey())
|
||||
this.setData({ showCheckinPopup: false })
|
||||
},
|
||||
handleCheckinRule() {
|
||||
wx.showToast({ title: '每日签到可领取金币', icon: 'none' })
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<view class="home-page">
|
||||
<custom-nav padding-x="28">
|
||||
<view class="topbar">
|
||||
<text class="brand">数字人视频工厂</text>
|
||||
<view class="coin-pill">
|
||||
<image class="coin-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text class="coin-label">金币</text>
|
||||
<text class="coin-count">128</text>
|
||||
</view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="home-content">
|
||||
<view class="hero">
|
||||
<image src="../../static/images/indexed/top.png" style="width: 698rpx;height: 228rpx;"></image>
|
||||
</view>
|
||||
|
||||
<view class="card parse-card">
|
||||
<view class="card-head">
|
||||
<view class="section-title">
|
||||
<text class="step-dot">1</text>
|
||||
<text>粘贴视频链接</text>
|
||||
</view>
|
||||
<view class="help-link">
|
||||
<text class="help-dot">?</text>
|
||||
<text>如何获取链接?</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="input-row">
|
||||
<input class="link-input" value="{{videoLink}}" placeholder="粘贴视频链接到这里" placeholder-class="input-placeholder" bindinput="handleInput" />
|
||||
<view class="paste-btn" bindtap="handlePaste">一键粘贴</view>
|
||||
</view>
|
||||
|
||||
<view class="primary-action" bindtap="handleParse">
|
||||
<image class="plane-icon icon-placeholder" src="/static/images/xfj.png" mode="aspectFit"></image>
|
||||
<text>开始解析</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<block wx:if="{{parsed}}">
|
||||
<view class="success-strip">
|
||||
<image class="success-icon icon-placeholder" src="/static/images/checked.png" mode="aspectFit"></image>
|
||||
<view class="success-copy">
|
||||
<text class="success-title">链接解析成功</text>
|
||||
<text class="success-subtitle">已为你提取到口播文案</text>
|
||||
</view>
|
||||
<view class="outline-btn" bindtap="handleReset">重新解析</view>
|
||||
</view>
|
||||
|
||||
<view class="card copy-card">
|
||||
<view class="card-head copy-head">
|
||||
<text class="copy-title">提取到的文案</text>
|
||||
<view class="copy-btn" bindtap="handleCopy">
|
||||
<image class="copy-icon icon-placeholder" src="/static/images/file_copy.png" mode="aspectFit"></image>
|
||||
<text>复制文案</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="copy-box">
|
||||
<text>{{scriptText}}</text>
|
||||
</view>
|
||||
<view class="polish-btn" bindtap="handlePolish">
|
||||
<view class="polish-text">
|
||||
<image class="spark-icon icon-placeholder" src="/static/images/filter-3-filled.png" mode="aspectFit"></image>
|
||||
<text class="polish-title">AI 一键润色</text>
|
||||
</view>
|
||||
<view><text class="polish-subtitle">让口播更自然,更吸引人</text></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tip-strip">
|
||||
<image class="tip-icon icon-placeholder" src="/static/images/lightbulb.png" mode="aspectFit"></image>
|
||||
<text>润色后可进入下一步,设置数字人和视频背景</text>
|
||||
</view>
|
||||
|
||||
<view class="generate-btn" bindtap="handleGoCreate">
|
||||
<text>去生成数字人视频</text>
|
||||
<image class="arrow-icon icon-placeholder" src="/static/images/chevron-down.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<block wx:else>
|
||||
<view class="flow-card">
|
||||
<image src="../../static/images/indexed/lc_card.png" style="width: 699rpx;height: 298rpx;"></image>
|
||||
</view>
|
||||
|
||||
<view class="sample-card" bindtap="handleExperience">
|
||||
<image src="../../static/images/indexed/down_bottom.png" style="width: 100%;" mode="widthFix"></image>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<checkin-popup visible="{{showCheckinPopup}}" bind:close="handleCheckinClose" bind:rule="handleCheckinRule"></checkin-popup>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -0,0 +1,809 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8faff;
|
||||
color: #101522;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.home-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
/* background:
|
||||
radial-gradient(circle at 74% 11%, rgba(116, 114, 255, 0.13), transparent 18%),
|
||||
linear-gradient(180deg, #ffffff 0%, #f7f9ff 56%, #ffffff 100%); */
|
||||
}
|
||||
|
||||
.home-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
padding: 22rpx 28rpx 22rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
font-size: 32rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
color: #121521;
|
||||
}
|
||||
|
||||
.coin-pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
height: 52rpx;
|
||||
margin-right: 160rpx;
|
||||
margin-bottom: 10rpx;
|
||||
padding: 0 22rpx 0 12rpx;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: 0 6rpx 18rpx rgba(84, 91, 167, 0.14);
|
||||
border: 1rpx solid rgba(222, 226, 255, 0.88);
|
||||
}
|
||||
|
||||
.coin-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 18rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #ffd875, #ff9f25);
|
||||
}
|
||||
|
||||
.coin-label {
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
color: #25283a;
|
||||
}
|
||||
|
||||
.coin-count {
|
||||
font-size: 26rpx;
|
||||
font-weight: 800;
|
||||
color: #6763ff;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 238rpx;
|
||||
padding-top: 16rpx;
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hero-title-accent,
|
||||
.hero-title-main {
|
||||
display: block;
|
||||
font-size: 44rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.hero-title-accent {
|
||||
color: #6356ff;
|
||||
text-shadow: 0 5rpx 0 rgba(99, 86, 255, 0.12);
|
||||
}
|
||||
|
||||
.hero-title-main {
|
||||
margin-top: 10rpx;
|
||||
color: #070a16;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
margin-top: 32rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.4;
|
||||
color: #4a4e5d;
|
||||
}
|
||||
|
||||
.hero-visual {
|
||||
width: 236rpx;
|
||||
min-height: 202rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.visual-halo {
|
||||
width: 162rpx;
|
||||
height: 162rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, rgba(111, 107, 255, 0.18), rgba(92, 191, 255, 0.05));
|
||||
margin-bottom: -138rpx;
|
||||
transform: translateX(18rpx);
|
||||
}
|
||||
|
||||
.visual-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: -16rpx;
|
||||
}
|
||||
|
||||
.video-tile {
|
||||
width: 110rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #7d6dff 0%, #358cf3 100%);
|
||||
box-shadow: 22rpx 12rpx 0 rgba(81, 210, 255, 0.34), 0 16rpx 34rpx rgba(77, 83, 234, 0.34);
|
||||
transform: translateY(-18rpx);
|
||||
}
|
||||
|
||||
.play-mark {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 24rpx solid transparent;
|
||||
border-bottom: 24rpx solid transparent;
|
||||
border-left: 34rpx solid #ffffff;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.ai-chip {
|
||||
width: 48rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #579dff, #8852ff);
|
||||
box-shadow: 0 10rpx 22rpx rgba(109, 88, 255, 0.28);
|
||||
margin-left: -4rpx;
|
||||
transform: translateY(8rpx);
|
||||
}
|
||||
|
||||
.orbital-base {
|
||||
width: 178rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(90deg, #6c55f8, #edf6ff 46%, #8873ff);
|
||||
box-shadow: 0 12rpx 22rpx rgba(96, 116, 255, 0.22);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.base-center {
|
||||
width: 110rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
box-shadow: inset 0 0 14rpx rgba(92, 115, 255, 0.2);
|
||||
}
|
||||
|
||||
.card,
|
||||
.sample-card,
|
||||
.success-strip,
|
||||
.tip-strip {
|
||||
/* border: 1rpx solid rgba(215, 220, 249, 0.95); */
|
||||
box-shadow: 0 8rpx 24rpx rgba(74, 88, 148, 0.06);
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 18rpx;
|
||||
padding: 26rpx 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 800;
|
||||
color: #141720;
|
||||
}
|
||||
|
||||
.step-dot {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 20rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #506bff, #8155ff);
|
||||
}
|
||||
|
||||
.help-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #8389a5;
|
||||
font-size: 21rpx;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.help-dot {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid #a7add3;
|
||||
font-size: 17rpx;
|
||||
line-height: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
margin-top: 26rpx;
|
||||
height: 84rpx;
|
||||
padding: 0 16rpx 0 22rpx;
|
||||
border-radius: 14rpx;
|
||||
border: 2rpx solid #d8d5ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.link-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 80rpx;
|
||||
font-size: 25rpx;
|
||||
color: #2a3041;
|
||||
}
|
||||
|
||||
.input-placeholder {
|
||||
color: #a9aec6;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.paste-btn {
|
||||
width: 124rpx;
|
||||
height: 50rpx;
|
||||
text-align: center;
|
||||
line-height: 50rpx;
|
||||
border-radius: 10rpx;
|
||||
color: #ffffff;
|
||||
font-size: 22rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #528bff, #7b52ff);
|
||||
}
|
||||
|
||||
.primary-action,
|
||||
.polish-btn,
|
||||
.generate-btn,
|
||||
.sample-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #4f85ff 0%, #8b3df0 100%);
|
||||
box-shadow: 0 8rpx 18rpx rgba(84, 96, 255, 0.18);
|
||||
}
|
||||
|
||||
.primary-action {
|
||||
margin-top: 28rpx;
|
||||
height: 74rpx;
|
||||
border-radius: 14rpx;
|
||||
gap: 18rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.plane-icon {
|
||||
width: 28rpx;
|
||||
height: 22rpx;
|
||||
display: block;
|
||||
border-top: 10rpx solid transparent;
|
||||
border-bottom: 10rpx solid transparent;
|
||||
border-left: 32rpx solid #ffffff;
|
||||
box-sizing: border-box;
|
||||
transform: rotate(-22deg);
|
||||
}
|
||||
|
||||
.success-strip {
|
||||
min-height: 70rpx;
|
||||
border-radius: 18rpx;
|
||||
padding: 12rpx 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
background: linear-gradient(90deg, #e7fbf0 0%, #f6fffb 100%);
|
||||
border-color: #c8f1dc;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
background: #24c878;
|
||||
}
|
||||
|
||||
.check-mark {
|
||||
width: 18rpx;
|
||||
height: 10rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #ffffff;
|
||||
border-bottom: 5rpx solid #ffffff;
|
||||
transform: rotate(-45deg) translateY(-2rpx);
|
||||
}
|
||||
|
||||
.success-copy {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.success-title {
|
||||
color: #131720;
|
||||
font-size: 25rpx;
|
||||
font-weight: 800;
|
||||
line-height: 1.18;
|
||||
}
|
||||
|
||||
.success-subtitle {
|
||||
margin-top: 4rpx;
|
||||
color: #747b8d;
|
||||
font-size: 21rpx;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.outline-btn {
|
||||
width: 118rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 999rpx;
|
||||
border: 2rpx solid #c4c4ff;
|
||||
color: #7165ff;
|
||||
text-align: center;
|
||||
line-height: 46rpx;
|
||||
font-size: 21rpx;
|
||||
font-weight: 800;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.copy-card {
|
||||
gap: 18rpx;
|
||||
padding-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.copy-head {
|
||||
min-height: 36rpx;
|
||||
}
|
||||
|
||||
.copy-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 800;
|
||||
color: #121722;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
height: 38rpx;
|
||||
padding: 0 12rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
border: 1rpx solid #e0ddff;
|
||||
color: #665fff;
|
||||
background: #ffffff;
|
||||
font-size: 21rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
display: block;
|
||||
border: 3rpx solid currentColor;
|
||||
border-radius: 3rpx;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 6rpx -5rpx 0 -2rpx #ffffff, 6rpx -5rpx 0 0 currentColor;
|
||||
}
|
||||
|
||||
.copy-box {
|
||||
min-height: 168rpx;
|
||||
padding: 12rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #d7d5ff;
|
||||
color: #232838;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.55;
|
||||
font-weight: 600;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.polish-btn {
|
||||
height: 72rpx;
|
||||
border-radius: 13rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.spark-icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
display: block;
|
||||
margin-right: 10rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 4rpx;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.polish-text {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
/* gap: 4rpx; */
|
||||
}
|
||||
|
||||
.polish-title {
|
||||
font-size: 28rpx;
|
||||
line-height: 1;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.polish-subtitle {
|
||||
font-size: 20rpx;
|
||||
line-height: 1;
|
||||
color: rgba(255, 255, 255, 0.82);
|
||||
}
|
||||
|
||||
.tip-strip {
|
||||
min-height: 44rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
color: #6569ff;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
background: #f8faff;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid #6867ff;
|
||||
box-sizing: border-box;
|
||||
font-size: 18rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.generate-btn {
|
||||
height: 58rpx;
|
||||
border-radius: 13rpx;
|
||||
gap: 28rpx;
|
||||
font-size: 27rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
display: block;
|
||||
border-top: 5rpx solid #ffffff;
|
||||
border-right: 5rpx solid #ffffff;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.flow-card {
|
||||
/* padding-top: 28rpx;
|
||||
padding-bottom: 30rpx;
|
||||
*/
|
||||
}
|
||||
|
||||
.flow-heading {
|
||||
font-size: 27rpx;
|
||||
font-weight: 800;
|
||||
color: #161923;
|
||||
}
|
||||
|
||||
.flow-list {
|
||||
margin-top: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flow-item {
|
||||
width: 178rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.flow-icon {
|
||||
width: 86rpx;
|
||||
height: 82rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #6455ff;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(145deg, #ffffff, #eef1ff);
|
||||
box-shadow: inset 0 0 0 2rpx rgba(213, 218, 255, 0.9), 0 8rpx 16rpx rgba(85, 96, 160, 0.08);
|
||||
}
|
||||
|
||||
.chain-icon text,
|
||||
.chain-icon::after {
|
||||
width: 34rpx;
|
||||
height: 20rpx;
|
||||
border: 6rpx solid currentColor;
|
||||
border-radius: 999rpx;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chain-icon {
|
||||
gap: 0;
|
||||
transform: rotate(-36deg);
|
||||
}
|
||||
|
||||
.chain-icon::after {
|
||||
content: "";
|
||||
margin-left: -10rpx;
|
||||
}
|
||||
|
||||
.doc-icon {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.bot-icon text {
|
||||
width: 48rpx;
|
||||
height: 34rpx;
|
||||
display: block;
|
||||
border-radius: 16rpx;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.bot-icon text::before,
|
||||
.bot-icon text::after {
|
||||
content: "";
|
||||
display: block;
|
||||
}
|
||||
|
||||
.flow-title {
|
||||
margin-top: 18rpx;
|
||||
color: #141720;
|
||||
font-size: 22rpx;
|
||||
font-weight: 800;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.flow-desc {
|
||||
margin-top: 10rpx;
|
||||
color: #888fa5;
|
||||
font-size: 19rpx;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flow-arrow {
|
||||
width: 28rpx;
|
||||
height: 4rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #c1c2ec;
|
||||
align-self: center;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.flow-arrow::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-top: 4rpx solid #c1c2ec;
|
||||
border-right: 4rpx solid #c1c2ec;
|
||||
transform: rotate(45deg) translate(8rpx, -9rpx);
|
||||
}
|
||||
|
||||
.sample-card {
|
||||
/* min-height: 124rpx; */
|
||||
border-radius: 18rpx;
|
||||
/* padding: 18rpx 28rpx 18rpx 24rpx; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* gap: 20rpx; */
|
||||
background: linear-gradient(100deg, #f0f4ff 0%, #fbfcff 100%);
|
||||
}
|
||||
|
||||
.gift-box {
|
||||
width: 88rpx;
|
||||
height: 86rpx;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
filter: drop-shadow(0 8rpx 14rpx rgba(112, 111, 255, 0.22));
|
||||
}
|
||||
|
||||
.gift-top {
|
||||
width: 72rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 7rpx 7rpx 3rpx 3rpx;
|
||||
background: linear-gradient(90deg, #dfe8ff, #7874ff, #dfe8ff);
|
||||
}
|
||||
|
||||
.gift-body {
|
||||
width: 62rpx;
|
||||
height: 54rpx;
|
||||
border-radius: 4rpx 4rpx 9rpx 9rpx;
|
||||
background: linear-gradient(90deg, #d7e3ff 0 35%, #8777ff 35% 52%, #c8d9ff 52% 100%);
|
||||
}
|
||||
|
||||
.sample-copy {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.sample-title {
|
||||
color: #141721;
|
||||
font-size: 26rpx;
|
||||
font-weight: 800;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.sample-desc {
|
||||
color: #7f859b;
|
||||
font-size: 20rpx;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sample-btn {
|
||||
width: 150rpx;
|
||||
height: 62rpx;
|
||||
border-radius: 999rpx;
|
||||
flex-shrink: 0;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.tabbar {
|
||||
height: 110rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-top: 1rpx solid rgba(219, 224, 241, 0.86);
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
width: 170rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #626777;
|
||||
font-size: 21rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #665cff;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 9rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22rpx;
|
||||
line-height: 1;
|
||||
color: currentColor;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-icon {
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #536dff, #7b55ff);
|
||||
}
|
||||
|
||||
.record-icon {
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 9rpx;
|
||||
}
|
||||
|
||||
.record-icon text {
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: block;
|
||||
border-top: 7rpx solid transparent;
|
||||
border-bottom: 7rpx solid transparent;
|
||||
border-left: 11rpx solid currentColor;
|
||||
margin-left: 3rpx;
|
||||
}
|
||||
|
||||
.mine-icon {
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.home-icon text {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
display: block;
|
||||
border-radius: 4rpx;
|
||||
background: currentColor;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// logs.ts
|
||||
// const util = require('../../utils/util.js')
|
||||
import { formatTime } from '../../utils/util'
|
||||
|
||||
Component({
|
||||
data: {
|
||||
logs: [],
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.setData({
|
||||
logs: (wx.getStorageSync('logs') || []).map((log: string) => {
|
||||
return {
|
||||
date: formatTime(new Date(log)),
|
||||
timeStamp: log
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
<!--logs.wxml-->
|
||||
<scroll-view class="scrollarea" scroll-y type="list">
|
||||
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
|
||||
<view class="log-item">{{index + 1}}. {{log.date}}</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
@@ -0,0 +1,16 @@
|
||||
page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.scrollarea {
|
||||
flex: 1;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.log-item {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.log-item:last-child {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav",
|
||||
"vip-popup": "/components/vip-popup/vip-popup",
|
||||
"checkin-popup": "/components/checkin-popup/checkin-popup"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { customEvent } from "../../utils/event"
|
||||
|
||||
Page({
|
||||
data: {
|
||||
showVipPopup: false,
|
||||
showCheckinPopup: false,
|
||||
menus: [
|
||||
{ key: 'feedback', title: '意见反馈', icon: '/static/images/my/my_icon_8.png' },
|
||||
{ key: 'privacy', title: '帮助中心', icon: '/static/images/my/my_icon_3.png' },
|
||||
{ key: 'privacy', title: '隐私协议', icon: '/static/images/my/my_icon_7.png' },
|
||||
],
|
||||
userinfo: {
|
||||
nickname: '创作小助手',
|
||||
id: '10010',
|
||||
avatar: 'https://cdn.zhuangb123.com/avatar/boy/a2cfe723-98ddc-12de-723b8f51b-71b1e3.jpeg',
|
||||
description: 'AI 创作,让想象力触手可及 ✨'
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.setData({
|
||||
userinfo: wx.getStorageSync('userInfo')
|
||||
})
|
||||
customEvent.on('update:userinfo', this.onResetUserinfo)
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
customEvent.off('update:userinfo', this.onResetUserinfo)
|
||||
},
|
||||
onResetUserinfo() {
|
||||
this.setData({ userinfo: wx.getStorageSync('userInfo') })
|
||||
},
|
||||
handleEdit() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/myPackage/edit/index',
|
||||
})
|
||||
},
|
||||
handleCheckin() {
|
||||
this.setData({ showCheckinPopup: true })
|
||||
},
|
||||
handleCheckinClose() {
|
||||
this.setData({ showCheckinPopup: false })
|
||||
},
|
||||
handleCheckinRule() {
|
||||
wx.showToast({ title: '每日签到可领取金币', icon: 'none' })
|
||||
},
|
||||
handleAddCoin() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/myPackage/golb/index',
|
||||
})
|
||||
},
|
||||
handleOpenVip() {
|
||||
this.setData({ showVipPopup: true })
|
||||
},
|
||||
handleVipClose() {
|
||||
this.setData({ showVipPopup: false })
|
||||
},
|
||||
handleVipConfirm(e: WechatMiniprogram.CustomEvent) {
|
||||
this.setData({ showVipPopup: false })
|
||||
const plan = e.detail.plan
|
||||
wx.showToast({ title: plan ? '已选择' + plan.name : '立即开通', icon: 'none' })
|
||||
},
|
||||
handleMenuTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const key = e.currentTarget.dataset.key
|
||||
const routeMap: Record<string, string> = {
|
||||
feedback: '/pages/myPackage/yjfk/index',
|
||||
privacy: '/pages/myPackage/ysxy/index',
|
||||
}
|
||||
const url = routeMap[String(key || '')]
|
||||
|
||||
if (url) {
|
||||
wx.navigateTo({ url })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<view class="profile-page">
|
||||
<custom-nav padding-x="38">
|
||||
<view class="profile-nav">
|
||||
<text class="nav-title">个人中心</text>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="profile-content">
|
||||
<view class="user-section">
|
||||
<view class="avatar">
|
||||
<image src="{{userinfo.avatar}}"></image>
|
||||
</view>
|
||||
<view class="user-info">
|
||||
<view class="name-row">
|
||||
<text class="user-name">{{userinfo.nickname}}</text>
|
||||
<text class="level-badge">普通用户</text>
|
||||
</view>
|
||||
<text class="user-id">ID:{{userinfo.id}}</text>
|
||||
<text class="user-desc">{{userinfo.description}}</text>
|
||||
</view>
|
||||
<view class="user-actions">
|
||||
<view class="outline-action" bindtap="handleEdit">
|
||||
<!-- <text class="edit-icon"></text> -->
|
||||
<image src="../../static/images/my/edit.png" style="width: 24rpx;height: 24rpx;"></image>
|
||||
<text>编辑资料</text>
|
||||
</view>
|
||||
<view class="outline-action checkin" bindtap="handleCheckin">
|
||||
<image src="../../static/images/my/Signin.png" style="width: 24rpx;height: 24rpx;"></image>
|
||||
<text>签到领金币</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="coin-card" bind:tap="handleAddCoin">
|
||||
<image src="/static/images/my/my_icon_1.png"
|
||||
style="width: 700rpx;height: 186rpx;position: absolute;left: 0;top: 0;"></image>
|
||||
<view class="coin-copy">
|
||||
<text>{{userinfo.diamond}}</text>
|
||||
<image src="/static/images/my/add.png" style="width: 40rpx;height: 40rpx;"></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="vip-card" bindtap="handleOpenVip">
|
||||
<image class="crown-icon icon-placeholder" src="/static/images/my/my_icon_2.png" mode="widthFix"></image>
|
||||
<!-- <view class="vip-left">
|
||||
<image class="crown-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text class="vip-title">会员中心</text>
|
||||
</view>
|
||||
<text class="vip-desc">解锁更多创作权益,生成更鲨金币</text>
|
||||
<view class="vip-btn" bindtap="handleOpenVip">开通会员</view> -->
|
||||
</view>
|
||||
|
||||
<view class="menu-card">
|
||||
<view wx:for="{{menus}}" wx:key="key" class="menu-item" bindtap="handleMenuTap" data-key="{{item.key}}">
|
||||
<image src="{{item.icon}}" style="width: 38rpx;height: 38rpx;"></image>
|
||||
<text class="menu-title">{{item.title}}</text>
|
||||
<text class="menu-arrow"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<vip-popup visible="{{showVipPopup}}" bind:close="handleVipClose" bind:confirm="handleVipConfirm"></vip-popup>
|
||||
<checkin-popup visible="{{showCheckinPopup}}" bind:close="handleCheckinClose" bind:rule="handleCheckinRule">
|
||||
</checkin-popup>
|
||||
</view>
|
||||
@@ -0,0 +1,462 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8f8ff;
|
||||
color: #111521;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.profile-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 80% 6%, rgba(129, 93, 255, 0.22), transparent 20%),
|
||||
radial-gradient(circle at 18% 9%, rgba(116, 118, 255, 0.16), transparent 24%),
|
||||
linear-gradient(180deg, #f1efff 0%, #fbfbff 36%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.profile-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 31rpx;
|
||||
font-weight: 800;
|
||||
color: #090c15;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
padding: 34rpx 27rpx 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.user-section {
|
||||
min-height: 136rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 26rpx;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 94rpx;
|
||||
height: 94rpx;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
/* background: linear-gradient(135deg, #f4c2d0, #b985ff); */
|
||||
box-shadow: 0 10rpx 18rpx rgba(136, 95, 186, 0.18);
|
||||
}
|
||||
.avatar image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 30rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
color: #111521;
|
||||
}
|
||||
|
||||
.level-badge {
|
||||
height: 30rpx;
|
||||
padding: 0 14rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #ffffff;
|
||||
font-size: 18rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #5c7cff, #7e39eb);
|
||||
}
|
||||
|
||||
.user-id,
|
||||
.user-desc {
|
||||
color: #72727c;
|
||||
font-size: 21rpx;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.user-actions {
|
||||
width: 176rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.outline-action {
|
||||
height: 52rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
color: #664cff;
|
||||
font-size: 21rpx;
|
||||
font-weight: 800;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
border: 2rpx solid #8b72ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.checkin {
|
||||
border-color: transparent;
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
box-shadow: 0 6rpx 14rpx rgba(122, 102, 255, 0.08);
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
display: block;
|
||||
border-left: 4rpx solid currentColor;
|
||||
border-bottom: 4rpx solid currentColor;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
width: 22rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border: 3rpx solid currentColor;
|
||||
border-radius: 5rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coin-card {
|
||||
min-height: 180rpx;
|
||||
margin-top: 26rpx;
|
||||
padding: 30rpx 38rpx;
|
||||
border-radius: 22rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(circle at 78% 50%, rgba(255, 210, 105, 0.18), transparent 26%),
|
||||
linear-gradient(100deg, #fffdf9 0%, #fff8eb 100%);
|
||||
border: 1rpx solid #f1d8a9;
|
||||
box-shadow: 0 8rpx 18rpx rgba(159, 117, 46, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coin-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
position: absolute;
|
||||
left: 100rpx;
|
||||
top: 80rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.coin-copy text:first-child{
|
||||
font-size: 50rpx;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.coin-copy image{
|
||||
margin-top: -4rpx;
|
||||
}
|
||||
|
||||
.coin-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #141925;
|
||||
}
|
||||
|
||||
.coin-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
}
|
||||
|
||||
.coin-symbol,
|
||||
.coin-add {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(135deg, #ffd46a, #ff9900);
|
||||
box-shadow: inset 0 0 0 3rpx rgba(255, 255, 255, 0.42), 0 6rpx 12rpx rgba(245, 154, 16, 0.2);
|
||||
}
|
||||
|
||||
.coin-symbol {
|
||||
font-size: 18rpx;
|
||||
}
|
||||
|
||||
.coin-count {
|
||||
font-size: 50rpx;
|
||||
line-height: 1;
|
||||
font-weight: 900;
|
||||
color: #111925;
|
||||
}
|
||||
|
||||
.coin-add {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.treasure-scene {
|
||||
width: 284rpx;
|
||||
height: 122rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.treasure-box {
|
||||
width: 116rpx;
|
||||
height: 92rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
filter: drop-shadow(0 8rpx 12rpx rgba(127, 76, 216, 0.22));
|
||||
}
|
||||
|
||||
.treasure-lid {
|
||||
width: 120rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 18rpx 18rpx 8rpx 8rpx;
|
||||
background: linear-gradient(90deg, #ce79ff 0 24%, #ffc05d 24% 38%, #8d57e8 38% 76%, #ffc05d 76% 100%);
|
||||
transform: skewX(8deg);
|
||||
}
|
||||
|
||||
.treasure-body {
|
||||
width: 104rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 8rpx 8rpx 16rpx 16rpx;
|
||||
background: linear-gradient(90deg, #7e55d9 0 28%, #ffb845 28% 44%, #9f62ef 44% 100%);
|
||||
}
|
||||
|
||||
.coin-stack {
|
||||
width: 74rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #ffd366, #f39b12);
|
||||
box-shadow: 10rpx -13rpx 0 -1rpx #ffc457, 24rpx 6rpx 0 -2rpx #f39b12;
|
||||
}
|
||||
|
||||
.left-stack {
|
||||
margin-right: -10rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.right-stack {
|
||||
margin-left: -8rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.spark {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
background: #ffc95d;
|
||||
border-radius: 4rpx;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.spark-one {
|
||||
margin-right: 18rpx;
|
||||
margin-bottom: 74rpx;
|
||||
}
|
||||
|
||||
.spark-two {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
margin-right: 18rpx;
|
||||
margin-bottom: 88rpx;
|
||||
}
|
||||
|
||||
.vip-card {
|
||||
/* height: 126rpx; */
|
||||
/* padding: 20rpx 16rpx 20rpx 24rpx; */
|
||||
/* border-radius: 16rpx; */
|
||||
/* display: flex;
|
||||
align-items: center; */
|
||||
/* gap: 22rpx; */
|
||||
/* background: linear-gradient(100deg, #fffdf8, #fff8ea); */
|
||||
/* border: 1rpx solid #f0d8aa; */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.vip-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.crown-icon {
|
||||
width: 100%;
|
||||
/* height: 100%; */
|
||||
}
|
||||
|
||||
.crown-icon text {
|
||||
flex: 1;
|
||||
height: 28rpx;
|
||||
border-radius: 3rpx 3rpx 7rpx 7rpx;
|
||||
background: linear-gradient(180deg, #ffd45d, #f8a50a);
|
||||
}
|
||||
|
||||
.crown-icon text:nth-child(2) {
|
||||
height: 38rpx;
|
||||
}
|
||||
|
||||
.vip-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 900;
|
||||
color: #151925;
|
||||
}
|
||||
|
||||
.vip-desc {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 20rpx;
|
||||
line-height: 1.2;
|
||||
color: #9a5a1f;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.vip-btn {
|
||||
width: 132rpx;
|
||||
height: 54rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #7b4b12;
|
||||
font-size: 23rpx;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(135deg, #fff0bd, #ffd886);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.menu-card {
|
||||
margin-top: 8rpx;
|
||||
padding: 20rpx 28rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: 0 8rpx 22rpx rgba(76, 84, 135, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
min-height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 22rpx;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.feedback-icon {
|
||||
background: linear-gradient(135deg, #ed8aff, #9d5cff);
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
background: linear-gradient(135deg, #7fb8ff, #4e7dff);
|
||||
}
|
||||
|
||||
.privacy-icon {
|
||||
background: linear-gradient(135deg, #31dec2, #15bd96);
|
||||
}
|
||||
|
||||
.feedback-icon text {
|
||||
width: 24rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 6rpx;
|
||||
display: block;
|
||||
background: currentColor;
|
||||
color: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: inset 7rpx 0 0 rgba(255, 255, 255, 0.2), inset 14rpx 0 0 rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
.help-icon text {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
border: 5rpx solid rgba(255, 255, 255, 0.92);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.privacy-icon text {
|
||||
width: 22rpx;
|
||||
height: 26rpx;
|
||||
border-radius: 5rpx 5rpx 10rpx 10rpx;
|
||||
display: block;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
flex: 1;
|
||||
font-size: 25rpx;
|
||||
font-weight: 700;
|
||||
color: #151925;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
border-top: 4rpx solid #bdc1ca;
|
||||
border-right: 4rpx solid #bdc1ca;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// pages/myPackage/bzzx/index.ts
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,2 @@
|
||||
<!--pages/myPackage/bzzx/index.wxml-->
|
||||
<text>pages/myPackage/bzzx/index.wxml</text>
|
||||
@@ -0,0 +1 @@
|
||||
/* pages/myPackage/bzzx/index.wxss */
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { client } from "../../../utils/api";
|
||||
import { updateuserinfo, userInfo } from "../../../utils/request";
|
||||
|
||||
Page({
|
||||
data: {
|
||||
userinfo: {
|
||||
nickname: '创作小助手',
|
||||
id: '10010',
|
||||
avatar: 'https://cdn.zhuangb123.com/avatar/boy/a2cfe723-98ddc-12de-723b8f51b-71b1e3.jpeg',
|
||||
description: 'AI 创作,让想象力触手可及 ✨'
|
||||
},
|
||||
oldAvatar: '',
|
||||
newAvatar: ''
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({ userinfo: wx.getStorageSync('userInfo') });
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/my/my' }),
|
||||
})
|
||||
},
|
||||
handleChangeAvatar() {
|
||||
let that = this
|
||||
wx.chooseImage({
|
||||
count: 1,
|
||||
success(res) {
|
||||
let userInfo = that.data.userinfo;
|
||||
let oldAvatar = userInfo.avatar;
|
||||
userInfo.avatar = res.tempFilePaths[0];
|
||||
|
||||
that.setData({
|
||||
userinfo: userInfo,
|
||||
oldAvatar: oldAvatar
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
handleNicknameInput(e: any) {
|
||||
let userinfo = this.data.userinfo;
|
||||
userinfo.nickname = e.detail.value;
|
||||
this.setData({
|
||||
userinfo: userinfo,
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
let nickname = this.data.userinfo;
|
||||
if (nickname.nickname.length < 2) {
|
||||
wx.showToast({ title: '昵称至少2个字符', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
let that = this;
|
||||
let update = () => {
|
||||
updateuserinfo(nickname.nickname, nickname.avatar).then((res: any) => {
|
||||
if (!res.code) {
|
||||
userInfo().then((res: any) => {
|
||||
wx.setStorageSync('userInfo', res.data);
|
||||
|
||||
that.setData({ userinfo: res.data });
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.data.userinfo.avatar.indexOf('http://tmp/') === -1) {
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
client.upload(this.data.userinfo.avatar, {}).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
nickname.avatar = res.data.url;
|
||||
update();
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: '头像上传失败' })
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
<view class="edit-page">
|
||||
<custom-nav padding-x="42">
|
||||
<view class="edit-nav">
|
||||
<view class="nav-back" bindtap="handleBack">
|
||||
<text></text>
|
||||
</view>
|
||||
<text class="nav-title">编辑资料</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="edit-content">
|
||||
<view class="edit-card">
|
||||
<view class="section-title">
|
||||
<text class="section-mark"></text>
|
||||
<text>头像</text>
|
||||
</view>
|
||||
|
||||
<view class="avatar-row">
|
||||
<view class="avatar-wrap">
|
||||
<view class="avatar-large">
|
||||
<image src="{{userinfo.avatar}}"></image>
|
||||
</view>
|
||||
<view class="camera-badge">
|
||||
<image class="camera-icon icon-placeholder" src="/static/images/my/caram.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="change-avatar" bindtap="handleChangeAvatar">
|
||||
<image class="image-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>更换头像</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="section-title nickname-title">
|
||||
<text class="section-mark"></text>
|
||||
<text>昵称</text>
|
||||
</view>
|
||||
|
||||
<view class="input-shell">
|
||||
<input class="nickname-input" value="{{userinfo.nickname}}" maxlength="12" placeholder="请输入昵称" bindinput="handleNicknameInput" />
|
||||
<image class="edit-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<text class="input-tip">2–12个字符</text>
|
||||
|
||||
<view class="card-spacer"></view>
|
||||
|
||||
<view class="sync-tip">
|
||||
<image class="shield-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>修改后将同步更新个人中心信息</text>
|
||||
</view>
|
||||
|
||||
<view class="save-btn" bindtap="handleSave">保存修改</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #f8f6ff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.edit-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 82% 4%, rgba(137, 95, 255, 0.18), transparent 20%),
|
||||
radial-gradient(circle at 16% 10%, rgba(118, 129, 255, 0.14), transparent 24%),
|
||||
linear-gradient(180deg, #f4f1ff 0%, #fbfaff 42%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.edit-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-placeholder {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 32rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
color: #101522;
|
||||
}
|
||||
|
||||
.edit-content {
|
||||
flex: 1;
|
||||
padding: 50rpx 32rpx 78rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.edit-card {
|
||||
width: 100%;
|
||||
min-height: 1074rpx;
|
||||
padding: 54rpx 40rpx 50rpx;
|
||||
border-radius: 34rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-shadow: 0 16rpx 42rpx rgba(91, 84, 142, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
color: #111827;
|
||||
font-size: 30rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.section-mark {
|
||||
width: 7rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 999rpx;
|
||||
background: linear-gradient(180deg, #aa6dff, #6f67ff);
|
||||
}
|
||||
|
||||
.avatar-row {
|
||||
margin-top: 32rpx;
|
||||
padding: 0 44rpx 0 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.avatar-wrap {
|
||||
width: 246rpx;
|
||||
height: 246rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar-large {
|
||||
width: 222rpx;
|
||||
height: 222rpx;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #f3e0d7, #fff7f4);
|
||||
/* border: 4rpx solid #e6dcff; */
|
||||
box-shadow: inset 0 0 0 5rpx #ffffff;
|
||||
}
|
||||
|
||||
.avatar-large>image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.camera-badge {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* background: linear-gradient(135deg, #9a6cff, #7656ef); */
|
||||
background: #ffffff;
|
||||
box-shadow: 0 8rpx 18rpx rgba(115, 83, 238, 0.24), 0 0 0 8rpx #ffffff;
|
||||
margin-left: -70rpx;
|
||||
margin-top: 142rpx;
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
display: block;
|
||||
border-radius: 6rpx;
|
||||
/* border: 4rpx solid #ffffff; */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* .camera-icon::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
margin: 2rpx auto 0;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
} */
|
||||
|
||||
.change-avatar {
|
||||
width: 220rpx;
|
||||
height: 58rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14rpx;
|
||||
color: #7d5cff;
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
border: 2rpx solid #8d6cff;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.image-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
display: block;
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 3rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.image-icon::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 9rpx;
|
||||
height: 9rpx;
|
||||
margin: 5rpx 0 0 6rpx;
|
||||
border-left: 4rpx solid currentColor;
|
||||
border-top: 4rpx solid currentColor;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1rpx;
|
||||
margin: 42rpx 0 54rpx;
|
||||
background: #e5e7ef;
|
||||
}
|
||||
|
||||
.nickname-title {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.input-shell {
|
||||
height: 86rpx;
|
||||
padding: 0 30rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
border: 2rpx solid #ddd7ff;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 82rpx;
|
||||
color: #111827;
|
||||
font-size: 27rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #9a79ff;
|
||||
border-bottom: 5rpx solid #9a79ff;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-tip {
|
||||
margin-top: 18rpx;
|
||||
color: #8b90a2;
|
||||
font-size: 20rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.card-spacer {
|
||||
flex: 1;
|
||||
min-height: 210rpx;
|
||||
}
|
||||
|
||||
.sync-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14rpx;
|
||||
color: #9095a5;
|
||||
font-size: 20rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.shield-icon {
|
||||
width: 24rpx;
|
||||
height: 26rpx;
|
||||
border-radius: 6rpx 6rpx 12rpx 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #a56dff, #715eff);
|
||||
}
|
||||
|
||||
.shield-icon::after {
|
||||
content: "";
|
||||
width: 9rpx;
|
||||
height: 5rpx;
|
||||
display: block;
|
||||
border-left: 3rpx solid #ffffff;
|
||||
border-bottom: 3rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
height: 86rpx;
|
||||
margin-top: 28rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(135deg, #b26bff 0%, #7549f5 100%);
|
||||
box-shadow: 0 14rpx 26rpx rgba(117, 73, 245, 0.2);
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { diamonds, diamondVirtualPayment, updatesessionkey, updateuserinfo, userInfo } from '../../../utils/request';
|
||||
|
||||
interface CoinPackage {
|
||||
id: number
|
||||
coins: number
|
||||
price: number
|
||||
ribbon?: string
|
||||
ribbonClass?: string
|
||||
artClass: string
|
||||
chest?: boolean
|
||||
selected: boolean
|
||||
}
|
||||
Page({
|
||||
data: {
|
||||
packages: [],
|
||||
selectedPackage: null as CoinPackage | null,
|
||||
userInfo: { diamond: 0 }
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({ userInfo: wx.getStorageSync('userInfo') })
|
||||
diamonds().then((res: any) => {
|
||||
if (!res.code) {
|
||||
this.setData({ packages: res.data });
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/my/my' }),
|
||||
})
|
||||
},
|
||||
handlePackageTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
const selectedPackage = this.data.packages.find((item: CoinPackage) => item.id === id) || this.data.selectedPackage
|
||||
|
||||
this.setData({
|
||||
selectedPackage,
|
||||
})
|
||||
},
|
||||
handleBuy() {
|
||||
const that = this;
|
||||
if (that.data.selectedPackage == null) {
|
||||
return;
|
||||
}
|
||||
wx.showLoading({ title: '处理中, 请稍后.', mask: true });
|
||||
wx.checkSession({
|
||||
success() {
|
||||
that.payment();
|
||||
},
|
||||
fail() {
|
||||
wx.login({
|
||||
success(login) {
|
||||
updatesessionkey(login.code).then((res: any) => {
|
||||
if (!res.code) {
|
||||
that.payment();
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: res.message,
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
wx.hideLoading();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
payment() {
|
||||
let that = this;
|
||||
diamondVirtualPayment((that.data.selectedPackage || { id: 0 }).id).then((res: any) => {
|
||||
wx.requestVirtualPayment({
|
||||
signData: JSON.stringify(res.param.signData),
|
||||
paySig: res.param.paySig,
|
||||
signature: res.param.signature,
|
||||
mode: res.param.mode,
|
||||
success(result: any) {
|
||||
wx.hideLoading();
|
||||
console.log(result)
|
||||
|
||||
userInfo().then((res: any) => {
|
||||
if (!res.code) {
|
||||
wx.setStorageSync('userInfo', res.data);
|
||||
that.setData({ userInfo: res.data });
|
||||
}
|
||||
})
|
||||
},
|
||||
fail(error: any) {
|
||||
wx.hideLoading();
|
||||
console.log(error);
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '支付失败',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
wx.hideLoading();
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '系统繁忙, 请稍后再试',
|
||||
showCancel: false
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,71 @@
|
||||
<view class="coin-page">
|
||||
<custom-nav padding-x="42">
|
||||
<view class="coin-nav">
|
||||
<view class="nav-back" bindtap="handleBack"><text></text></view>
|
||||
<text class="nav-title">购买金币</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="coin-content">
|
||||
<view class="balance-card">
|
||||
<image class="balance-art icon-placeholder" src="/static/images/icons/frame_1.png" mode="widthFix"></image>
|
||||
<view class="balance-copy">{{userInfo.diamond}}</view>
|
||||
</view>
|
||||
|
||||
<view class="section-head">
|
||||
<text class="section-title">金币套餐</text>
|
||||
<view class="section-note">
|
||||
<image class="info-icon icon-placeholder" src="/static/images/info-circle.png" mode="aspectFit"></image>
|
||||
<text>套餐数量与价格以实际配置为准</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="package-grid">
|
||||
<view
|
||||
wx:for="{{packages}}"
|
||||
wx:key="id"
|
||||
class="package-card {{selectedPackage.id == item.id ? 'selected' : ''}}"
|
||||
data-id="{{item.id}}"
|
||||
bindtap="handlePackageTap"
|
||||
>
|
||||
<view wx:if="{{item.ribbon}}" class="ribbon {{item.ribbonClass}}">{{item.ribbon}}</view>
|
||||
<text class="package-name">{{item.coins}} 金币</text>
|
||||
<image class="package-art {{item.artClass}} icon-placeholder" src="{{item.icon}}" mode="widthFix"></image>
|
||||
<view class="package-price">
|
||||
<text>¥</text>
|
||||
<text>{{item.price}}</text>
|
||||
</view>
|
||||
<view wx:if="{{item.selected}}" class="selected-check"><text></text></view>
|
||||
|
||||
<view wx:if="{{item.tag == 'best_seller'}}" class="right-jiao best_seller">热卖</view>
|
||||
<view wx:if="{{item.tag == 'hot'}}" class="right-jiao">爆款</view>
|
||||
<view wx:if="{{item.tag == 'recommend'}}" class="right-jiao recommend">推荐</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tips-card">
|
||||
<view class="tip-row">
|
||||
<image class="tip-icon flash-tip icon-placeholder" src="/static/images/icons/frame_7.png" mode="aspectFit"></image>
|
||||
<text>充值后金币实时到账</text>
|
||||
</view>
|
||||
<view class="tip-row">
|
||||
<image class="tip-icon shield-tip icon-placeholder" src="/static/images/icons/frame_.png" mode="aspectFit"></image>
|
||||
<text>金币仅用于平台内数字人视频相关功能</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="selected-bar">
|
||||
<view class="selected-left">
|
||||
<image class="selected-icon icon-placeholder" src="/static/images/icons/check-circle-filled.png" mode="aspectFit"></image>
|
||||
<text>已选:</text>
|
||||
<text class="selected-coins">{{selectedPackage.coin || 0}}</text>
|
||||
<text>金币</text>
|
||||
</view>
|
||||
<text class="selected-price">¥{{selectedPackage.price || 0.00}}</text>
|
||||
</view>
|
||||
|
||||
<view class="buy-btn" bindtap="handleBuy">立即购买</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #fbfaff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.coin-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 80% 5%, rgba(138, 103, 255, 0.16), transparent 20%),
|
||||
radial-gradient(circle at 18% 8%, rgba(115, 129, 255, 0.12), transparent 24%),
|
||||
linear-gradient(180deg, #f9f6ff 0%, #fbfbff 42%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.coin-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back,
|
||||
.nav-placeholder {
|
||||
width: 58rpx;
|
||||
height: 58rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 31rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.coin-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
position: relative;
|
||||
/* height: 198rpx; */
|
||||
/* padding: 36rpx 38rpx; */
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* overflow: hidden; */
|
||||
/* background:
|
||||
radial-gradient(circle at 82% 46%, rgba(126, 83, 255, 0.22), transparent 30%),
|
||||
linear-gradient(100deg, #ffffff 0%, #eee8ff 100%); */
|
||||
/* border: 1rpx solid #ded6ff; */
|
||||
box-shadow: 0 10rpx 22rpx rgba(103, 86, 176, 0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.balance-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
z-index: 2026;
|
||||
font-weight: bold;
|
||||
font-size: 72rpx;
|
||||
left: 110rpx;
|
||||
bottom: 45rpx;
|
||||
}
|
||||
|
||||
.balance-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.balance-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
}
|
||||
|
||||
.coin-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 20rpx;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(135deg, #ffd56b, #ff9900);
|
||||
box-shadow: inset 0 0 0 4rpx rgba(255, 255, 255, 0.38), 0 7rpx 13rpx rgba(248, 154, 12, 0.2);
|
||||
}
|
||||
|
||||
.balance-count {
|
||||
font-size: 68rpx;
|
||||
line-height: 1;
|
||||
font-weight: 900;
|
||||
color: #0e1118;
|
||||
}
|
||||
|
||||
.balance-art {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
/* position: absolute; */
|
||||
/* left: 0;
|
||||
top: 0; */
|
||||
}
|
||||
|
||||
.open-box {
|
||||
width: 142rpx;
|
||||
height: 104rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.box-lid {
|
||||
width: 142rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 24rpx 24rpx 8rpx 8rpx;
|
||||
background: linear-gradient(135deg, rgba(196, 163, 255, 0.55), rgba(138, 89, 255, 0.28));
|
||||
transform: rotate(6deg) translateY(12rpx);
|
||||
}
|
||||
|
||||
.box-body {
|
||||
width: 126rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 12rpx 12rpx 28rpx 28rpx;
|
||||
background: linear-gradient(135deg, rgba(126, 83, 255, 0.28), rgba(196, 163, 255, 0.5));
|
||||
box-shadow: 0 8rpx 18rpx rgba(126, 83, 255, 0.18);
|
||||
}
|
||||
|
||||
.big-coin {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
margin-top: -108rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #ffe28b, #ffac19);
|
||||
box-shadow: inset 0 0 0 8rpx rgba(255, 255, 255, 0.34), 0 10rpx 18rpx rgba(255, 172, 25, 0.24);
|
||||
}
|
||||
|
||||
.big-coin text {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 8rpx;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.art-spark {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 5rpx;
|
||||
background: #ffffff;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.spark-one {
|
||||
margin-right: -12rpx;
|
||||
margin-bottom: 98rpx;
|
||||
}
|
||||
|
||||
.spark-two {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
margin-left: -4rpx;
|
||||
margin-bottom: 46rpx;
|
||||
background: #8d73ff;
|
||||
}
|
||||
|
||||
.section-head {
|
||||
margin-top: 34rpx;
|
||||
margin-bottom: 22rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 27rpx;
|
||||
font-weight: 900;
|
||||
color: #121722;
|
||||
}
|
||||
|
||||
.section-note {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #85899a;
|
||||
font-size: 20rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2rpx solid currentColor;
|
||||
font-size: 14rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.package-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 22rpx 18rpx;
|
||||
}
|
||||
|
||||
.package-card {
|
||||
position: relative;
|
||||
height: 230rpx;
|
||||
border-radius: 22rpx;
|
||||
padding: 28rpx 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0 8rpx 20rpx rgba(82, 90, 146, 0.08);
|
||||
border-width: 2rpx;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.package-card.selected {
|
||||
border-color: #7351ff;
|
||||
background-color: rgba(196, 163, 255, 0.1);
|
||||
}
|
||||
|
||||
.ribbon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 74rpx;
|
||||
height: 42rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 18rpx;
|
||||
font-weight: 800;
|
||||
transform: rotate(-45deg) translate(-22rpx, -10rpx);
|
||||
}
|
||||
|
||||
.red-ribbon {
|
||||
background: #ff5b78;
|
||||
}
|
||||
|
||||
.purple-ribbon {
|
||||
background: #7452ff;
|
||||
}
|
||||
|
||||
.gold-ribbon {
|
||||
background: #ffb629;
|
||||
}
|
||||
|
||||
.package-name {
|
||||
color: #111827;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.1;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.package-art {
|
||||
width: 82rpx;
|
||||
margin-top: 18rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.coin-pile {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.coin-pile text {
|
||||
width: 54rpx;
|
||||
height: 22rpx;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
background: linear-gradient(180deg, #ffe28b, #f8a113);
|
||||
box-shadow: inset 0 0 0 4rpx rgba(255, 255, 255, 0.36), 0 8rpx 0 -2rpx #e98a0d;
|
||||
}
|
||||
|
||||
.coin-pile text:nth-child(1) {
|
||||
margin-right: -26rpx;
|
||||
}
|
||||
|
||||
.coin-pile text:nth-child(2) {
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
.coin-pile text:nth-child(3) {
|
||||
margin-left: -26rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.large-pile .coin-pile text {
|
||||
width: 66rpx;
|
||||
height: 26rpx;
|
||||
}
|
||||
|
||||
.mini-chest {
|
||||
width: 74rpx;
|
||||
height: 54rpx;
|
||||
margin-left: -18rpx;
|
||||
border-radius: 8rpx 8rpx 14rpx 14rpx;
|
||||
background: linear-gradient(90deg, #7b56d9 0 28%, #ffbd47 28% 46%, #a166f0 46% 100%);
|
||||
box-shadow: 0 8rpx 12rpx rgba(113, 83, 226, 0.18);
|
||||
}
|
||||
|
||||
.package-price {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4rpx;
|
||||
color: #6d4cff;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.package-price text:first-child {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.package-price text:last-child {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.right-jiao {
|
||||
position: absolute;
|
||||
left: -90rpx;
|
||||
top: -9rpx;
|
||||
width: 100%;
|
||||
height: 50rpx;
|
||||
line-height: 70rpx;
|
||||
background-color: #6d4cff;
|
||||
z-index: 9999;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
font-size: 18rpx;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.right-jiao.best_seller {
|
||||
background-color: orange;
|
||||
}
|
||||
.right-jiao.recommend{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.selected-check {
|
||||
position: absolute;
|
||||
right: 12rpx;
|
||||
bottom: 12rpx;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #6f4cff;
|
||||
}
|
||||
|
||||
.selected-check text {
|
||||
width: 16rpx;
|
||||
height: 9rpx;
|
||||
border-left: 4rpx solid #ffffff;
|
||||
border-bottom: 4rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.tips-card {
|
||||
margin-top: 26rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
background: #f5f3ff;
|
||||
color: #73788a;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.tip-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
background: #6f4cff;
|
||||
}
|
||||
|
||||
.shield-tip {
|
||||
border-radius: 6rpx 6rpx 12rpx 12rpx;
|
||||
}
|
||||
|
||||
.selected-bar {
|
||||
height: 62rpx;
|
||||
margin-top: 14rpx;
|
||||
padding: 0 30rpx 0 24rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #ffffff;
|
||||
border: 1rpx solid #e4e2f2;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.selected-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
color: #171b26;
|
||||
font-size: 23rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.selected-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #6f4cff;
|
||||
}
|
||||
|
||||
.selected-icon text {
|
||||
width: 14rpx;
|
||||
height: 8rpx;
|
||||
border-left: 4rpx solid #ffffff;
|
||||
border-bottom: 4rpx solid #ffffff;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.selected-coins,
|
||||
.selected-price {
|
||||
color: #6f4cff;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.selected-price {
|
||||
font-size: 29rpx;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
height: 68rpx;
|
||||
margin-top: 12rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 29rpx;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #4c88ff 0%, #7b3df2 100%);
|
||||
box-shadow: 0 10rpx 18rpx rgba(91, 83, 244, 0.2);
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// pages/myPackage/vip/index.ts
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,2 @@
|
||||
<!--pages/myPackage/vip/index.wxml-->
|
||||
<text>pages/myPackage/vip/index.wxml</text>
|
||||
@@ -0,0 +1 @@
|
||||
/* pages/myPackage/vip/index.wxss */
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"custom-nav": "/components/custom-nav/custom-nav"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import { client } from "../../../utils/api"
|
||||
import { feedback, uploadavatar } from "../../../utils/request"
|
||||
|
||||
interface FeedbackType {
|
||||
key: number
|
||||
label: string
|
||||
icon: string
|
||||
active: boolean
|
||||
}
|
||||
|
||||
interface submits {
|
||||
categoryes: number[],
|
||||
content: string,
|
||||
images: string[],
|
||||
phone: string
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
description: '',
|
||||
contact: '',
|
||||
types: [
|
||||
{ key: 1, label: '功能问题', icon: '/static/images/my/debug.png', active: true },
|
||||
{ key: 2, label: '体验优化', active: false, icon: '/static/images/my/star.png' },
|
||||
{ key: 3, label: '内容建议', active: false, icon: '/static/images/my/msg.png' },
|
||||
{ key: 4, label: '其他问题', active: false, icon: '/static/images/my/more.png' },
|
||||
] as FeedbackType[],
|
||||
datas: {} as submits
|
||||
},
|
||||
onLoad() {
|
||||
this.setData({ datas: { categoryes: [], content: '', images: [], phone: '' } })
|
||||
},
|
||||
handleBack() {
|
||||
wx.navigateBack({
|
||||
fail: () => wx.switchTab({ url: '/pages/my/my' }),
|
||||
})
|
||||
},
|
||||
handleRecord() {
|
||||
wx.showToast({ title: '反馈记录', icon: 'none' })
|
||||
},
|
||||
handleTypeTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const key = e.currentTarget.dataset.key
|
||||
|
||||
this.setData({
|
||||
types: this.data.types.map((item) => ({
|
||||
...item,
|
||||
active: item.key === key ? !item.active : item.active,
|
||||
})),
|
||||
})
|
||||
},
|
||||
handleDescriptionInput(e: any) {
|
||||
this.setData({ description: e.detail.value })
|
||||
},
|
||||
handleContactInput(e: any) {
|
||||
this.setData({ contact: e.detail.value })
|
||||
},
|
||||
handleUpload() {
|
||||
let that = this;
|
||||
wx.showLoading({ mask: true, title: '请稍后...' })
|
||||
wx.chooseMedia({
|
||||
count: 3 - this.data.datas.images.length,
|
||||
mediaType: ['image', 'video'],
|
||||
sourceType: ['album', 'camera'],
|
||||
maxDuration: 30,
|
||||
camera: 'back',
|
||||
success(res) {
|
||||
client.upload(res.tempFiles[0].tempFilePath, {}).then((res: any) => {
|
||||
wx.hideLoading();
|
||||
if (res.code == 0) {
|
||||
let images = that.data.datas;
|
||||
images.images.push(res.data.url);
|
||||
that.setData({ datas: images })
|
||||
}
|
||||
})
|
||||
},
|
||||
fail(err) {
|
||||
wx.hideLoading();
|
||||
console.log(err);
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
let that = this;
|
||||
if (!this.data.description.trim()) {
|
||||
wx.showToast({ title: '请填写问题描述', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
let datas = this.data.datas;
|
||||
let types: FeedbackType[] = [];
|
||||
for (let q = 0; q < this.data.types.length; q++) {
|
||||
let item = that.data.types[q];
|
||||
if (item.active) {
|
||||
datas.categoryes.push(item.key)
|
||||
}
|
||||
item.active = false;
|
||||
types.push(item);
|
||||
}
|
||||
|
||||
datas.content = this.data.description;
|
||||
datas.phone = this.data.contact;
|
||||
|
||||
feedback(JSON.stringify(datas)).then((res: any) => {
|
||||
if (!res.code) {
|
||||
this.setData({ datas: { categoryes: [], content: '', images: [], phone: '' }, contact: '', description: '', types: types })
|
||||
|
||||
wx.showModal({ title: '温馨提示', content: '提交成功', showCancel: false });
|
||||
} else {
|
||||
wx.showModal({ title: '温馨提示', content: '提交失败, 请稍后重试', showCancel: false });
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,86 @@
|
||||
<view class="feedback-page">
|
||||
<custom-nav padding-x="42">
|
||||
<view class="feedback-nav">
|
||||
<view class="nav-back" bindtap="handleBack">
|
||||
<text></text>
|
||||
</view>
|
||||
<text class="nav-title">意见反馈</text>
|
||||
<view class="record-link" bindtap="handleRecord"></view>
|
||||
</view>
|
||||
</custom-nav>
|
||||
|
||||
<view class="feedback-content">
|
||||
<view class="hero-row">
|
||||
<image class="hero-illustration" src="/static/images/my/yjfk_top.png" mode="widthFix"></image>
|
||||
<!-- <view class="hero-copy">
|
||||
<view class="hero-title">
|
||||
<text>你的意见对我们很</text>
|
||||
<text class="accent">重要</text>
|
||||
</view>
|
||||
<text class="hero-desc">欢迎提出宝贵的建议</text>
|
||||
<text class="hero-desc">帮助我们做得更好</text>
|
||||
<view class="hero-line"></view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<view class="form-card type-card">
|
||||
<view class="card-title">
|
||||
<image class="title-icon type-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit"></image>
|
||||
<text>反馈类型</text>
|
||||
<text class="optional">(可多选)</text>
|
||||
</view>
|
||||
<view class="type-grid">
|
||||
<view wx:for="{{types}}" wx:key="key" class="type-chip {{item.active ? 'active' : 'gray'}}"
|
||||
data-key="{{item.key}}" bindtap="handleTypeTap">
|
||||
<image class="type-chip-icon icon-placeholder" src="{{item.icon}}" mode="aspectFit"></image>
|
||||
<text>{{item.label}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-card desc-card">
|
||||
<view class="card-title">
|
||||
<image class="title-icon pen-icon icon-placeholder" src="/static/images/my/edit.png" mode="aspectFit"></image>
|
||||
<text>问题描述</text>
|
||||
</view>
|
||||
<view class="textarea-shell">
|
||||
<textarea class="desc-input" value="{{description}}" maxlength="500" placeholder="请详细描述您遇到的问题或建议…"
|
||||
placeholder-class="placeholder" bindinput="handleDescriptionInput"></textarea>
|
||||
<text class="counter">{{description.length}}/500</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-card image-card">
|
||||
<view class="card-title">
|
||||
<image class="title-icon image-title-icon icon-placeholder" src="/static/images/my/image.png" mode="aspectFit">
|
||||
</image>
|
||||
<text>添加图片</text>
|
||||
<text class="optional">(选填)</text>
|
||||
</view>
|
||||
<view style="display: flex;flex-direction: row;gap: 20;">
|
||||
<view class="upload-box image-full" wx:for="{{datas.images}}" wx:key="index" bindtap="handleUpload">
|
||||
<image class="plus-icon icon-placeholder" src="{{item}}"></image>
|
||||
</view>
|
||||
<view class="upload-box" wx:if="{{datas.images.length < 3}}" bindtap="handleUpload">
|
||||
<image class="plus-icon icon-placeholder" src="/static/images/my/Addimages.png"
|
||||
style="width: 26rpx;height: 26rpx;"></image>
|
||||
<text>上传图片</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="upload-tip">最多可上传 3 张图片</text>
|
||||
</view>
|
||||
|
||||
<view class="form-card contact-card">
|
||||
<view class="card-title">
|
||||
<image class="title-icon phone-icon icon-placeholder" src="/static/images/my/call.png" mode="aspectFit"></image>
|
||||
<text>联系方式</text>
|
||||
<text class="optional">(选填)</text>
|
||||
</view>
|
||||
<input class="contact-input" value="{{contact}}" placeholder="请输入手机号或微信号,方便我们与您联系" placeholder-class="placeholder"
|
||||
bindinput="handleContactInput" />
|
||||
</view>
|
||||
|
||||
<view class="submit-btn" bindtap="handleSubmit">提交反馈</view>
|
||||
<view class="thanks-text">感谢您的反馈,我们会认真对待每一条建议 💜</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,441 @@
|
||||
page {
|
||||
min-height: 100vh;
|
||||
background: #fbfaff;
|
||||
color: #111827;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.feedback-page {
|
||||
width: 750rpx;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 78% 4%, rgba(137, 95, 255, 0.16), transparent 20%),
|
||||
radial-gradient(circle at 18% 8%, rgba(118, 129, 255, 0.12), transparent 24%),
|
||||
linear-gradient(180deg, #f7f3ff 0%, #fbfaff 48%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.feedback-nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-back text {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
display: block;
|
||||
border-left: 5rpx solid #111827;
|
||||
border-bottom: 5rpx solid #111827;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 31rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.record-link {
|
||||
width: 142rpx;
|
||||
height: 56rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: #111827;
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.feedback-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14rpx;
|
||||
padding: 26rpx 38rpx 38rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hero-row {
|
||||
/* min-height: 184rpx; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.hero-illustration {
|
||||
/* width: 250rpx;
|
||||
height: 174rpx; */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.paper {
|
||||
width: 116rpx;
|
||||
height: 126rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14rpx;
|
||||
padding: 30rpx 20rpx 0 34rpx;
|
||||
background: linear-gradient(145deg, #ffffff, #ece5ff);
|
||||
box-shadow: 0 14rpx 24rpx rgba(120, 92, 219, 0.2);
|
||||
transform: rotate(-7deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.paper text {
|
||||
height: 8rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #cfc2ff;
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
width: 114rpx;
|
||||
height: 82rpx;
|
||||
margin-left: -168rpx;
|
||||
margin-top: 44rpx;
|
||||
border-radius: 42rpx 42rpx 42rpx 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
background: linear-gradient(135deg, #9d79ff, #6d4cef);
|
||||
box-shadow: 0 16rpx 24rpx rgba(108, 76, 239, 0.25);
|
||||
}
|
||||
|
||||
.chat-bubble text {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
}
|
||||
|
||||
.pencil {
|
||||
width: 76rpx;
|
||||
height: 22rpx;
|
||||
margin-left: 92rpx;
|
||||
margin-top: -18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: linear-gradient(90deg, #7654f7 0 20%, #ffd05e 20% 78%, #ff6b91 78% 100%);
|
||||
transform: rotate(-42deg);
|
||||
}
|
||||
|
||||
.heart {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
margin-right: -40rpx;
|
||||
margin-top: -88rpx;
|
||||
border-radius: 50% 50% 8rpx 50%;
|
||||
background: linear-gradient(135deg, #ff9ec2, #ff679a);
|
||||
transform: rotate(45deg);
|
||||
box-shadow: 0 8rpx 14rpx rgba(255, 105, 154, 0.22);
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.25;
|
||||
font-weight: 900;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.accent {
|
||||
color: #744dff;
|
||||
}
|
||||
|
||||
.hero-desc {
|
||||
margin-top: 14rpx;
|
||||
color: #6c7280;
|
||||
font-size: 23rpx;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.hero-line {
|
||||
width: 72rpx;
|
||||
height: 30rpx;
|
||||
margin-top: 8rpx;
|
||||
border-bottom: 5rpx solid #7c57ff;
|
||||
border-radius: 50%;
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
|
||||
.form-card {
|
||||
border-radius: 18rpx;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-shadow: 0 8rpx 24rpx rgba(84, 91, 148, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
color: #111827;
|
||||
font-size: 25rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.optional {
|
||||
color: #8b91a1;
|
||||
font-size: 18rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.title-icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #7454ff;
|
||||
background: #f3efff;
|
||||
}
|
||||
|
||||
.title-icon text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.type-icon text {
|
||||
width: 17rpx;
|
||||
height: 19rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 5rpx 5rpx 9rpx 9rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pen-icon text {
|
||||
width: 19rpx;
|
||||
height: 19rpx;
|
||||
border-left: 5rpx solid currentColor;
|
||||
border-bottom: 5rpx solid currentColor;
|
||||
transform: rotate(-45deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.image-title-icon text {
|
||||
width: 18rpx;
|
||||
height: 16rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 3rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.phone-icon text {
|
||||
width: 18rpx;
|
||||
height: 22rpx;
|
||||
border-left: 5rpx solid currentColor;
|
||||
border-bottom: 5rpx solid currentColor;
|
||||
border-radius: 0 0 0 10rpx;
|
||||
transform: rotate(-25deg);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.type-grid {
|
||||
margin-top: 22rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.type-chip {
|
||||
height: 56rpx;
|
||||
border-radius: 11rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
color: #737887;
|
||||
font-size: 20rpx;
|
||||
font-weight: 800;
|
||||
background: #f8f8fb;
|
||||
border: 2rpx solid #ececf3;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.type-chip.active {
|
||||
color: #6e4cff;
|
||||
background: #ffffff;
|
||||
border-color: #805cff;
|
||||
filter: hue-rotate(180deg); /* 旋转色相 */
|
||||
filter: sepia(1) saturate(5) hue-rotate(200deg); /* 强制转为暖色调 */
|
||||
}
|
||||
|
||||
.type-chip-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bug-icon {
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid currentColor;
|
||||
}
|
||||
|
||||
.star-icon {
|
||||
border-radius: 5rpx;
|
||||
border: 4rpx solid currentColor;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.message-icon,
|
||||
.more-icon {
|
||||
border: 4rpx solid currentColor;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.desc-card {
|
||||
padding-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.textarea-shell {
|
||||
min-height: 158rpx;
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 20rpx 34rpx;
|
||||
border-radius: 14rpx;
|
||||
border: 1rpx solid #e4e4eb;
|
||||
background: #fbfbfd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.desc-input {
|
||||
width: 100%;
|
||||
height: 104rpx;
|
||||
color: #2d3340;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: #a2a6b2;
|
||||
}
|
||||
|
||||
.counter {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
color: #8f94a2;
|
||||
font-size: 18rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.image-card {
|
||||
min-height: 218rpx;
|
||||
}
|
||||
|
||||
.upload-box {
|
||||
width: 106rpx;
|
||||
height: 106rpx;
|
||||
margin-top: 22rpx;
|
||||
border-radius: 13rpx;
|
||||
border: 2rpx dashed #d8d1f8;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
/* color: #7a57ff; */
|
||||
font-size: 19rpx;
|
||||
/* font-weight: 700; */
|
||||
margin-right: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.upload-box.image-full image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 4rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.plus-icon {
|
||||
font-size: 44rpx;
|
||||
line-height: 0.75;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
margin-top: 12rpx;
|
||||
color: #9ca0ad;
|
||||
font-size: 18rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
min-height: 152rpx;
|
||||
}
|
||||
|
||||
.contact-input {
|
||||
height: 54rpx;
|
||||
margin-top: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 1rpx solid #e6e6ee;
|
||||
background: #fbfbfd;
|
||||
color: #2d3340;
|
||||
font-size: 21rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 68rpx;
|
||||
margin: 12rpx 14rpx 0;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 900;
|
||||
background: linear-gradient(180deg, #a45fff 0%, #6d2df1 100%);
|
||||
box-shadow: 0 12rpx 24rpx rgba(111, 48, 241, 0.24);
|
||||
}
|
||||
|
||||
.thanks-text {
|
||||
margin-top: 8rpx;
|
||||
text-align: center;
|
||||
color: #969aa7;
|
||||
font-size: 19rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// pages/myPackage/ysxy/index.ts
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
<web-view style="width: 100px;height: 100px;" src="https://veil-chat-audio-speed.zhuangb123.com/ashdas.html"></web-view>
|
||||
@@ -0,0 +1 @@
|
||||
/* pages/myPackage/ysxy/index.wxss */
|
||||
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 984 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 48 KiB |