commit
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "文章详情",
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// pages/article-detail/article-detail.ts
|
||||
import { formatDate, getStatusInfo, getChannelInfo, getCoverColor, getCoverIcon } from '../../utils/util'
|
||||
import { EmployeeService } from '../../services/employee'
|
||||
|
||||
Page({
|
||||
data: {
|
||||
article: {} as any,
|
||||
copyId: 0, // 文案ID
|
||||
productId: 0, // 产品ID
|
||||
showClaimButton: true // 是否显示领取按钮
|
||||
},
|
||||
|
||||
onLoad(options: any) {
|
||||
const copyId = parseInt(options.id);
|
||||
const productId = parseInt(options.productId || '0');
|
||||
|
||||
this.setData({
|
||||
copyId,
|
||||
productId
|
||||
});
|
||||
|
||||
// 如果有copyId,显示文案详情
|
||||
if (copyId) {
|
||||
this.setData({
|
||||
article: {
|
||||
id: copyId,
|
||||
title: '正在加载...',
|
||||
content: ''
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 领取文案
|
||||
async claimCopy() {
|
||||
const { copyId, productId } = this.data;
|
||||
|
||||
if (!copyId || !productId) {
|
||||
wx.showToast({
|
||||
title: '参数错误',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await EmployeeService.claimCopy(copyId, productId);
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
wx.showToast({
|
||||
title: '领取成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 隐藏领取按钮
|
||||
this.setData({
|
||||
showClaimButton: false
|
||||
});
|
||||
|
||||
// 延迟后跳转到发布页面,传递领取信息
|
||||
setTimeout(() => {
|
||||
const copy = response.data!.copy;
|
||||
wx.redirectTo({
|
||||
url: `/pages/article-generate/article-generate?copyId=${copyId}&claimId=${response.data!.claim_id}&productId=${productId}&productName=${encodeURIComponent(copy.title)}&title=${encodeURIComponent(copy.title)}&content=${encodeURIComponent(copy.content)}`
|
||||
});
|
||||
}, 1500);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('领取文案失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 分享功能
|
||||
onShareAppMessage() {
|
||||
const article = this.data.article;
|
||||
return {
|
||||
title: article.title || '精彩种草文案',
|
||||
path: `/pages/article-detail/article-detail?id=${this.data.copyId}&productId=${this.data.productId}`,
|
||||
imageUrl: '' // 可以设置文章封面图
|
||||
};
|
||||
},
|
||||
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
const article = this.data.article;
|
||||
return {
|
||||
title: article.title || '精彩种草文案',
|
||||
imageUrl: '' // 可以设置文章封面图
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1,115 +0,0 @@
|
||||
<!--pages/article-detail/article-detail.wxml-->
|
||||
<scroll-view class="container" scroll-y>
|
||||
<view class="article-cover" style="background-color: {{article.coverColor}}">
|
||||
<text class="cover-icon">{{article.coverIcon}}</text>
|
||||
</view>
|
||||
|
||||
<view class="detail-content">
|
||||
<view class="detail-title">{{article.title}}</view>
|
||||
|
||||
<view class="article-meta-info">
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">批次ID:</text>
|
||||
<text class="meta-value">{{article.batch_id}}</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">话题:</text>
|
||||
<text class="meta-value">{{article.topic}}</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">部门:</text>
|
||||
<text class="meta-value">{{article.department_name || article.department}}</text>
|
||||
</view>
|
||||
<view class="meta-item">
|
||||
<text class="meta-label">渠道:</text>
|
||||
<text class="channel-tag channel-{{article.channel}}">{{article.channelText}}</text>
|
||||
</view>
|
||||
<view class="meta-item full-width" wx:if="{{article.coze_tag}}">
|
||||
<text class="meta-label">标签:</text>
|
||||
<text class="meta-value">{{article.coze_tag}}</text>
|
||||
</view>
|
||||
<view class="meta-item full-width" wx:if="{{article.review_comment}}">
|
||||
<text class="meta-label">审核意见:</text>
|
||||
<text class="meta-value">{{article.review_comment}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-author">
|
||||
<view class="detail-author-avatar" style="background-color: {{article.coverColor}}">
|
||||
{{article.author_name ? article.author_name[0] : 'A'}}
|
||||
</view>
|
||||
<view class="author-info">
|
||||
<view class="author-name">{{article.author_name || '匿名'}}</view>
|
||||
<view class="author-time">创建于 {{article.created_at}}</view>
|
||||
</view>
|
||||
<view class="article-status status-{{article.status}}">{{article.statusText}}</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-text">{{article.content}}</view>
|
||||
|
||||
<view class="detail-stats">
|
||||
<view class="detail-stat">
|
||||
<view class="detail-stat-value">{{article.word_count}}</view>
|
||||
<view class="detail-stat-label">字数</view>
|
||||
</view>
|
||||
<view class="detail-stat">
|
||||
<view class="detail-stat-value">{{article.image_count}}</view>
|
||||
<view class="detail-stat-label">图片</view>
|
||||
</view>
|
||||
<view class="detail-stat">
|
||||
<view class="detail-stat-value">{{article.timeText}}</view>
|
||||
<view class="detail-stat-label">创建时间</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="action-buttons" wx:if="{{showActions}}">
|
||||
<button
|
||||
class="action-btn approve-btn"
|
||||
wx:if="{{article.status === 'pending_review'}}"
|
||||
bindtap="handleApprove"
|
||||
>
|
||||
✓ 通过审核
|
||||
</button>
|
||||
<button
|
||||
class="action-btn reject-btn"
|
||||
wx:if="{{article.status === 'pending_review'}}"
|
||||
bindtap="handleReject"
|
||||
>
|
||||
✕ 驳回
|
||||
</button>
|
||||
<button
|
||||
class="action-btn publish-btn"
|
||||
wx:if="{{article.status === 'approved'}}"
|
||||
bindtap="handlePublish"
|
||||
>
|
||||
📤 发布文章
|
||||
</button>
|
||||
<button
|
||||
class="action-btn publish-btn disabled"
|
||||
wx:if="{{article.status === 'published'}}"
|
||||
disabled
|
||||
>
|
||||
✓ 已发布
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="review-section" wx:if="{{showReviewSection}}">
|
||||
<view class="review-title">审核意见</view>
|
||||
<textarea
|
||||
class="review-textarea"
|
||||
placeholder="{{reviewAction === 'reject' ? '请输入驳回原因(必填)' : '请输入审核意见(可选)'}}"
|
||||
value="{{reviewComment}}"
|
||||
bindinput="onCommentInput"
|
||||
maxlength="500"
|
||||
></textarea>
|
||||
<view class="action-buttons">
|
||||
<button class="action-btn approve-btn" bindtap="confirmReview">
|
||||
✓ 确认提交
|
||||
</button>
|
||||
<button class="action-btn cancel-btn" bindtap="cancelReview">
|
||||
✕ 取消
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -1,341 +0,0 @@
|
||||
/* pages/article-detail/article-detail.wxss */
|
||||
page {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background: linear-gradient(to bottom, #fff 0%, #f8f9fa 100%);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.article-cover {
|
||||
width: 100%;
|
||||
height: 450rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.article-cover::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.15) 100%);
|
||||
}
|
||||
|
||||
.cover-icon {
|
||||
font-size: 150rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
filter: drop-shadow(0 8rpx 24rpx rgba(0, 0, 0, 0.15));
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
width: 100%;
|
||||
padding: 50rpx 40rpx;
|
||||
background: white;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
margin-top: -40rpx;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
box-shadow: 0 -8rpx 32rpx rgba(0, 0, 0, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 35rpx;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 1rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.article-meta-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24rpx;
|
||||
margin-bottom: 35rpx;
|
||||
padding: 35rpx;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #fff 100%);
|
||||
border-radius: 20rpx;
|
||||
border: 1rpx solid #f0f0f0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
flex: 0 0 auto;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.meta-item.full-width {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.meta-label {
|
||||
color: #999;
|
||||
margin-right: 12rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.meta-value {
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.channel-tag {
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
|
||||
.channel-1 {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.channel-2 {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.channel-3 {
|
||||
background-color: #f0f9ff;
|
||||
color: #07c160;
|
||||
}
|
||||
|
||||
.detail-author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #fff 100%);
|
||||
border-radius: 20rpx;
|
||||
border: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.detail-author-avatar {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 36rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.author-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10rpx;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.author-time {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.article-status {
|
||||
padding: 10rpx 28rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
|
||||
.status-topic {
|
||||
background-color: #f0f5ff;
|
||||
color: #2f54eb;
|
||||
}
|
||||
|
||||
.status-cover_image {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.status-generate {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.status-generate_failed {
|
||||
background-color: #fff1f0;
|
||||
color: #f5222d;
|
||||
}
|
||||
|
||||
.status-draft {
|
||||
background-color: #f5f5f5;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.status-pending_review {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.status-approved {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.status-rejected {
|
||||
background-color: #fff1f0;
|
||||
color: #f5222d;
|
||||
}
|
||||
|
||||
.status-published_review {
|
||||
background-color: #e6fffb;
|
||||
color: #13c2c2;
|
||||
}
|
||||
|
||||
.status-published {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.status-failed {
|
||||
background-color: #fff1f0;
|
||||
color: #f5222d;
|
||||
}
|
||||
|
||||
.detail-text {
|
||||
font-size: 32rpx;
|
||||
line-height: 2;
|
||||
color: #444;
|
||||
margin-bottom: 40rpx;
|
||||
white-space: pre-wrap;
|
||||
padding: 30rpx;
|
||||
background: #fafafa;
|
||||
border-radius: 20rpx;
|
||||
border-left: 4rpx solid #07c160;
|
||||
word-break: break-all;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.detail-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: 50rpx;
|
||||
padding: 40rpx 0;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #fff 100%);
|
||||
border-radius: 20rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.detail-stat {
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.detail-stat-value {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #07c160;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.detail-stat-label {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
margin-top: 40rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
flex: 1;
|
||||
min-width: 200rpx;
|
||||
padding: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
color: white;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.12);
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.action-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.approve-btn {
|
||||
background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
|
||||
}
|
||||
|
||||
.reject-btn {
|
||||
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
|
||||
}
|
||||
|
||||
.publish-btn {
|
||||
background: #07c160;
|
||||
}
|
||||
|
||||
.publish-btn.disabled {
|
||||
background: #d9d9d9;
|
||||
color: #999;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: linear-gradient(135deg, #d9d9d9 0%, #e8e8e8 100%);
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.review-section {
|
||||
margin-top: 50rpx;
|
||||
padding: 40rpx;
|
||||
background: linear-gradient(135deg, #fff5f5 0%, #fff 100%);
|
||||
border-radius: 20rpx;
|
||||
border: 2rpx solid #ffebee;
|
||||
}
|
||||
|
||||
.review-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 30rpx;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.review-textarea {
|
||||
width: 100%;
|
||||
min-height: 220rpx;
|
||||
padding: 28rpx;
|
||||
border: 2rpx solid #f0f0f0;
|
||||
border-radius: 16rpx;
|
||||
font-size: 30rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 30rpx;
|
||||
background: white;
|
||||
line-height: 1.8;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "AI生成种草文章",
|
||||
"navigationBarBackgroundColor": "#ff2442",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
// pages/article-generate/article-generate.ts
|
||||
import { EmployeeService } from '../../services/employee';
|
||||
|
||||
interface Article {
|
||||
title: string;
|
||||
content: string;
|
||||
tags: string[];
|
||||
images: string[];
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
productId: 0,
|
||||
productName: '',
|
||||
copyId: 0, // 领取的文案ID
|
||||
claimId: 0, // 领取记录ID
|
||||
article: {
|
||||
title: '',
|
||||
content: '',
|
||||
tags: [],
|
||||
images: []
|
||||
} as Article,
|
||||
generating: false,
|
||||
isFromClaim: false // 是否来自领取的文案
|
||||
},
|
||||
|
||||
onLoad(options: any) {
|
||||
const { productId, productName, copyId, claimId, title, content } = options;
|
||||
|
||||
this.setData({
|
||||
productId: parseInt(productId || '0'),
|
||||
productName: decodeURIComponent(productName || ''),
|
||||
copyId: parseInt(copyId || '0'),
|
||||
claimId: parseInt(claimId || '0'),
|
||||
isFromClaim: !!copyId
|
||||
});
|
||||
|
||||
// 如果有copyId,说明是从领取文案过来的
|
||||
if (this.data.copyId && this.data.claimId) {
|
||||
// 如果有传递文案内容,直接显示
|
||||
if (title && content) {
|
||||
this.setData({
|
||||
article: {
|
||||
title: decodeURIComponent(title),
|
||||
content: decodeURIComponent(content),
|
||||
tags: ['种草分享', '好物推荐'],
|
||||
images: []
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 否则生成模拟文案
|
||||
this.generateArticle();
|
||||
}
|
||||
} else {
|
||||
// 生成文章
|
||||
this.generateArticle();
|
||||
}
|
||||
},
|
||||
|
||||
// 生成文章
|
||||
generateArticle() {
|
||||
this.setData({ generating: true });
|
||||
|
||||
wx.showLoading({
|
||||
title: '生成中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 模拟AI生成文章
|
||||
setTimeout(() => {
|
||||
const mockArticles = [
|
||||
{
|
||||
title: `【种草分享】${this.data.productName}使用体验💕`,
|
||||
content: `姐妹们!今天必须来跟大家分享一下我最近入手的宝藏好物——${this.data.productName}!
|
||||
|
||||
✨使用感受:
|
||||
用了一段时间真的太爱了!质感超级好,完全超出我的预期。包装也非常精致,送人自用都很合适。
|
||||
|
||||
🌟推荐理由:
|
||||
1. 品质优秀,性价比超高
|
||||
2. 使用体验一级棒
|
||||
3. 颜值在线,拿出来超有面子
|
||||
|
||||
💰价格也很美丽,趁着活动入手真的很划算!强烈推荐给大家,绝对不会踩雷!`,
|
||||
tags: ['种草分享', '好物推荐', '必买清单', '真实测评'],
|
||||
images: [
|
||||
'https://picsum.photos/id/237/600/400',
|
||||
'https://picsum.photos/id/152/600/400'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: `真香警告!${this.data.productName}实测分享`,
|
||||
content: `集美们看过来!今天给大家带来${this.data.productName}的真实使用感受~
|
||||
|
||||
🎯第一印象:
|
||||
收到货的那一刻就被惊艳到了!包装精美,细节满满,完全是高端货的质感。
|
||||
|
||||
💫使用体验:
|
||||
用了几天下来,真的是越用越喜欢!质量很好,用起来特别顺手,完全就是我想要的样子!
|
||||
|
||||
⭐️总结:
|
||||
这个价位能买到这么好的产品,真的是太值了!强烈安利给大家,闭眼入不会错!`,
|
||||
tags: ['真实测评', '使用心得', '好物安利', '值得入手'],
|
||||
images: [
|
||||
'https://picsum.photos/id/292/600/400',
|
||||
'https://picsum.photos/id/365/600/400',
|
||||
'https://picsum.photos/id/180/600/400'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const randomArticle = mockArticles[Math.floor(Math.random() * mockArticles.length)];
|
||||
|
||||
this.setData({
|
||||
article: randomArticle,
|
||||
generating: false
|
||||
});
|
||||
|
||||
wx.hideLoading();
|
||||
}, 2000);
|
||||
},
|
||||
|
||||
// 删除图片
|
||||
deleteImage(e: any) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const images = this.data.article.images;
|
||||
images.splice(index, 1);
|
||||
|
||||
this.setData({
|
||||
'article.images': images
|
||||
});
|
||||
},
|
||||
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
wx.navigateBack();
|
||||
},
|
||||
|
||||
// 重新生成文章
|
||||
regenerateArticle() {
|
||||
if (this.data.generating) return;
|
||||
this.generateArticle();
|
||||
},
|
||||
|
||||
// 发布文章
|
||||
async publishArticle() {
|
||||
wx.showModal({
|
||||
title: '确认发布',
|
||||
content: '确定要发布这篇种草文章吗?',
|
||||
confirmText: '发布',
|
||||
confirmColor: '#ff2442',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
// 如果是从领取的文案,调用后端API
|
||||
if (this.data.isFromClaim && this.data.copyId) {
|
||||
try {
|
||||
const response = await EmployeeService.publish({
|
||||
copy_id: this.data.copyId,
|
||||
title: this.data.article.title,
|
||||
content: this.data.article.content,
|
||||
publish_link: '', // 可以后续添加发布链接输入
|
||||
xhs_note_id: '' // 小红书笔记ID
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
wx.showToast({
|
||||
title: '发布成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
// 保存到本地
|
||||
const articles = wx.getStorageSync('myArticles') || [];
|
||||
articles.unshift({
|
||||
id: (response.data && response.data.record_id) || Date.now(),
|
||||
productName: this.data.productName,
|
||||
title: this.data.article.title,
|
||||
content: this.data.article.content,
|
||||
tags: this.data.article.tags,
|
||||
createTime: new Date().toISOString(),
|
||||
status: 'published'
|
||||
});
|
||||
wx.setStorageSync('myArticles', articles);
|
||||
|
||||
// 2秒后返回首页
|
||||
setTimeout(() => {
|
||||
wx.navigateBack();
|
||||
}, 2000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发布失败:', error);
|
||||
}
|
||||
} else {
|
||||
// 模拟发布(非领取文案的情况)
|
||||
wx.showLoading({
|
||||
title: '发布中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: '发布成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
// 保存到本地(模拟)
|
||||
const articles = wx.getStorageSync('myArticles') || [];
|
||||
articles.unshift({
|
||||
id: Date.now(),
|
||||
productName: this.data.productName,
|
||||
title: this.data.article.title,
|
||||
content: this.data.article.content,
|
||||
tags: this.data.article.tags,
|
||||
createTime: new Date().toISOString(),
|
||||
status: 'published'
|
||||
});
|
||||
wx.setStorageSync('myArticles', articles);
|
||||
|
||||
// 2秒后返回首页
|
||||
setTimeout(() => {
|
||||
wx.navigateBack();
|
||||
}, 2000);
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,52 +0,0 @@
|
||||
<!--pages/article-generate/article-generate.wxml-->
|
||||
<view class="page-container">
|
||||
<!-- 顶部标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" bindtap="goBack">
|
||||
<view class="back-icon"></view>
|
||||
</view>
|
||||
<text class="page-title">生成具体内容</text>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 文章内容 -->
|
||||
<scroll-view class="article-container" scroll-y enable-flex>
|
||||
<view class="article-wrapper">
|
||||
<!-- 图片列表 -->
|
||||
<view class="article-images" wx:if="{{article.images.length > 0}}">
|
||||
<view
|
||||
class="image-item"
|
||||
wx:for="{{article.images}}"
|
||||
wx:key="index"
|
||||
>
|
||||
<image
|
||||
class="article-image"
|
||||
src="{{item}}"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="delete-icon" bindtap="deleteImage" data-index="{{index}}">
|
||||
<text class="delete-text">×</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 标题和内容 -->
|
||||
<view class="article-header">
|
||||
<text class="article-title">{{article.title}}</text>
|
||||
</view>
|
||||
|
||||
<view class="article-content">
|
||||
<text class="content-text">{{article.content}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="action-bar">
|
||||
<button class="action-btn secondary" bindtap="regenerateArticle">
|
||||
<text class="btn-text">换一换</text>
|
||||
</button>
|
||||
<button class="action-btn primary" bindtap="publishArticle">
|
||||
<text class="btn-text">一键发布</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -1,184 +0,0 @@
|
||||
/* pages/article-generate/article-generate.wxss */
|
||||
page {
|
||||
background: white;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: calc(136rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 30rpx;
|
||||
background: white;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.header-left,
|
||||
.header-right {
|
||||
width: 80rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%231a1a1a"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* 文章容器 */
|
||||
.article-container {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.article-wrapper {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
/* 图片列表 */
|
||||
.article-images {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 30rpx;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.article-images::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
flex-shrink: 0;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
position: relative;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.article-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
right: 8rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.delete-text {
|
||||
font-size: 36rpx;
|
||||
color: white;
|
||||
line-height: 1;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/* 标题区域 */
|
||||
.article-header {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.article-title {
|
||||
font-size: 36rpx;
|
||||
color: #1a1a1a;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.article-content {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.content-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.8;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
/* 操作栏 */
|
||||
.action-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx 30rpx;
|
||||
background: white;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
flex: 1;
|
||||
height: 96rpx;
|
||||
border: none;
|
||||
border-radius: 48rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.action-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
background: white;
|
||||
color: #07c160;
|
||||
border: 2rpx solid #07c160;
|
||||
}
|
||||
|
||||
.action-btn.secondary:active {
|
||||
background: #f0f9f4;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background: #07c160;
|
||||
color: white;
|
||||
box-shadow: 0 4rpx 16rpx rgba(7, 193, 96, 0.3);
|
||||
}
|
||||
|
||||
.action-btn.primary:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// index.ts
|
||||
// 获取应用实例
|
||||
const app = getApp<IAppOption>()
|
||||
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
|
||||
|
||||
Component({
|
||||
data: {
|
||||
motto: 'Hello World',
|
||||
userInfo: {
|
||||
avatarUrl: defaultAvatarUrl,
|
||||
nickName: '',
|
||||
},
|
||||
hasUserInfo: false,
|
||||
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
|
||||
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
|
||||
},
|
||||
methods: {
|
||||
// 事件处理函数
|
||||
bindViewTap() {
|
||||
wx.navigateTo({
|
||||
url: '../logs/logs',
|
||||
})
|
||||
},
|
||||
onChooseAvatar(e: any) {
|
||||
const { avatarUrl } = e.detail
|
||||
const { nickName } = this.data.userInfo
|
||||
this.setData({
|
||||
"userInfo.avatarUrl": avatarUrl,
|
||||
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
|
||||
})
|
||||
},
|
||||
onInputChange(e: any) {
|
||||
const nickName = e.detail.value
|
||||
const { avatarUrl } = this.data.userInfo
|
||||
this.setData({
|
||||
"userInfo.nickName": nickName,
|
||||
hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl,
|
||||
})
|
||||
},
|
||||
getUserProfile() {
|
||||
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
|
||||
wx.getUserProfile({
|
||||
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
this.setData({
|
||||
userInfo: res.userInfo,
|
||||
hasUserInfo: true
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1,27 +0,0 @@
|
||||
<!--index.wxml-->
|
||||
<scroll-view class="scrollarea" scroll-y type="list">
|
||||
<view class="container">
|
||||
<view class="userinfo">
|
||||
<block wx:if="{{canIUseNicknameComp && !hasUserInfo}}">
|
||||
<button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
|
||||
<image class="avatar" src="{{userInfo.avatarUrl}}"></image>
|
||||
</button>
|
||||
<view class="nickname-wrapper">
|
||||
<text class="nickname-label">昵称</text>
|
||||
<input type="nickname" class="nickname-input" placeholder="请输入昵称" bind:change="onInputChange" />
|
||||
</view>
|
||||
</block>
|
||||
<block wx:elif="{{!hasUserInfo}}">
|
||||
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
|
||||
<view wx:else> 请使用2.10.4及以上版本基础库 </view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
|
||||
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
|
||||
</block>
|
||||
</view>
|
||||
<view class="usermotto">
|
||||
<text class="user-motto">{{motto}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -1,62 +0,0 @@
|
||||
/**index.wxss**/
|
||||
page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.scrollarea {
|
||||
flex: 1;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.userinfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #aaa;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.userinfo-avatar {
|
||||
overflow: hidden;
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.usermotto {
|
||||
margin-top: 200px;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
padding: 0;
|
||||
width: 56px !important;
|
||||
border-radius: 8px;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.nickname-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-top: .5px solid rgba(0, 0, 0, 0.1);
|
||||
border-bottom: .5px solid rgba(0, 0, 0, 0.1);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.nickname-label {
|
||||
width: 105px;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "环境切换",
|
||||
"navigationBarBackgroundColor": "#667eea",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<!--pages/profile/env-switch/env-switch.wxml-->
|
||||
<view class="container">
|
||||
<!-- 当前环境 -->
|
||||
<view class="current-env">
|
||||
<view class="env-label">当前环境</view>
|
||||
<view class="env-value">
|
||||
<text class="env-tag env-tag-{{currentEnv}}">{{currentEnv === 'dev' ? '开发环境' : currentEnv === 'test' ? '测试环境' : '生产环境'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 环境列表 -->
|
||||
<view class="env-list">
|
||||
<view
|
||||
class="env-item {{currentEnv === item.key ? 'active' : ''}}"
|
||||
wx:for="{{envList}}"
|
||||
wx:key="key"
|
||||
bindtap="switchEnvironment"
|
||||
data-env="{{item.key}}"
|
||||
>
|
||||
<view class="env-header">
|
||||
<view class="env-name">
|
||||
<text class="env-icon" style="background-color: {{item.color}}"></text>
|
||||
<text>{{item.name}}</text>
|
||||
</view>
|
||||
<view class="env-status">
|
||||
<text wx:if="{{currentEnv === item.key}}" class="current-tag">当前</text>
|
||||
<text wx:else class="switch-text">切换</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="env-info">
|
||||
<view class="info-item">
|
||||
<text class="info-label">主服务:</text>
|
||||
<text class="info-value" bindtap="copyURL" catchtap="copyURL" data-url="{{configs[item.key].baseURL}}">
|
||||
{{configs[item.key].baseURL}}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item" wx:if="{{configs[item.key].pythonURL}}">
|
||||
<text class="info-label">Python:</text>
|
||||
<text class="info-value" bindtap="copyURL" catchtap="copyURL" data-url="{{configs[item.key].pythonURL}}">
|
||||
{{configs[item.key].pythonURL}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 说明 -->
|
||||
<view class="tips">
|
||||
<view class="tips-title">⚠️ 温馨提示</view>
|
||||
<view class="tips-item">• 切换环境后会清除登录状态,需要重新登录</view>
|
||||
<view class="tips-item">• 开发环境用于本地开发调试</view>
|
||||
<view class="tips-item">• 测试环境用于服务器功能测试</view>
|
||||
<view class="tips-item">• 生产环境为正式线上环境</view>
|
||||
<view class="tips-item">• 点击地址可以复制</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="actions">
|
||||
<button class="action-btn" bindtap="restartApp">重启小程序</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -328,20 +328,6 @@ Page({
|
||||
});
|
||||
},
|
||||
|
||||
// 数据统计
|
||||
goToStats() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/stats/stats'
|
||||
});
|
||||
},
|
||||
|
||||
// 我的文章
|
||||
goToMyArticles() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/my-articles/my-articles'
|
||||
});
|
||||
},
|
||||
|
||||
// 已发布文章
|
||||
goToPublished() {
|
||||
wx.navigateTo({
|
||||
@@ -349,34 +335,6 @@ Page({
|
||||
});
|
||||
},
|
||||
|
||||
// 收藏夹
|
||||
goToFavorites() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/favorites/favorites'
|
||||
});
|
||||
},
|
||||
|
||||
// 消息通知
|
||||
goToNotifications() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/notifications/notifications'
|
||||
});
|
||||
},
|
||||
|
||||
// 个人资料
|
||||
goToUserInfo() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/user-info/user-info'
|
||||
});
|
||||
},
|
||||
|
||||
// 社交账号绑定
|
||||
goToSocialBinding() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/social-binding/social-binding'
|
||||
});
|
||||
},
|
||||
|
||||
// 意见反馈
|
||||
goToFeedback() {
|
||||
wx.navigateTo({
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "社交账号绑定",
|
||||
"navigationBarBackgroundColor": "#ff2442",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
// pages/profile/social-binding/social-binding.ts
|
||||
import { EmployeeService } from '../../../services/employee';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
// 小红书
|
||||
xiaohongshuBinded: false,
|
||||
xiaohongshuPhone: '',
|
||||
xiaohongshuAccount: '',
|
||||
xiaohongshuCookieExpired: false, // Cookie是否失效
|
||||
xiaohongshuStatusText: '去绑定',
|
||||
xiaohongshuStatusClass: '',
|
||||
|
||||
// 微博
|
||||
weiboBinded: false,
|
||||
weiboPhone: '',
|
||||
|
||||
// 抖音
|
||||
douyinBinded: false,
|
||||
douyinPhone: ''
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadBindingStatus();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 每次显示时重新加载绑定状态
|
||||
this.loadBindingStatus();
|
||||
// 同时从后端加载
|
||||
this.loadUserProfile();
|
||||
},
|
||||
|
||||
// 从BACKEND加载用户信息(包含小红书绑定状态)
|
||||
async loadUserProfile() {
|
||||
try {
|
||||
const response = await EmployeeService.getProfile();
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
const userInfo = response.data;
|
||||
const isBound = userInfo.is_bound_xhs === 1;
|
||||
// 使用has_xhs_cookie字段判断,而不是xhs_cookie
|
||||
const hasCookie = userInfo.has_xhs_cookie === true;
|
||||
|
||||
// 判断状态
|
||||
let statusText = '去绑定';
|
||||
let statusClass = '';
|
||||
let cookieExpired = false;
|
||||
|
||||
if (isBound) {
|
||||
if (hasCookie) {
|
||||
// 已绑定且Cookie有效
|
||||
statusText = '已绑定';
|
||||
statusClass = 'binded';
|
||||
} else {
|
||||
// 已绑定但Cookie失效
|
||||
statusText = '已失效';
|
||||
statusClass = 'expired';
|
||||
cookieExpired = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.setData({
|
||||
xiaohongshuBinded: isBound,
|
||||
xiaohongshuAccount: userInfo.xhs_account || '',
|
||||
xiaohongshuPhone: userInfo.xhs_phone || '',
|
||||
xiaohongshuCookieExpired: cookieExpired,
|
||||
xiaohongshuStatusText: statusText,
|
||||
xiaohongshuStatusClass: statusClass
|
||||
});
|
||||
|
||||
// 更新本地存储
|
||||
if (isBound) {
|
||||
const bindings = wx.getStorageSync('socialBindings') || {};
|
||||
bindings.xiaohongshu = {
|
||||
phone: userInfo.xhs_phone,
|
||||
xhs_account: userInfo.xhs_account,
|
||||
bindTime: userInfo.bound_at || new Date().getTime(),
|
||||
cookieExpired: cookieExpired
|
||||
};
|
||||
wx.setStorageSync('socialBindings', bindings);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载用户信息失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 加载绑定状态
|
||||
loadBindingStatus() {
|
||||
const bindings = wx.getStorageSync('socialBindings') || {};
|
||||
|
||||
this.setData({
|
||||
xiaohongshuBinded: !!bindings.xiaohongshu,
|
||||
xiaohongshuPhone: (bindings.xiaohongshu && bindings.xiaohongshu.phone) || '',
|
||||
|
||||
weiboBinded: !!bindings.weibo,
|
||||
weiboPhone: (bindings.weibo && bindings.weibo.phone) || '',
|
||||
|
||||
douyinBinded: !!bindings.douyin,
|
||||
douyinPhone: (bindings.douyin && bindings.douyin.phone) || ''
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到平台绑定页面
|
||||
goToPlatformBind(e: any) {
|
||||
const platform = e.currentTarget.dataset.platform;
|
||||
|
||||
// 如果是小红书
|
||||
if (platform === 'xiaohongshu') {
|
||||
// Cookie失效,直接跳转重新绑定
|
||||
if (this.data.xiaohongshuCookieExpired) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/xhs-login/xhs-login'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 已绑定且Cookie有效,显示解绑确认
|
||||
if (this.data.xiaohongshuBinded && !this.data.xiaohongshuCookieExpired) {
|
||||
this.handleUnbindXHS();
|
||||
return;
|
||||
}
|
||||
|
||||
// 未绑定,跳转到绑定页
|
||||
wx.navigateTo({
|
||||
url: '/pages/profile/xhs-login/xhs-login'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.navigateTo({
|
||||
url: `/pages/profile/platform-bind/platform-bind?platform=${platform}`
|
||||
});
|
||||
},
|
||||
|
||||
// 解绑小红书
|
||||
handleUnbindXHS() {
|
||||
wx.showModal({
|
||||
title: '确认解绑',
|
||||
content: '确定要解绑小红书账号吗?',
|
||||
confirmText: '解绑',
|
||||
confirmColor: '#FF6B6B',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const response = await EmployeeService.unbindXHS();
|
||||
|
||||
if (response.code === 200) {
|
||||
wx.showToast({
|
||||
title: '解绑成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 清除本地存储
|
||||
const bindings = wx.getStorageSync('socialBindings') || {};
|
||||
delete bindings.xiaohongshu;
|
||||
wx.setStorageSync('socialBindings', bindings);
|
||||
|
||||
// 刷新页面
|
||||
this.setData({
|
||||
xiaohongshuBinded: false,
|
||||
xiaohongshuPhone: '',
|
||||
xiaohongshuAccount: ''
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解绑失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
<!--pages/profile/social-binding/social-binding.wxml-->
|
||||
<view class="page-container">
|
||||
<scroll-view class="content-scroll" scroll-y>
|
||||
|
||||
<!-- 小红书 -->
|
||||
<view class="platform-item" bindtap="goToPlatformBind" data-platform="xiaohongshu">
|
||||
<view class="platform-left">
|
||||
<view class="platform-icon xiaohongshu"></view>
|
||||
<view class="platform-info">
|
||||
<text class="platform-name">小红书</text>
|
||||
<text class="platform-desc">{{xiaohongshuBinded ? xiaohongshuPhone : '未绑定'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="platform-right">
|
||||
<view class="bind-status {{xiaohongshuStatusClass}}">{{xiaohongshuStatusText}}</view>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 微博 -->
|
||||
<view class="platform-item" bindtap="goToPlatformBind" data-platform="weibo">
|
||||
<view class="platform-left">
|
||||
<view class="platform-icon weibo"></view>
|
||||
<view class="platform-info">
|
||||
<text class="platform-name">微博</text>
|
||||
<text class="platform-desc">{{weiboBinded ? weiboPhone : '未绑定'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="platform-right">
|
||||
<view class="bind-status {{weiboBinded ? 'binded' : ''}}">{{weiboBinded ? '已绑定' : '去绑定'}}</view>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 抖音 -->
|
||||
<view class="platform-item" bindtap="goToPlatformBind" data-platform="douyin">
|
||||
<view class="platform-left">
|
||||
<view class="platform-icon douyin"></view>
|
||||
<view class="platform-info">
|
||||
<text class="platform-name">抖音</text>
|
||||
<text class="platform-desc">{{douyinBinded ? douyinPhone : '未绑定'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="platform-right">
|
||||
<view class="bind-status {{douyinBinded ? 'binded' : ''}}">{{douyinBinded ? '已绑定' : '去绑定'}}</view>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -1,112 +0,0 @@
|
||||
/* pages/profile/social-binding/social-binding.wxss */
|
||||
page {
|
||||
background: #f8f8f8;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 平台列表项 */
|
||||
.platform-item {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.platform-item:active {
|
||||
transform: scale(0.98);
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.platform-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.platform-icon {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.platform-icon.xiaohongshu {
|
||||
background: #07c160;
|
||||
}
|
||||
|
||||
.platform-icon.weibo {
|
||||
background: linear-gradient(135deg, #ff8200 0%, #ffb84d 100%);
|
||||
}
|
||||
|
||||
.platform-icon.douyin {
|
||||
background: linear-gradient(135deg, #000000 0%, #333333 100%);
|
||||
}
|
||||
|
||||
.platform-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.platform-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.platform-desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.platform-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.bind-status {
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
background: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.bind-status.binded {
|
||||
background: #e8f5e9;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.bind-status.expired {
|
||||
background: #fff3e0;
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.item-arrow {
|
||||
font-size: 40rpx;
|
||||
color: #d0d0d0;
|
||||
font-weight: 300;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "个人资料",
|
||||
"navigationBarBackgroundColor": "#ff2442",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// pages/profile/user-info/user-info.ts
|
||||
Page({
|
||||
data: {
|
||||
username: '管理员'
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
const username = wx.getStorageSync('username') || '管理员';
|
||||
this.setData({ username });
|
||||
},
|
||||
|
||||
handleSave() {
|
||||
wx.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
@@ -1,49 +0,0 @@
|
||||
<!--pages/profile/user-info/user-info.wxml-->
|
||||
<view class="page-container">
|
||||
<view class="info-section">
|
||||
<view class="info-item">
|
||||
<view class="item-label">头像</view>
|
||||
<view class="item-value">
|
||||
<view class="avatar-preview">
|
||||
<text class="avatar-icon"></text>
|
||||
</view>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="item-label">昵称</view>
|
||||
<view class="item-value">
|
||||
<text class="value-text">{{username}}</text>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="item-label">手机号</view>
|
||||
<view class="item-value">
|
||||
<text class="value-text">138****8888</text>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="item-label">邮箱</view>
|
||||
<view class="item-value">
|
||||
<text class="value-text">user@example.com</text>
|
||||
<text class="item-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="item-label">角色</view>
|
||||
<view class="item-value">
|
||||
<text class="value-text role">内容管理员</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="save-section">
|
||||
<button class="save-btn" bindtap="handleSave">保存修改</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -1,99 +0,0 @@
|
||||
/* pages/profile/user-info/user-info.wxss */
|
||||
page {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
width: 100%;
|
||||
background: white;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 32rpx 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.value-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value-text.role {
|
||||
color: #07c160;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.item-arrow {
|
||||
font-size: 36rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #fff5f7 0%, #ffe8ec 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ff2442"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.save-section {
|
||||
width: 100%;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
width: 100%;
|
||||
background: #07c160;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 8rpx 24rpx rgba(255, 36, 66, 0.3);
|
||||
}
|
||||
|
||||
.save-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.save-btn:active {
|
||||
opacity: 0.9;
|
||||
transform: translateY(2rpx);
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
<!--pages/profile/xhs-publish/xhs-publish.wxml-->
|
||||
<view class="page-container">
|
||||
<!-- 渐变红背景 + 动画效果 -->
|
||||
<view class="background">
|
||||
<view class="gradient-bg"></view>
|
||||
<view class="circle circle1"></view>
|
||||
<view class="circle circle2"></view>
|
||||
<view class="circle circle3"></view>
|
||||
</view>
|
||||
|
||||
<!-- 发布卡片 - 毛玻璃效果 -->
|
||||
<view class="publish-card">
|
||||
<view class="card-header">
|
||||
<text class="header-title">✨ 发布小红书笔记</text>
|
||||
<text class="header-subtitle">分享你的精彩时刻</text>
|
||||
</view>
|
||||
|
||||
<!-- 标题输入 -->
|
||||
<view class="input-group">
|
||||
<view class="input-label">
|
||||
<text class="label-icon">📝</text>
|
||||
<text class="label-text">标题</text>
|
||||
</view>
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="给你的笔记起个吸引人的标题"
|
||||
value="{{title}}"
|
||||
bindinput="onTitleInput"
|
||||
maxlength="30"
|
||||
/>
|
||||
<view class="char-count">{{title.length}}/30</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容输入 -->
|
||||
<view class="input-group">
|
||||
<view class="input-label">
|
||||
<text class="label-icon">✍️</text>
|
||||
<text class="label-text">正文内容</text>
|
||||
</view>
|
||||
<textarea
|
||||
class="textarea-field"
|
||||
placeholder="分享你的故事、经验或想法..."
|
||||
value="{{content}}"
|
||||
bindinput="onContentInput"
|
||||
maxlength="1000"
|
||||
auto-height
|
||||
></textarea>
|
||||
<view class="char-count">{{content.length}}/1000</view>
|
||||
</view>
|
||||
|
||||
<!-- 话题标签 -->
|
||||
<view class="input-group">
|
||||
<view class="input-label">
|
||||
<text class="label-icon">🏷️</text>
|
||||
<text class="label-text">话题标签</text>
|
||||
<text class="label-tip">(可选)</text>
|
||||
</view>
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="输入话题后按空格分隔,如:旅行 美食 生活"
|
||||
value="{{topicsText}}"
|
||||
bindinput="onTopicsInput"
|
||||
/>
|
||||
<view class="topics-preview" wx:if="{{topics.length > 0}}">
|
||||
<block wx:for="{{topics}}" wx:key="index">
|
||||
<view class="topic-tag">#{{item}}#</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tips-box">
|
||||
<text class="tips-icon">💡</text>
|
||||
<text class="tips-text">发布前请确保已登录小红书账号</text>
|
||||
</view>
|
||||
|
||||
<!-- 发布按钮 -->
|
||||
<button
|
||||
class="publish-btn {{publishing ? 'disabled' : ''}}"
|
||||
bindtap="handlePublish"
|
||||
disabled="{{publishing}}"
|
||||
>
|
||||
<text wx:if="{{!publishing}}">🚀 立即发布</text>
|
||||
<text wx:else>发布中...</text>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- Toast提示 -->
|
||||
<view class="toast {{showToast ? 'show' : ''}}" wx:if="{{toastMessage}}">
|
||||
<text>{{toastMessage}}</text>
|
||||
</view>
|
||||
</view>
|
||||
Reference in New Issue
Block a user