|
|
@@ -0,0 +1,359 @@
|
|
|
+<template>
|
|
|
+ <view class="edit-container">
|
|
|
+ <!-- 自定义导航 -->
|
|
|
+ <view class="edit-header">
|
|
|
+ <view class="header-left" @click="onBack">
|
|
|
+ <text class="back-icon">←</text>
|
|
|
+ <text class="back-text">返回</text>
|
|
|
+ </view>
|
|
|
+ <text class="header-title">写成长记录</text>
|
|
|
+ <view class="header-right" @click="goMyPosts">
|
|
|
+ <text class="history-text">历史</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <scroll-view scroll-y class="edit-form">
|
|
|
+ <!-- 封面图 -->
|
|
|
+ <view class="form-cover" @click="chooseCover">
|
|
|
+ <image v-if="coverImage" :src="coverImage" mode="aspectFill" class="cover-preview" />
|
|
|
+ <view v-else class="cover-placeholder">
|
|
|
+ <text class="cover-icon">📷</text>
|
|
|
+ <text class="cover-hint">添加封面</text>
|
|
|
+ </view>
|
|
|
+ <view v-if="coverImage" class="cover-change" @click.stop="chooseCover">
|
|
|
+ <text class="change-text">更换</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 标题 -->
|
|
|
+ <view class="form-group">
|
|
|
+ <input
|
|
|
+ class="form-input title-input"
|
|
|
+ v-model="title"
|
|
|
+ placeholder="给这篇记录取个标题"
|
|
|
+ maxlength="50"
|
|
|
+ />
|
|
|
+ <text class="char-count">{{ title.length }}/50</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 维度选择 -->
|
|
|
+ <view class="form-group">
|
|
|
+ <text class="form-label">关联维度(选填)</text>
|
|
|
+ <view class="dimension-chips">
|
|
|
+ <view
|
|
|
+ v-for="dim in dimensionList"
|
|
|
+ :key="dim.code"
|
|
|
+ :class="['dim-chip', selectedDimensions.indexOf(dim.code) >= 0 ? 'active' : '']"
|
|
|
+ :style="selectedDimensions.indexOf(dim.code) >= 0 ? { background: dim.color, color: '#fff', borderColor: dim.color } : {}"
|
|
|
+ @click="toggleDimension(dim.code)"
|
|
|
+ >
|
|
|
+ {{ dim.name }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 正文 -->
|
|
|
+ <view class="form-group">
|
|
|
+ <textarea
|
|
|
+ class="form-textarea"
|
|
|
+ v-model="content"
|
|
|
+ placeholder="记录孩子的成长点滴..."
|
|
|
+ maxlength="2000"
|
|
|
+ />
|
|
|
+ <text class="char-count">{{ content.length }}/2000</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 可见范围 -->
|
|
|
+ <view class="form-group">
|
|
|
+ <text class="form-label">可见范围</text>
|
|
|
+ <view class="visibility-options">
|
|
|
+ <view
|
|
|
+ :class="['vis-option', visibility === 'private' ? 'active' : '']"
|
|
|
+ @click="visibility = 'private'"
|
|
|
+ >
|
|
|
+ <text class="vis-icon">🏠</text>
|
|
|
+ <text class="vis-text">仅家庭</text>
|
|
|
+ <text class="vis-desc">仅家庭成员可见</text>
|
|
|
+ </view>
|
|
|
+ <view
|
|
|
+ :class="['vis-option', visibility === 'public' ? 'active' : '']"
|
|
|
+ @click="visibility = 'public'"
|
|
|
+ >
|
|
|
+ <text class="vis-icon">🌍</text>
|
|
|
+ <text class="vis-text">公开发布</text>
|
|
|
+ <text class="vis-desc">所有人可见,需审核</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 发布按钮 -->
|
|
|
+ <button class="publish-btn" :disabled="!canPublish" @click="onPublish">
|
|
|
+ {{ publishing ? '发布中...' : '发布' }}
|
|
|
+ </button>
|
|
|
+ <view style="height: 60rpx;"></view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { publishArticle } from '@/utils/api.js'
|
|
|
+import config from '@/config.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ title: '',
|
|
|
+ coverImage: '',
|
|
|
+ content: '',
|
|
|
+ visibility: 'private',
|
|
|
+ selectedDimensions: [],
|
|
|
+ publishing: false,
|
|
|
+ dimensionList: [
|
|
|
+ { code: 'body', name: '身', color: '#FF8C42' },
|
|
|
+ { code: 'mind', name: '智', color: '#6366F1' },
|
|
|
+ { code: 'wisdom', name: '心', color: '#FF6B9D' },
|
|
|
+ { code: 'action', name: '行', color: '#10B981' },
|
|
|
+ { code: 'wealth', name: '富', color: '#F59E0B' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ canPublish: function() {
|
|
|
+ return this.title.trim().length > 0 && this.content.trim().length > 0 && !this.publishing
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ chooseCover() {
|
|
|
+ var self = this
|
|
|
+ uni.chooseImage({
|
|
|
+ count: 1,
|
|
|
+ sizeType: ['compressed'],
|
|
|
+ sourceType: ['album', 'camera'],
|
|
|
+ success: function(res) {
|
|
|
+ var tempPath = res.tempFilePaths[0]
|
|
|
+ // 上传图片
|
|
|
+ var token = uni.getStorageSync('token')
|
|
|
+ uni.uploadFile({
|
|
|
+ url: (config.default && config.default.API_BASE_URL) || config.API_BASE_URL || '' + '/api/upload/image',
|
|
|
+ filePath: tempPath,
|
|
|
+ name: 'file',
|
|
|
+ header: {
|
|
|
+ 'Authorization': token ? 'Bearer ' + token : ''
|
|
|
+ },
|
|
|
+ success: function(uploadRes) {
|
|
|
+ try {
|
|
|
+ var data = JSON.parse(uploadRes.data)
|
|
|
+ if (data && data.code === 200) {
|
|
|
+ self.coverImage = data.data
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: '上传失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: '上传失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: function() {
|
|
|
+ uni.showToast({ title: '上传失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ toggleDimension(code) {
|
|
|
+ var idx = this.selectedDimensions.indexOf(code)
|
|
|
+ if (idx >= 0) {
|
|
|
+ this.selectedDimensions.splice(idx, 1)
|
|
|
+ } else {
|
|
|
+ this.selectedDimensions.push(code)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onBack() {
|
|
|
+ if (this.title || this.content) {
|
|
|
+ var self = this
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '是否保存草稿?',
|
|
|
+ success: function(res) {
|
|
|
+ if (res.confirm) {
|
|
|
+ uni.setStorageSync('article_draft', {
|
|
|
+ title: self.title,
|
|
|
+ coverImage: self.coverImage,
|
|
|
+ content: self.content,
|
|
|
+ visibility: self.visibility,
|
|
|
+ selectedDimensions: self.selectedDimensions
|
|
|
+ })
|
|
|
+ }
|
|
|
+ uni.navigateBack()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ uni.navigateBack()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ goMyPosts() {
|
|
|
+ uni.navigateTo({ url: '/pages/article-center/my-posts' })
|
|
|
+ },
|
|
|
+ async onPublish() {
|
|
|
+ if (!this.canPublish) return
|
|
|
+ this.publishing = true
|
|
|
+ try {
|
|
|
+ var res = await publishArticle({
|
|
|
+ title: this.title.trim(),
|
|
|
+ content: this.content.trim(),
|
|
|
+ coverImage: this.coverImage,
|
|
|
+ visibility: this.visibility,
|
|
|
+ relatedDimensions: this.selectedDimensions.join(',')
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ var msg = this.visibility === 'public'
|
|
|
+ ? '发布成功,等待审核'
|
|
|
+ : '发布成功,已对家庭可见'
|
|
|
+ uni.showToast({ title: msg, icon: 'success', duration: 2000 })
|
|
|
+ uni.removeStorageSync('article_draft')
|
|
|
+ var self = this
|
|
|
+ setTimeout(function() {
|
|
|
+ uni.navigateBack()
|
|
|
+ }, 1500)
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.message || '发布失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: '发布失败', icon: 'none' })
|
|
|
+ } finally {
|
|
|
+ this.publishing = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ // 加载草稿
|
|
|
+ try {
|
|
|
+ var draft = uni.getStorageSync('article_draft')
|
|
|
+ if (draft) {
|
|
|
+ this.title = draft.title || ''
|
|
|
+ this.coverImage = draft.coverImage || ''
|
|
|
+ this.content = draft.content || ''
|
|
|
+ this.visibility = draft.visibility || 'private'
|
|
|
+ this.selectedDimensions = draft.selectedDimensions || []
|
|
|
+ }
|
|
|
+ } catch (e) {}
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.edit-container { min-height: 100vh; background: #f5f7fa; }
|
|
|
+.edit-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 80rpx 30rpx 20rpx;
|
|
|
+ background: #fff;
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+.header-left { display: flex; align-items: center; }
|
|
|
+.back-icon { font-size: 36rpx; margin-right: 8rpx; }
|
|
|
+.back-text { font-size: 26rpx; color: #333; }
|
|
|
+.header-title { font-size: 32rpx; font-weight: bold; color: #333; }
|
|
|
+.header-right { }
|
|
|
+.history-text { font-size: 26rpx; color: #5B9BD5; }
|
|
|
+.edit-form { padding: 20rpx 30rpx; }
|
|
|
+/* 封面 */
|
|
|
+.form-cover {
|
|
|
+ width: 100%;
|
|
|
+ height: 300rpx;
|
|
|
+ background: #eee;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+.cover-preview { width: 100%; height: 100%; }
|
|
|
+.cover-placeholder {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+.cover-icon { font-size: 60rpx; margin-bottom: 10rpx; }
|
|
|
+.cover-hint { font-size: 24rpx; color: #999; }
|
|
|
+.cover-change {
|
|
|
+ position: absolute;
|
|
|
+ right: 16rpx;
|
|
|
+ bottom: 16rpx;
|
|
|
+ background: rgba(0,0,0,0.5);
|
|
|
+ color: #fff;
|
|
|
+ padding: 6rpx 20rpx;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
+}
|
|
|
+/* 表单组 */
|
|
|
+.form-group {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ padding: 24rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+.form-input {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #333;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+}
|
|
|
+.title-input { font-weight: bold; }
|
|
|
+.char-count { display: block; text-align: right; font-size: 20rpx; color: #bbb; margin-top: 8rpx; }
|
|
|
+.form-label { font-size: 24rpx; color: #666; display: block; margin-bottom: 16rpx; }
|
|
|
+/* 维度 */
|
|
|
+.dimension-chips { display: flex; flex-wrap: wrap; gap: 16rpx; }
|
|
|
+.dim-chip {
|
|
|
+ padding: 10rpx 28rpx;
|
|
|
+ border-radius: 30rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ border: 2rpx solid #ddd;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+.dim-chip.active { color: #fff; border-color: transparent; }
|
|
|
+/* 文本框 */
|
|
|
+.form-textarea {
|
|
|
+ width: 100%;
|
|
|
+ height: 300rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ line-height: 1.6;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ resize: none;
|
|
|
+}
|
|
|
+/* 可见范围 */
|
|
|
+.visibility-options { display: flex; gap: 20rpx; }
|
|
|
+.vis-option {
|
|
|
+ flex: 1;
|
|
|
+ padding: 24rpx;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ border: 2rpx solid #eee;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.vis-option.active { border-color: #5B9BD5; background: #E8F4FD; }
|
|
|
+.vis-icon { font-size: 40rpx; display: block; margin-bottom: 8rpx; }
|
|
|
+.vis-text { font-size: 26rpx; font-weight: bold; color: #333; display: block; }
|
|
|
+.vis-desc { font-size: 20rpx; color: #999; display: block; margin-top: 4rpx; }
|
|
|
+/* 发布按钮 */
|
|
|
+.publish-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 88rpx;
|
|
|
+ line-height: 88rpx;
|
|
|
+ background: linear-gradient(135deg, #F97316, #EA580C);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ border-radius: 44rpx;
|
|
|
+ text-align: center;
|
|
|
+ border: none;
|
|
|
+ margin-top: 20rpx;
|
|
|
+}
|
|
|
+.publish-btn[disabled] { opacity: 0.4; }
|
|
|
+.publish-btn::after { border: none; }
|
|
|
+</style>
|