Browse Source

经验分享发布

master
ZhaoYang 1 month ago
parent
commit
663d86ca0d
  1. 3
      app.json
  2. 191
      pagesA/pages/releaseSuffer/releaseSuffer.js
  3. 4
      pagesA/pages/releaseSuffer/releaseSuffer.json
  4. 109
      pagesA/pages/releaseSuffer/releaseSuffer.wxml
  5. 278
      pagesA/pages/releaseSuffer/releaseSuffer.wxss
  6. 7
      pagesB/pages/experienceList/experienceList.js
  7. 8
      pagesB/pages/experienceList/experienceList.wxml
  8. 61
      pagesB/pages/experienceList/experienceList.wxss
  9. 10
      utils/api.js

3
app.json

@ -22,7 +22,8 @@
"pages/noticeList/noticeList", "pages/noticeList/noticeList",
"pages/noticeListDetails/noticeListDetails", "pages/noticeListDetails/noticeListDetails",
"pages/todayInquiry/todayInquiry", "pages/todayInquiry/todayInquiry",
"pages/carouselDetail/carouselDetail"
"pages/carouselDetail/carouselDetail",
"pages/releaseSuffer/releaseSuffer"
] ]
}, },
{ {

191
pagesA/pages/releaseSuffer/releaseSuffer.js

@ -0,0 +1,191 @@
import http from '../../../utils/api';
const baseUrl = require('../../../utils/baseUrl');
Page({
data: {
baseUrl: baseUrl,
// 表单数据
formData: {
title: '',
summary: '',
categoryName: '',
tags: '', // 改为字符串格式,如 "传染病,疫苗"
content: ''
},
// 分类列表 - 直接从接口返回的 rows 赋值
categoryList: [],
categoryIndex: -1,
// 标签列表 - 直接从接口返回的 rows 赋值
tagList: [],
// 已选中的标签对象数组
selectedTags: [],
// 提交状态
submitting: false
},
onLoad(options) {
this.getCategoryList();
this.getTagList();
},
// 输入处理
onInput(e) {
const { field } = e.currentTarget.dataset;
const { value } = e.detail;
this.setData({
[`formData.${field}`]: value
});
},
// 获取文章分类 - 直接使用 res.rows
getCategoryList() {
http.articleZd({
data: {
dictType: 'vet_experience_category'
},
success: (res) => {
// 直接使用 res.rows 赋值
if (res.rows && Array.isArray(res.rows)) {
this.setData({ categoryList: res.rows });
} else {
console.error('分类数据格式错误', res);
wx.showToast({ title: '分类加载失败', icon: 'none' });
}
},
fail: (err) => {
console.error('分类接口异常', err);
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
// 获取文章标签 - 直接使用 res.rows
getTagList() {
http.videoZd({
data: {
dictType: 'vet_experience_tag'
},
success: (res) => {
// 直接使用 res.rows 赋值
if (res.rows && Array.isArray(res.rows)) {
this.setData({ tagList: res.rows });
} else {
console.error('标签数据格式错误', res);
wx.showToast({ title: '标签加载失败', icon: 'none' });
}
},
fail: (err) => {
console.error('标签接口异常', err);
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
// 分类选择
onCategoryChange(e) {
const index = parseInt(e.detail.value, 10);
const selectedCategory = this.data.categoryList[index];
this.setData({
categoryIndex: index,
[`formData.categoryName`]: selectedCategory.dictLabel
});
},
// 标签点击切换
toggleTag(e) {
const tagItem = e.currentTarget.dataset.item;
let selectedTags = [...this.data.selectedTags];
const index = selectedTags.findIndex(t => t.dictValue === tagItem.dictValue);
if (index > -1) {
selectedTags.splice(index, 1);
} else {
selectedTags.push(tagItem);
}
// 生成逗号分隔的标签字符串,如 "传染病,疫苗"
const tagString = selectedTags.map(item => item.dictLabel).join(',');
this.setData({
selectedTags: selectedTags,
[`formData.tags`]: tagString
});
},
// 表单提交
formSubmit(e) {
const { title, categoryName, content } = this.data.formData;
// 表单验证
if (!title || title.trim() === '') {
this.showError('请填写文章标题');
return;
}
if (!categoryName) {
this.showError('请选择文章分类');
return;
}
if (this.data.selectedTags.length === 0) {
this.showError('请至少选择一个标签');
return;
}
if (!content || content.trim() === '') {
this.showError('请填写文章内容');
return;
}
this.setData({ submitting: true });
// 构建提交数据 - tags 已经是字符串格式
const postData = {
title: this.data.formData.title,
summary: this.data.formData.summary || '',
categoryName: this.data.formData.categoryName,
tags: this.data.formData.tags, // 已经是 "传染病,疫苗" 格式
content: this.data.formData.content
};
console.log('提交数据:', postData); // 调试用
http.shareAdd({
data: postData,
success: (res) => {
if(res.code == 200){
wx.showToast({
title: '发布成功',
icon: 'success',
duration: 2000,
success: () => {
setTimeout(() => {
wx.navigateBack();
}, 1500);
}
})
}else{
console.error('发布失败', err);
this.showError('发布失败,请重试');
this.setData({ submitting: false });
}
},
fail: (err) => {
console.error('发布失败', err);
this.showError('发布失败,请重试');
this.setData({ submitting: false });
},
complete: () => {
setTimeout(() => {
this.setData({ submitting: false });
}, 3000);
}
});
},
// 错误提示
showError(msg) {
wx.showToast({
title: msg,
icon: 'none',
duration: 2000
});
}
});

4
pagesA/pages/releaseSuffer/releaseSuffer.json

@ -0,0 +1,4 @@
{
"navigationBarTitleText":"发布文章",
"usingComponents": {}
}

109
pagesA/pages/releaseSuffer/releaseSuffer.wxml

@ -0,0 +1,109 @@
<view class="page-wrapper">
<form catchsubmit="formSubmit">
<!-- 标题卡片-->
<view class="form-card">
<view class="card-header">
<text class="header-icon">📝</text>
<text class="header-title">文章标题</text>
<text class="required-badge">必填</text>
</view>
<view class="card-content no-padding">
<view class="input-wrapper">
<input type="text" placeholder="请输入吸引人的标题(最多50字)"
name="title" maxlength="50" value="{{formData.title}}"
bindinput="onInput" data-field="title"
placeholder-class="placeholder-style" />
</view>
</view>
</view>
<!-- 摘要卡片 -->
<view class="form-card">
<view class="card-header">
<text class="header-icon">📋</text>
<text class="header-title">文章摘要</text>
<text class="optional-badge">选填</text>
</view>
<view class="card-content no-padding">
<view class="textarea-wrapper">
<textarea placeholder="简单描述文章要点,让读者快速了解内容(最多200字)"
name="summary" maxlength="200" auto-height
value="{{formData.summary}}" bindinput="onInput"
data-field="summary" placeholder-class="placeholder-style" />
</view>
</view>
</view>
<!-- 分类卡片 -->
<view class="form-card">
<view class="card-header">
<text class="header-icon">📂</text>
<text class="header-title">文章分类</text>
<text class="required-badge">必填</text>
</view>
<view class="card-content">
<picker mode="selector" range="{{categoryList}}" range-key="dictLabel"
bindchange="onCategoryChange" value="{{categoryIndex}}">
<view class="picker-trigger {{categoryIndex > -1 ? 'selected' : ''}}">
<text>{{categoryIndex > -1 ? categoryList[categoryIndex].dictLabel : '请选择文章分类'}}</text>
<text class="picker-arrow">▼</text>
</view>
</picker>
</view>
</view>
<!-- 标签卡片 -->
<view class="form-card">
<view class="card-header">
<text class="header-icon">🏷️</text>
<text class="header-title">文章标签</text>
<text class="required-badge">必填</text>
</view>
<view class="card-content">
<view class="tag-group">
<block wx:for="{{tagList}}" wx:key="dictValue">
<view class="tag-item {{selectedTags.includes(item) ? 'active' : ''}}"
bindtap="toggleTag" data-item="{{item}}">
{{item.dictLabel}}
</view>
</block>
</view>
<view class="selected-tags" wx:if="{{selectedTags.length}}">
<text class="selected-label">已选标签:</text>
<view class="selected-tag-list">
<view class="selected-tag-item" wx:for="{{selectedTags}}" wx:key="index">
{{item.dictLabel}}
</view>
</view>
</view>
</view>
</view>
<!-- 内容卡片 -->
<view class="form-card content-card">
<view class="card-header">
<text class="header-icon">📄</text>
<text class="header-title">文章内容</text>
<text class="required-badge">必填</text>
</view>
<view class="card-content no-padding">
<view class="textarea-wrapper">
<textarea placeholder="开始撰写您的文章吧...(支持最多5000字)"
name="content" maxlength="5000" auto-height
value="{{formData.content}}" bindinput="onInput"
data-field="content" placeholder-class="placeholder-style"
class="content-textarea" />
</view>
</view>
</view>
<!-- 提交按钮区域 -->
<view class="submit-area">
<button form-type="submit" class="submit-btn" loading="{{submitting}}" disabled="{{submitting}}">
<text wx:if="{{!submitting}}">✨ 发布文章</text>
<text wx:else>发布中...</text>
</button>
<view class="tip-text">好的内容值得被更多人看见</view>
</view>
</form>
</view>

278
pagesA/pages/releaseSuffer/releaseSuffer.wxss

@ -0,0 +1,278 @@
.page-wrapper {
min-height: 100vh;
background: linear-gradient(135deg, #f5f7fa 0%, #e9edf5 100%);
padding: 30rpx;
box-sizing: border-box;
}
/* 卡片样式 */
.form-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 32rpx;
margin-bottom: 30rpx;
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.05), 0 4rpx 12rpx rgba(0, 0, 0, 0.03);
overflow: hidden;
border: 2rpx solid rgba(255, 255, 255, 0.8);
transition: all 0.3s ease;
}
/* 卡片头部 */
.card-header {
padding: 28rpx 32rpx;
background: linear-gradient(90deg, #ffffff, #fafcff);
border-bottom: 2rpx solid rgba(7, 193, 96, 0.1);
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 20rpx;
}
.header-icon {
font-size: 36rpx;
line-height: 1;
filter: drop-shadow(0 4rpx 6rpx rgba(7, 193, 96, 0.2));
}
.header-title {
font-size: 32rpx;
font-weight: 600;
color: #1a2b3c;
letter-spacing: 1rpx;
}
/* 徽章样式 */
.required-badge {
background: linear-gradient(135deg, #ff6b6b, #ff4757);
color: white;
font-size: 22rpx;
padding: 4rpx 16rpx;
border-radius: 30rpx;
margin-left: 16rpx;
box-shadow: 0 4rpx 10rpx rgba(255, 71, 87, 0.3);
}
.optional-badge {
background: linear-gradient(135deg, #a0a0a0, #808080);
color: white;
font-size: 22rpx;
padding: 4rpx 16rpx;
border-radius: 30rpx;
margin-left: 16rpx;
opacity: 0.8;
}
/* 卡片内容 */
.card-content {
padding: 0 32rpx 32rpx 32rpx;
}
.card-content.no-padding {
padding: 0;
}
/* 输入框包装器 */
.input-wrapper,
.textarea-wrapper {
background: #f8fafd;
border-radius: 24rpx;
margin: 0 32rpx 32rpx 32rpx;
border: 2rpx solid transparent;
transition: all 0.3s ease;
box-shadow: inset 0 2rpx 6rpx rgba(0, 0, 0, 0.02);
overflow: hidden;
}
.input-wrapper:focus-within,
.textarea-wrapper:focus-within {
border-color: #07c160;
background: #ffffff;
box-shadow: 0 0 0 6rpx rgba(7, 193, 96, 0.1), inset 0 2rpx 6rpx rgba(0, 0, 0, 0.02);
}
/* 输入框样式 */
input, textarea {
width: 100%;
font-size: 30rpx;
color: #1e293b;
padding: 24rpx 28rpx;
background: transparent;
border: none;
outline: none;
}
textarea {
min-height: 120rpx;
line-height: 1.6;
}
.placeholder-style {
color: #aab8c5;
font-size: 28rpx;
}
/* 分类选择器 */
.picker-trigger {
background: #f8fafd;
padding: 24rpx 28rpx;
border-radius: 24rpx;
font-size: 30rpx;
color: #aab8c5;
display: flex;
justify-content: space-between;
align-items: center;
border: 2rpx solid transparent;
transition: all 0.3s ease;
box-shadow: inset 0 2rpx 6rpx rgba(0, 0, 0, 0.02);
}
.picker-trigger.selected {
color: #1e293b;
border-color: #07c160;
background: #ffffff;
}
.picker-arrow {
font-size: 28rpx;
color: #94a3b8;
transition: transform 0.3s ease;
}
/* 标签组 */
.tag-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 24rpx;
}
.tag-item {
padding: 16rpx 36rpx;
background: #f1f5f9;
border-radius: 60rpx;
font-size: 28rpx;
color: #475569;
border: 2rpx solid #e2e8f0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.02);
}
.tag-item.active {
background: linear-gradient(135deg, #07c160, #059669);
color: white;
border-color: #07c160;
transform: translateY(-2rpx);
box-shadow: 0 10rpx 20rpx rgba(7, 193, 96, 0.3);
}
/* 已选标签区域 */
.selected-tags {
margin-top: 24rpx;
padding: 24rpx;
background: linear-gradient(135deg, #f0fdf4, #dcfce7);
border-radius: 24rpx;
border: 2rpx solid rgba(7, 193, 96, 0.2);
}
.selected-label {
font-size: 26rpx;
color: #059669;
font-weight: 500;
display: block;
margin-bottom: 16rpx;
}
.selected-tag-list {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
margin-bottom: 16rpx;
}
.selected-tag-item {
padding: 10rpx 28rpx;
background: white;
border-radius: 40rpx;
font-size: 26rpx;
color: #07c160;
border: 2rpx solid #07c160;
box-shadow: 0 4rpx 10rpx rgba(7, 193, 96, 0.1);
}
/* 标签字符串预览 */
.tag-string-preview {
font-size: 26rpx;
color: #475569;
padding: 16rpx;
background: rgba(255, 255, 255, 0.7);
border-radius: 16rpx;
border: 2rpx dashed #07c160;
}
.tag-string-value {
color: #07c160;
font-weight: 500;
word-break: break-all;
}
/* 内容区域特殊样式 */
.content-card .content-textarea {
min-height: 300rpx;
}
/* 提交区域 */
.submit-area {
margin-top: 60rpx;
padding-bottom: 40rpx;
text-align: center;
}
.submit-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #07c160, #059669);
border-radius: 60rpx;
color: white;
font-size: 36rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
border: none;
box-shadow: 0 20rpx 40rpx rgba(7, 193, 96, 0.3);
transition: all 0.3s ease;
}
.submit-btn:active {
transform: translateY(-4rpx);
box-shadow: 0 30rpx 50rpx rgba(7, 193, 96, 0.4);
}
.submit-btn[disabled] {
opacity: 0.7;
transform: none;
box-shadow: 0 10rpx 20rpx rgba(7, 193, 96, 0.2);
}
.tip-text {
margin-top: 24rpx;
font-size: 26rpx;
color: #94a3b8;
letter-spacing: 2rpx;
}
/* 动画效果 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.form-card {
animation: fadeIn 0.4s ease-out forwards;
}

7
pagesB/pages/experienceList/experienceList.js

@ -107,6 +107,13 @@ Page({
}) })
}, },
//发布文章
bindPublish(){
wx.navigateTo({
url: '/pagesA/pages/releaseSuffer/releaseSuffer',
})
},
// 处理搜索输入(带防抖) // 处理搜索输入(带防抖)
onSearchInput(e) { onSearchInput(e) {
const searchText = e.detail.value const searchText = e.detail.value

8
pagesB/pages/experienceList/experienceList.wxml

@ -57,6 +57,14 @@
</view> </view>
</view> </view>
<!-- 新增气泡按钮 -->
<view class="create-btn-container" bind:tap="bindPublish">
<view class="create-btn" bindtap="showCreateModal">
<image class="btn-icon" src="/pagesA/images/jh.png"></image>
<text class="btn-text">发布</text>
</view>
</view>
<!-- 加载更多 --> <!-- 加载更多 -->
<view wx:if="{{!loading && hasMore}}" class="load-more" bindtap="loadMoreData"> <view wx:if="{{!loading && hasMore}}" class="load-more" bindtap="loadMoreData">
<text class="load-more-text">点击加载更多</text> <text class="load-more-text">点击加载更多</text>

61
pagesB/pages/experienceList/experienceList.wxss

@ -204,6 +204,67 @@
color: #ccc; color: #ccc;
flex-shrink: 0; flex-shrink: 0;
} }
/* 新增视频气泡按钮 */
.create-btn-container {
position: fixed;
bottom: 40rpx;
right: 15rpx;
z-index: 100;
}
.create-btn {
width: 120rpx;
height: 120rpx;
background: linear-gradient(135deg, #6D9EFF 0%, #4A7CFF 100%);
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 32rpx rgba(74, 144, 226, 0.3);
transition: all 0.3s cubic-bezier(0.2, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.create-btn::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.1);
opacity: 0;
transition: opacity 0.2s ease;
}
.create-btn:active {
transform: scale(0.95);
box-shadow: 0 4rpx 20rpx rgba(74, 144, 226, 0.4);
}
.create-btn:active::after {
opacity: 1;
}
.btn-icon {
width: 40rpx;
height: 40rpx;
margin-bottom: 10rpx;
}
.btn-text {
font-size: 26rpx;
color: white;
font-weight: 600;
letter-spacing: 0.5rpx;
}
/* 空状态 */ /* 空状态 */
.empty-state { .empty-state {

10
utils/api.js

@ -206,6 +206,14 @@ function experiencezd(params) {
http('/vet/article/options', 'get', params) http('/vet/article/options', 'get', params)
} }
// 新增经验分享
function shareAdd(params) {
http('/vet/article', 'post', params)
}
// 实名认证 // 实名认证
function realName(params) { function realName(params) {
http('/muhu/user/auth/submit', 'post', params) http('/muhu/user/auth/submit', 'post', params)
@ -233,7 +241,7 @@ function today(params) {
export default { // 暴露接口 export default { // 暴露接口
login,carousel,disaster,pharmacy,guidance,getPhoneNumber,inquiry,policyeDetails,
login,carousel,disaster,pharmacy,guidance,getPhoneNumber,inquiry,policyeDetails,shareAdd,
search,trend,feed,sales,wzd,wzdxq,wzdAdd,expertsList,recommendationList,policyeZd, search,trend,feed,sales,wzd,wzdxq,wzdAdd,expertsList,recommendationList,policyeZd,
recommendationXq,queryList,tipList,article,articleDetails,articleZd,policyelucidation, recommendationXq,queryList,tipList,article,articleDetails,articleZd,policyelucidation,
areaChildren,userCode,UserInfo,videoList,videoZd,videoDetails,forumList,forumAdd,forumDetails, areaChildren,userCode,UserInfo,videoList,videoZd,videoDetails,forumList,forumAdd,forumDetails,

Loading…
Cancel
Save