| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- <template>
- <view class="container">
- <view v-if="!loading" class="form-container">
- <view class="section">
- <view class="section-title">节点配置</view>
-
- <view class="form-item">
- <text class="label">任务标题</text>
- <input v-model="node.title" class="input" placeholder="请输入任务标题" />
- </view>
-
- <view class="form-item">
- <text class="label">任务描述</text>
- <textarea v-model="node.description" class="textarea" placeholder="可选,任务描述" />
- </view>
-
- <view class="form-item">
- <text class="label">积分</text>
- <input v-model="node.points" class="input" type="number" placeholder="完成此任务获得的积分" />
- </view>
-
- <view class="form-item">
- <text class="label">超时时间(分钟)</text>
- <input v-model="node.timeout_minutes" class="input" type="number" placeholder="0表示不限制" />
- <text class="hint">超过此时长未完成任务将触发超时兜底</text>
- </view>
-
- <view class="form-item">
- <text class="label">最大循环次数</text>
- <input v-model="node.max_loops" class="input" type="number" placeholder="0表示不限制" />
- <text class="hint">达到上限后节点自动终止</text>
- </view>
-
- <view class="form-item">
- <text class="label">执行人</text>
- <picker :range="executorTypes" @change="onExecutorChange">
- <view class="picker">{{ executorLabels[node.executorType] || '请选择' }}</view>
- </picker>
- </view>
-
- <view class="form-item" v-if="node.executorType === 'member'">
- <text class="label">分配给</text>
- <checkbox-group @change="onMemberChange">
- <label v-for="m in members" :key="m.id" class="checkbox-label">
- <checkbox :value="String(m.id)" :checked="selectedMembers.indexOf(m.id) >= 0" />
- <text>{{ m.nickname }}</text>
- </label>
- </checkbox-group>
- </view>
- </view>
-
- <view class="action-bar">
- <button class="btn-save" @click="handleSave">保存</button>
- </view>
- </view>
-
- <view v-if="loading" class="loading">
- <text>加载中...</text>
- </view>
- </view>
- </template>
- <script>
- import { getFamilyMemberList } from '../../utils/api.js'
- export default {
- data() {
- return {
- nodeId: null,
- node: {
- title: '',
- description: '',
- points: 2,
- timeout_minutes: 0,
- max_loops: 0,
- executorType: 'child'
- },
- members: [],
- selectedMembers: [],
- executorTypes: ['child', 'member'],
- executorLabels: { child: '孩子', member: '家庭成员' },
- loading: false
- }
- },
- onLoad(options) {
- this.nodeId = options.id
- // 初始化节点数据(从页面参数或父组件传递)
- if (options.nodeData) {
- try {
- this.node = JSON.parse(decodeURIComponent(options.nodeData))
- } catch (e) {
- console.error('解析节点数据失败', e)
- }
- }
- this.loadMembers()
- },
- methods: {
- async loadMembers() {
- try {
- var res = await getFamilyMemberList({})
- this.members = res.data || []
- } catch (e) {
- console.error('加载成员列表失败', e)
- }
- },
- onExecutorChange(e) {
- var idx = e.detail.value
- this.node.executorType = this.executorTypes[idx]
- },
- onMemberChange(e) {
- this.selectedMembers = e.detail.value.map(Number)
- },
- handleSave() {
- // 返回上一页并传递节点数据
- var pages = getCurrentPages()
- if (pages.length > 1) {
- var prevPage = pages[pages.length - 2]
- prevPage.$vm.updateNode(this.nodeId, this.node)
- }
- uni.navigateBack()
- }
- }
- }
- </script>
- <style scoped>
- .container {
- min-height: 100vh;
- background: #F8F8F8;
- }
- .loading {
- text-align: center;
- padding: 100rpx;
- color: #94A3B8;
- }
- .form-container {
- padding: 30rpx;
- }
- .section {
- background: #fff;
- border-radius: 16rpx;
- padding: 30rpx;
- margin-bottom: 24rpx;
- }
- .section-title {
- font-size: 28rpx;
- font-weight: bold;
- color: #1E293B;
- margin-bottom: 24rpx;
- }
- .form-item {
- margin-bottom: 24rpx;
- }
- .label {
- display: block;
- font-size: 26rpx;
- color: #64748B;
- margin-bottom: 12rpx;
- }
- .input {
- width: 100%;
- height: 80rpx;
- border: 2rpx solid #E2E8F0;
- border-radius: 12rpx;
- padding: 0 20rpx;
- font-size: 28rpx;
- box-sizing: border-box;
- }
- .textarea {
- width: 100%;
- height: 160rpx;
- border: 2rpx solid #E2E8F0;
- border-radius: 12rpx;
- padding: 20rpx;
- font-size: 28rpx;
- box-sizing: border-box;
- }
- .picker {
- width: 100%;
- height: 80rpx;
- border: 2rpx solid #E2E8F0;
- border-radius: 12rpx;
- padding: 0 20rpx;
- font-size: 28rpx;
- line-height: 80rpx;
- }
- .hint {
- display: block;
- font-size: 22rpx;
- color: #94A3B8;
- margin-top: 8rpx;
- }
- .checkbox-label {
- display: flex;
- align-items: center;
- padding: 16rpx 0;
- }
- .action-bar {
- padding: 30rpx;
- }
- .btn-save {
- width: 100%;
- height: 88rpx;
- line-height: 88rpx;
- border-radius: 44rpx;
- font-size: 30rpx;
- font-weight: bold;
- background: linear-gradient(135deg, #F97316 0%, #EA580C 100%);
- color: #fff;
- border: none;
- }
- .btn-save::after { border: none; }
- </style>
|