|
@@ -3,23 +3,14 @@
|
|
|
<view class="section">
|
|
<view class="section">
|
|
|
<view class="section-title">我的画像描述</view>
|
|
<view class="section-title">我的画像描述</view>
|
|
|
<view class="hint">请输入你的个人画像描述,AI 会根据这些信息提供更有针对性的建议(最多 2000 字)</view>
|
|
<view class="hint">请输入你的个人画像描述,AI 会根据这些信息提供更有针对性的建议(最多 2000 字)</view>
|
|
|
-
|
|
|
|
|
- <!-- 操作按钮行 -->
|
|
|
|
|
- <view class="action-row">
|
|
|
|
|
- <button class="action-btn" :loading="generating" @click="onGenerate" v-if="!portraitPrompt">
|
|
|
|
|
- 🪄 AI 生成画像
|
|
|
|
|
- </button>
|
|
|
|
|
- <button class="action-btn secondary" :loading="regenerating" @click="onRegenerate" v-if="portraitPrompt">
|
|
|
|
|
- 🔄 重画画像
|
|
|
|
|
- </button>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<textarea
|
|
<textarea
|
|
|
class="portrait-textarea"
|
|
class="portrait-textarea"
|
|
|
:value="portraitPrompt"
|
|
:value="portraitPrompt"
|
|
|
placeholder="例如:我家孩子 8 岁,偏瘦,挑食,容易积食,睡眠不足..."
|
|
placeholder="例如:我家孩子 8 岁,偏瘦,挑食,容易积食,睡眠不足..."
|
|
|
maxlength="2000"
|
|
maxlength="2000"
|
|
|
@input="onInput"
|
|
@input="onInput"
|
|
|
|
|
+ auto-height
|
|
|
></textarea>
|
|
></textarea>
|
|
|
<view class="char-count">{{ portraitPrompt.length }}/2000</view>
|
|
<view class="char-count">{{ portraitPrompt.length }}/2000</view>
|
|
|
</view>
|
|
</view>
|
|
@@ -28,21 +19,21 @@
|
|
|
<view class="section-title">参考指标(自动生成)</view>
|
|
<view class="section-title">参考指标(自动生成)</view>
|
|
|
<view class="snapshot-text">{{ renderedSnapshot }}</view>
|
|
<view class="snapshot-text">{{ renderedSnapshot }}</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
|
|
|
|
|
+ <view class="save-bar">
|
|
|
<button class="save-btn" :loading="saving" @click="onSave">保存</button>
|
|
<button class="save-btn" :loading="saving" @click="onSave">保存</button>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { getPortrait, editPortrait, generatePortrait, regeneratePortrait } from '../../utils/api.js'
|
|
|
|
|
|
|
+import { getPortrait, editPortrait } from '../../utils/api.js'
|
|
|
export default {
|
|
export default {
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
portraitPrompt: '',
|
|
portraitPrompt: '',
|
|
|
renderedSnapshot: '',
|
|
renderedSnapshot: '',
|
|
|
- saving: false,
|
|
|
|
|
- generating: false,
|
|
|
|
|
- regenerating: false
|
|
|
|
|
|
|
+ saving: false
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
onLoad() {
|
|
onLoad() {
|
|
@@ -63,45 +54,6 @@ export default {
|
|
|
onInput(e) {
|
|
onInput(e) {
|
|
|
this.portraitPrompt = e.detail.value
|
|
this.portraitPrompt = e.detail.value
|
|
|
},
|
|
},
|
|
|
- async onGenerate() {
|
|
|
|
|
- this.generating = true
|
|
|
|
|
- try {
|
|
|
|
|
- const memberId = this.$store.state.currentMemberId
|
|
|
|
|
- const res = await generatePortrait({ memberId })
|
|
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
|
|
- this.portraitPrompt = res.data.portraitPrompt || ''
|
|
|
|
|
- this.renderedSnapshot = res.data.renderedSnapshot || ''
|
|
|
|
|
- uni.showToast({ title: '生成成功', icon: 'success' })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: res.message || '生成失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- uni.showToast({ title: '生成失败', icon: 'none' })
|
|
|
|
|
- } finally {
|
|
|
|
|
- this.generating = false
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- async onRegenerate() {
|
|
|
|
|
- this.regenerating = true
|
|
|
|
|
- try {
|
|
|
|
|
- const memberId = this.$store.state.currentMemberId
|
|
|
|
|
- const res = await regeneratePortrait({
|
|
|
|
|
- memberId,
|
|
|
|
|
- previousPortrait: this.portraitPrompt // 传入当前画像作为参考
|
|
|
|
|
- })
|
|
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
|
|
- this.portraitPrompt = res.data.portraitPrompt || ''
|
|
|
|
|
- this.renderedSnapshot = res.data.renderedSnapshot || ''
|
|
|
|
|
- uni.showToast({ title: '重画成功', icon: 'success' })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: res.message || '重画失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- uni.showToast({ title: '重画失败', icon: 'none' })
|
|
|
|
|
- } finally {
|
|
|
|
|
- this.regenerating = false
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
async onSave() {
|
|
async onSave() {
|
|
|
this.saving = true
|
|
this.saving = true
|
|
|
try {
|
|
try {
|
|
@@ -125,8 +77,10 @@ export default {
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
.portrait-edit-page {
|
|
.portrait-edit-page {
|
|
|
padding: 24rpx;
|
|
padding: 24rpx;
|
|
|
|
|
+ padding-bottom: 160rpx;
|
|
|
min-height: 100vh;
|
|
min-height: 100vh;
|
|
|
background: #f5f5f5;
|
|
background: #f5f5f5;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
}
|
|
|
.section {
|
|
.section {
|
|
|
background: #fff;
|
|
background: #fff;
|
|
@@ -145,25 +99,9 @@ export default {
|
|
|
color: #999;
|
|
color: #999;
|
|
|
margin-bottom: 16rpx;
|
|
margin-bottom: 16rpx;
|
|
|
}
|
|
}
|
|
|
-.action-row {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 16rpx;
|
|
|
|
|
- margin-bottom: 16rpx;
|
|
|
|
|
-}
|
|
|
|
|
-.action-btn {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- height: 72rpx;
|
|
|
|
|
- border-radius: 36rpx;
|
|
|
|
|
- font-size: 26rpx;
|
|
|
|
|
- background: linear-gradient(135deg, #667eea, #764ba2);
|
|
|
|
|
- color: #fff;
|
|
|
|
|
-}
|
|
|
|
|
-.action-btn.secondary {
|
|
|
|
|
- background: linear-gradient(135deg, #F97316, #F59E0B);
|
|
|
|
|
-}
|
|
|
|
|
.portrait-textarea {
|
|
.portrait-textarea {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
- height: 300rpx;
|
|
|
|
|
|
|
+ min-height: 500rpx;
|
|
|
border: 1rpx solid #eee;
|
|
border: 1rpx solid #eee;
|
|
|
border-radius: 8rpx;
|
|
border-radius: 8rpx;
|
|
|
padding: 16rpx;
|
|
padding: 16rpx;
|
|
@@ -183,6 +121,18 @@ export default {
|
|
|
white-space: pre-wrap;
|
|
white-space: pre-wrap;
|
|
|
line-height: 1.6;
|
|
line-height: 1.6;
|
|
|
}
|
|
}
|
|
|
|
|
+.save-bar {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
|
|
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.08);
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ z-index: 100;
|
|
|
|
|
+}
|
|
|
.save-btn {
|
|
.save-btn {
|
|
|
background: #F97316;
|
|
background: #F97316;
|
|
|
color: #fff;
|
|
color: #fff;
|
|
@@ -190,6 +140,5 @@ export default {
|
|
|
height: 88rpx;
|
|
height: 88rpx;
|
|
|
line-height: 88rpx;
|
|
line-height: 88rpx;
|
|
|
font-size: 32rpx;
|
|
font-size: 32rpx;
|
|
|
- margin-top: 32rpx;
|
|
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|