|
@@ -1,113 +1,227 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <view class="container">
|
|
|
|
|
- <view class="form-container">
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">任务名称</text>
|
|
|
|
|
- <input class="input" v-model="form.title" placeholder="请输入任务名称" />
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">任务描述</text>
|
|
|
|
|
- <textarea class="textarea" v-model="form.description" placeholder="请输入任务描述" />
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">选择孩子</text>
|
|
|
|
|
- <picker :range="children" range-key="nickname" @change="onChildChange">
|
|
|
|
|
- <view class="picker">
|
|
|
|
|
- {{ selectedChild ? selectedChild.nickname : '请选择孩子' }}
|
|
|
|
|
- </view>
|
|
|
|
|
- </picker>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">积分</text>
|
|
|
|
|
- <input class="input" type="number" v-model="form.points" placeholder="请输入积分" />
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">分类</text>
|
|
|
|
|
- <picker :range="categories" @change="onCategoryChange">
|
|
|
|
|
- <view class="picker">
|
|
|
|
|
- {{ form.category || '请选择分类' }}
|
|
|
|
|
- </view>
|
|
|
|
|
- </picker>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <view class="form-item">
|
|
|
|
|
- <text class="label">需要审核</text>
|
|
|
|
|
- <switch :checked="form.needReview" @change="form.needReview = !form.needReview" />
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
- <button class="btn-primary" @click="submit">创建任务</button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
|
|
+<view class="container">
|
|
|
|
|
+<view class="form-container">
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">任务名称</text>
|
|
|
|
|
+<input class="input" v-model="form.title" placeholder="请输入任务名称" />
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">任务描述</text>
|
|
|
|
|
+<textarea class="textarea" v-model="form.description" placeholder="请输入任务描述" />
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">选择孩子</text>
|
|
|
|
|
+<picker :range="children" range-key="nickname" @change="onChildChange">
|
|
|
|
|
+<view class="picker">
|
|
|
|
|
+{{ selectedChild ? selectedChild.nickname : '请选择孩子' }}
|
|
|
|
|
+</view>
|
|
|
|
|
+</picker>
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">积分</text>
|
|
|
|
|
+<input class="input" type="number" v-model="form.points" placeholder="请输入积分 (1-10)" />
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">分类</text>
|
|
|
|
|
+<picker :range="categories" @change="onCategoryChange">
|
|
|
|
|
+<view class="picker">
|
|
|
|
|
+{{ form.category || '请选择分类' }}
|
|
|
|
|
+</view>
|
|
|
|
|
+</picker>
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<!-- TASK-003: 截止时间设置 -->
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">截止时间</text>
|
|
|
|
|
+<picker mode="multiSelector" :range="dateTimeRange" :value="dateTimeIndex" @change="onDateTimeChange" @columnchange="onColumnChange">
|
|
|
|
|
+<view class="picker">
|
|
|
|
|
+{{ deadlineText || '请选择截止时间' }}
|
|
|
|
|
+</view>
|
|
|
|
|
+</picker>
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<!-- TASK-004: 重复设置 -->
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">重复设置</text>
|
|
|
|
|
+<picker :range="repeatTypes" range-key="label" @change="onRepeatChange">
|
|
|
|
|
+<view class="picker">
|
|
|
|
|
+{{ repeatTypeLabel || '不重复' }}
|
|
|
|
|
+</view>
|
|
|
|
|
+</picker>
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<view class="form-item">
|
|
|
|
|
+<text class="label">需要审核</text>
|
|
|
|
|
+<switch :checked="form.needReview" @change="onNeedReviewChange" />
|
|
|
|
|
+</view>
|
|
|
|
|
+
|
|
|
|
|
+<button class="btn-primary" @click="submit">创建任务</button>
|
|
|
|
|
+</view>
|
|
|
|
|
+</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import { getChildren, createTask } from '../../utils/api.js'
|
|
import { getChildren, createTask } from '../../utils/api.js'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
- data() {
|
|
|
|
|
- return {
|
|
|
|
|
- form: {
|
|
|
|
|
- title: '',
|
|
|
|
|
- description: '',
|
|
|
|
|
- childId: '',
|
|
|
|
|
- points: 2,
|
|
|
|
|
- category: '',
|
|
|
|
|
- needReview: false
|
|
|
|
|
- },
|
|
|
|
|
- children: [],
|
|
|
|
|
- selectedChild: null,
|
|
|
|
|
- categories: ['学习', '生活', '运动', '其他']
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- onLoad() {
|
|
|
|
|
- this.loadChildren()
|
|
|
|
|
- },
|
|
|
|
|
- methods: {
|
|
|
|
|
- async loadChildren() {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await getChildren()
|
|
|
|
|
- this.children = res.data || []
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error(e)
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- onChildChange(e) {
|
|
|
|
|
- this.selectedChild = this.children[e.detail.value]
|
|
|
|
|
- this.form.childId = this.selectedChild.id
|
|
|
|
|
- },
|
|
|
|
|
- onCategoryChange(e) {
|
|
|
|
|
- this.form.category = this.categories[e.detail.value]
|
|
|
|
|
- },
|
|
|
|
|
- async submit() {
|
|
|
|
|
- if (!this.form.title) {
|
|
|
|
|
- uni.showToast({ title: '请输入任务名称', icon: 'none' })
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- if (!this.form.childId) {
|
|
|
|
|
- uni.showToast({ title: '请选择孩子', icon: 'none' })
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- await createTask({
|
|
|
|
|
- title: this.form.title,
|
|
|
|
|
- description: this.form.description,
|
|
|
|
|
- childId: this.form.childId,
|
|
|
|
|
- points: parseInt(this.form.points) || 2,
|
|
|
|
|
- category: this.form.category || '其他',
|
|
|
|
|
- needReview: this.form.needReview ? 1 : 0
|
|
|
|
|
- })
|
|
|
|
|
- uni.showToast({ title: '创建成功', icon: 'success' })
|
|
|
|
|
- setTimeout(() => uni.navigateBack(), 1500)
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- uni.showToast({ title: '创建失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+data() {
|
|
|
|
|
+return {
|
|
|
|
|
+form: {
|
|
|
|
|
+title: '',
|
|
|
|
|
+description: '',
|
|
|
|
|
+childId: '',
|
|
|
|
|
+points: 2,
|
|
|
|
|
+category: '',
|
|
|
|
|
+deadline: null,
|
|
|
|
|
+repeatType: 'none',
|
|
|
|
|
+needReview: false
|
|
|
|
|
+},
|
|
|
|
|
+children: [],
|
|
|
|
|
+selectedChild: null,
|
|
|
|
|
+categories: ['学习类', '生活类', '运动类', '其他'],
|
|
|
|
|
+repeatTypes: [
|
|
|
|
|
+{ value: 'none', label: '不重复' },
|
|
|
|
|
+{ value: 'daily', label: '每天' },
|
|
|
|
|
+{ value: 'weekly', label: '每周' }
|
|
|
|
|
+],
|
|
|
|
|
+dateTimeRange: [[], [], [], []],
|
|
|
|
|
+dateTimeIndex: [0, 0, 0, 0],
|
|
|
|
|
+deadlineText: ''
|
|
|
|
|
+}
|
|
|
|
|
+},
|
|
|
|
|
+onLoad() {
|
|
|
|
|
+this.loadChildren()
|
|
|
|
|
+this.initDateTimePicker()
|
|
|
|
|
+},
|
|
|
|
|
+methods: {
|
|
|
|
|
+async loadChildren() {
|
|
|
|
|
+try {
|
|
|
|
|
+const res = await getChildren()
|
|
|
|
|
+this.children = res.data || []
|
|
|
|
|
+} catch (e) {
|
|
|
|
|
+console.error(e)
|
|
|
|
|
+}
|
|
|
|
|
+},
|
|
|
|
|
+initDateTimePicker() {
|
|
|
|
|
+// 初始化日期时间选择器
|
|
|
|
|
+const now = new Date()
|
|
|
|
|
+const year = now.getFullYear()
|
|
|
|
|
+const month = now.getMonth() + 1
|
|
|
|
|
+const day = now.getDate()
|
|
|
|
|
+const hour = now.getHours()
|
|
|
|
|
+const minute = now.getMinutes()
|
|
|
|
|
+
|
|
|
|
|
+// 年(当前年份+未来2年)
|
|
|
|
|
+const years = []
|
|
|
|
|
+for (let i = year; i <= year + 2; i++) {
|
|
|
|
|
+years.push(i + '年')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 月
|
|
|
|
|
+const months = []
|
|
|
|
|
+for (let i = 1; i <= 12; i++) {
|
|
|
|
|
+months.push(i + '月')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 日
|
|
|
|
|
+const days = []
|
|
|
|
|
+const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
|
|
+for (let i = 1; i <= daysInMonth; i++) {
|
|
|
|
|
+days.push(i + '日')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 时
|
|
|
|
|
+const hours = []
|
|
|
|
|
+for (let i = 0; i < 24; i++) {
|
|
|
|
|
+hours.push(i.toString().padStart(2, '0') + '时')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 分
|
|
|
|
|
+const minutes = []
|
|
|
|
|
+for (let i = 0; i < 60; i += 5) {
|
|
|
|
|
+minutes.push(i.toString().padStart(2, '0') + '分')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+this.dateTimeRange = [years, months, days, hours, minutes]
|
|
|
|
|
+},
|
|
|
|
|
+onChildChange(e) {
|
|
|
|
|
+this.selectedChild = this.children[e.detail.value]
|
|
|
|
|
+this.form.childId = this.selectedChild.id
|
|
|
|
|
+},
|
|
|
|
|
+onCategoryChange(e) {
|
|
|
|
|
+this.form.category = this.categories[e.detail.value]
|
|
|
|
|
+},
|
|
|
|
|
+onDateTimeChange(e) {
|
|
|
|
|
+const vals = e.detail.value
|
|
|
|
|
+this.dateTimeIndex = vals
|
|
|
|
|
+
|
|
|
|
|
+const now = new Date()
|
|
|
|
|
+const year = now.getFullYear() + vals[0]
|
|
|
|
|
+const month = vals[1] + 1
|
|
|
|
|
+const day = vals[2] + 1
|
|
|
|
|
+const hour = vals[3]
|
|
|
|
|
+const minute = vals[4] * 5
|
|
|
|
|
+
|
|
|
|
|
+this.deadlineText = `${year}年${month}月${day}日 ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`
|
|
|
|
|
+this.form.deadline = new Date(year, month - 1, day, hour, minute)
|
|
|
|
|
+},
|
|
|
|
|
+onColumnChange(e) {
|
|
|
|
|
+// 处理月份变化时更新天数
|
|
|
|
|
+if (e.detail.column === 1) {
|
|
|
|
|
+const month = e.detail.value + 1
|
|
|
|
|
+const now = new Date()
|
|
|
|
|
+const year = now.getFullYear() + this.dateTimeIndex[0]
|
|
|
|
|
+const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
|
|
+const days = []
|
|
|
|
|
+for (let i = 1; i <= daysInMonth; i++) {
|
|
|
|
|
+days.push(i + '日')
|
|
|
|
|
+}
|
|
|
|
|
+this.$set(this.dateTimeRange, 2, days)
|
|
|
|
|
+}
|
|
|
|
|
+},
|
|
|
|
|
+onRepeatChange(e) {
|
|
|
|
|
+const selected = this.repeatTypes[e.detail.value]
|
|
|
|
|
+this.form.repeatType = selected.value
|
|
|
|
|
+},
|
|
|
|
|
+onNeedReviewChange(e) {
|
|
|
|
|
+this.form.needReview = e.detail.value
|
|
|
|
|
+},
|
|
|
|
|
+async submit() {
|
|
|
|
|
+if (!this.form.title) {
|
|
|
|
|
+uni.showToast({ title: '请输入任务名称', icon: 'none' })
|
|
|
|
|
+return
|
|
|
|
|
+}
|
|
|
|
|
+if (!this.form.childId) {
|
|
|
|
|
+uni.showToast({ title: '请选择孩子', icon: 'none' })
|
|
|
|
|
+return
|
|
|
|
|
+}
|
|
|
|
|
+if (!this.form.deadline) {
|
|
|
|
|
+uni.showToast({ title: '请选择截止时间', icon: 'none' })
|
|
|
|
|
+return
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+try {
|
|
|
|
|
+await createTask({
|
|
|
|
|
+title: this.form.title,
|
|
|
|
|
+description: this.form.description,
|
|
|
|
|
+childId: this.form.childId,
|
|
|
|
|
+points: parseInt(this.form.points) || 2,
|
|
|
|
|
+category: this.form.category || '其他',
|
|
|
|
|
+deadline: this.form.deadline.toISOString(),
|
|
|
|
|
+repeatType: this.form.repeatType,
|
|
|
|
|
+needReview: this.form.needReview ? 1 : 0
|
|
|
|
|
+})
|
|
|
|
|
+uni.showToast({ title: '创建成功', icon: 'success' })
|
|
|
|
|
+setTimeout(() => uni.navigateBack(), 1500)
|
|
|
|
|
+} catch (e) {
|
|
|
|
|
+uni.showToast({ title: '创建失败', icon: 'none' })
|
|
|
|
|
+}
|
|
|
|
|
+}
|
|
|
|
|
+}
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -116,7 +230,7 @@ export default {
|
|
|
.form-container { background: #fff; border-radius: 20rpx; padding: 30rpx; }
|
|
.form-container { background: #fff; border-radius: 20rpx; padding: 30rpx; }
|
|
|
.form-item { margin-bottom: 30rpx; }
|
|
.form-item { margin-bottom: 30rpx; }
|
|
|
.label { display: block; font-size: 28rpx; color: #333; margin-bottom: 10rpx; }
|
|
.label { display: block; font-size: 28rpx; color: #333; margin-bottom: 10rpx; }
|
|
|
-.input, .textarea { border: 1rpx solid #ddd; border-radius: 10rpx; padding: 20rpx; font-size: 28rpx; }
|
|
|
|
|
|
|
+.input, .textarea { border: 1rpx solid #ddd; border-radius: 10rpx; padding: 20rpx; font-size: 28rpx; width: 100%; box-sizing: border-box; }
|
|
|
.textarea { height: 150rpx; }
|
|
.textarea { height: 150rpx; }
|
|
|
.picker { border: 1rpx solid #ddd; border-radius: 10rpx; padding: 20rpx; font-size: 28rpx; color: #666; }
|
|
.picker { border: 1rpx solid #ddd; border-radius: 10rpx; padding: 20rpx; font-size: 28rpx; color: #666; }
|
|
|
.btn-primary { background: #FF6B6B; color: #fff; border-radius: 20rpx; margin-top: 40rpx; }
|
|
.btn-primary { background: #FF6B6B; color: #fff; border-radius: 20rpx; margin-top: 40rpx; }
|