0.0.0
This commit is contained in:
130
miniprogram/pages/dog-edit/dog-edit.js
Normal file
130
miniprogram/pages/dog-edit/dog-edit.js
Normal file
@@ -0,0 +1,130 @@
|
||||
// pages/dog-edit/dog-edit — 0b 建档/编辑(复用,docs/05 R2)
|
||||
// 仅名字、犬种必填。未知犬种(中华田园犬/其他)需手动选体型档位。?id= 进编辑模式。
|
||||
const { call } = require('../../utils/cloud.js');
|
||||
const store = require('../../utils/store.js');
|
||||
const { SIZE_LABELS, sizeOfBreed } = require('../../utils/dogStep.js');
|
||||
const { chooseAndUpload } = require('../../utils/media.js');
|
||||
|
||||
const BREEDS = [
|
||||
'柯基', '比熊', '泰迪', '柴犬', '金毛', '拉布拉多',
|
||||
'哈士奇', '边境牧羊犬', '萨摩耶', '法斗', '中华田园犬', '其他',
|
||||
];
|
||||
const AGE_STAGES = [
|
||||
{ key: 'puppy', label: '幼犬' },
|
||||
{ key: 'adult', label: '成犬' },
|
||||
{ key: 'senior', label: '老年犬' },
|
||||
];
|
||||
|
||||
Page({
|
||||
data: {
|
||||
isEdit: false,
|
||||
dogId: '',
|
||||
breeds: BREEDS,
|
||||
ageStages: AGE_STAGES,
|
||||
sizeLabels: SIZE_LABELS,
|
||||
breedIndex: -1,
|
||||
needSize: false, // 未知犬种时需手动选体型
|
||||
form: {
|
||||
name: '',
|
||||
breed: '',
|
||||
sizeLevel: '',
|
||||
gender: '',
|
||||
ageStage: '',
|
||||
weight: '',
|
||||
avatar: '',
|
||||
},
|
||||
submitting: false,
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
const id = options.id;
|
||||
if (id) {
|
||||
const dog = (store.getState().dogs || []).find((d) => d._id === id);
|
||||
if (dog) {
|
||||
wx.setNavigationBarTitle({ title: '编辑资料' });
|
||||
this.setData({
|
||||
isEdit: true,
|
||||
dogId: id,
|
||||
breedIndex: Math.max(0, BREEDS.indexOf(dog.breed)),
|
||||
needSize: !sizeOfBreed(dog.breed),
|
||||
form: {
|
||||
name: dog.name || '',
|
||||
breed: dog.breed || '',
|
||||
sizeLevel: dog.sizeLevel || '',
|
||||
gender: dog.gender || '',
|
||||
ageStage: dog.ageStage || '',
|
||||
weight: dog.weight != null ? String(dog.weight) : '',
|
||||
avatar: dog.avatar || '',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onNameInput(e) { this.setData({ 'form.name': e.detail.value }); },
|
||||
onWeightInput(e) { this.setData({ 'form.weight': e.detail.value }); },
|
||||
|
||||
async onPickAvatar() {
|
||||
const fileID = await chooseAndUpload('avatars');
|
||||
if (fileID) this.setData({ 'form.avatar': fileID });
|
||||
},
|
||||
|
||||
onBreedChange(e) {
|
||||
const idx = Number(e.detail.value);
|
||||
const breed = BREEDS[idx];
|
||||
const mapped = sizeOfBreed(breed);
|
||||
this.setData({
|
||||
breedIndex: idx,
|
||||
'form.breed': breed,
|
||||
needSize: !mapped, // 未知犬种 → 手动选
|
||||
'form.sizeLevel': mapped || '',
|
||||
});
|
||||
},
|
||||
|
||||
onSizeTap(e) { this.setData({ 'form.sizeLevel': e.currentTarget.dataset.v }); },
|
||||
|
||||
onGenderTap(e) {
|
||||
const v = e.currentTarget.dataset.v;
|
||||
this.setData({ 'form.gender': this.data.form.gender === v ? '' : v });
|
||||
},
|
||||
onAgeTap(e) {
|
||||
const v = e.currentTarget.dataset.v;
|
||||
this.setData({ 'form.ageStage': this.data.form.ageStage === v ? '' : v });
|
||||
},
|
||||
|
||||
async onSubmit() {
|
||||
const { form, isEdit, dogId, needSize, submitting } = this.data;
|
||||
if (submitting) return;
|
||||
if (!form.name.trim()) return wx.showToast({ title: '请填写名字', icon: 'none' });
|
||||
if (!form.breed) return wx.showToast({ title: '请选择犬种', icon: 'none' });
|
||||
if (needSize && !form.sizeLevel) return wx.showToast({ title: '请选择体型档位', icon: 'none' });
|
||||
|
||||
const ageText = (AGE_STAGES.find((a) => a.key === form.ageStage) || {}).label || '';
|
||||
const payload = {
|
||||
name: form.name.trim(),
|
||||
breed: form.breed,
|
||||
sizeLevel: form.sizeLevel || null, // 已知犬种服务端会覆盖
|
||||
gender: form.gender || null,
|
||||
ageStage: form.ageStage || null,
|
||||
ageText,
|
||||
weight: form.weight ? Number(form.weight) : null,
|
||||
avatar: form.avatar || '',
|
||||
};
|
||||
|
||||
this.setData({ submitting: true });
|
||||
const res = await call('dogManage', {
|
||||
action: isEdit ? 'update' : 'create',
|
||||
dog: isEdit ? { _id: dogId, ...payload } : payload,
|
||||
}, { loading: true, loadingText: '保存中' });
|
||||
this.setData({ submitting: false });
|
||||
if (!res.ok) return;
|
||||
|
||||
const dogs = (store.getState().dogs || []).slice();
|
||||
const i = dogs.findIndex((d) => d._id === res.data._id);
|
||||
if (i >= 0) dogs[i] = res.data; else dogs.push(res.data);
|
||||
store.set({ dogs, currentDogId: res.data._id });
|
||||
|
||||
if (isEdit) wx.navigateBack();
|
||||
else wx.switchTab({ url: '/pages/home/home' });
|
||||
},
|
||||
});
|
||||
4
miniprogram/pages/dog-edit/dog-edit.json
Normal file
4
miniprogram/pages/dog-edit/dog-edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationBarTitleText": "认识你的狗狗"
|
||||
}
|
||||
70
miniprogram/pages/dog-edit/dog-edit.wxml
Normal file
70
miniprogram/pages/dog-edit/dog-edit.wxml
Normal file
@@ -0,0 +1,70 @@
|
||||
<view class="page">
|
||||
<!-- 头像(可选) -->
|
||||
<view class="avatar-block" bindtap="onPickAvatar">
|
||||
<image wx:if="{{form.avatar}}" class="avatar" src="{{form.avatar}}" mode="aspectFill" />
|
||||
<view wx:else class="avatar">🐶</view>
|
||||
<view class="avatar-tip">点击上传头像(可选)</view>
|
||||
</view>
|
||||
|
||||
<!-- 名字 * -->
|
||||
<view class="field">
|
||||
<view class="flabel">名字 <text class="req">*</text></view>
|
||||
<input class="finput" placeholder="给狗狗起个名字" value="{{form.name}}" bindinput="onNameInput" maxlength="12" />
|
||||
</view>
|
||||
|
||||
<!-- 犬种 * -->
|
||||
<view class="field">
|
||||
<view class="flabel">犬种 <text class="req">*</text></view>
|
||||
<picker mode="selector" range="{{breeds}}" value="{{breedIndex}}" bindchange="onBreedChange">
|
||||
<view class="fpicker {{form.breed ? '' : 'placeholder'}}">
|
||||
{{form.breed || '请选择犬种'}}
|
||||
<text class="chev">›</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 体型档位(未知犬种必选,用于狗步换算) -->
|
||||
<view wx:if="{{needSize}}" class="field">
|
||||
<view class="flabel">体型档位 <text class="req">*</text></view>
|
||||
<view class="chips">
|
||||
<view wx:for="{{sizeLabels}}" wx:key="key"
|
||||
class="chip {{form.sizeLevel===item.key?'sel':''}}"
|
||||
data-v="{{item.key}}" bindtap="onSizeTap">{{item.label}}</view>
|
||||
</view>
|
||||
<view class="size-tip">找不到品种时,按腿长/体型选一个,用于估算狗步</view>
|
||||
</view>
|
||||
|
||||
<!-- 性别 -->
|
||||
<view class="field">
|
||||
<view class="flabel">性别</view>
|
||||
<view class="chips">
|
||||
<view class="chip {{form.gender==='male'?'sel':''}}" data-v="male" bindtap="onGenderTap">公</view>
|
||||
<view class="chip {{form.gender==='female'?'sel':''}}" data-v="female" bindtap="onGenderTap">母</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 年龄(可选) -->
|
||||
<view class="field">
|
||||
<view class="flabel">年龄(可选)</view>
|
||||
<view class="chips">
|
||||
<view wx:for="{{ageStages}}" wx:key="key"
|
||||
class="chip {{form.ageStage===item.key?'sel':''}}"
|
||||
data-v="{{item.key}}" bindtap="onAgeTap">{{item.label}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 体重(可选) -->
|
||||
<view class="field last">
|
||||
<view class="flabel">体重(可选,用于估算狗步)</view>
|
||||
<view class="weight-row">
|
||||
<input class="finput" type="digit" placeholder="如 12" value="{{form.weight}}" bindinput="onWeightInput" />
|
||||
<text class="unit">kg</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="submit">
|
||||
<button class="btn primary" bindtap="onSubmit" loading="{{submitting}}">
|
||||
{{isEdit ? '保存' : '完成,开始遛狗'}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
70
miniprogram/pages/dog-edit/dog-edit.wxss
Normal file
70
miniprogram/pages/dog-edit/dog-edit.wxss
Normal file
@@ -0,0 +1,70 @@
|
||||
.page { min-height: 100vh; padding-bottom: calc(48rpx + env(safe-area-inset-bottom)); }
|
||||
|
||||
.avatar-block {
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
padding: 36rpx 0 8rpx;
|
||||
}
|
||||
.avatar {
|
||||
width: 156rpx; height: 156rpx; border-radius: 50%;
|
||||
background: var(--surface-2);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 72rpx;
|
||||
border: 1rpx solid var(--line);
|
||||
}
|
||||
.avatar-tip { margin-top: 16rpx; font-size: 22rpx; color: var(--ink-2); }
|
||||
|
||||
.field {
|
||||
padding: 22rpx 32rpx;
|
||||
border-bottom: 1rpx solid var(--line);
|
||||
}
|
||||
.field.last { border-bottom: none; }
|
||||
.flabel { font-size: var(--form-label-size); color: var(--ink-2); margin-bottom: 12rpx; }
|
||||
.req { color: var(--danger); }
|
||||
|
||||
.finput {
|
||||
height: var(--input-height);
|
||||
min-height: var(--input-height);
|
||||
font-size: var(--input-font-size);
|
||||
color: var(--ink);
|
||||
background: var(--surface-2);
|
||||
border-radius: var(--input-radius);
|
||||
padding: var(--input-padding-y) var(--input-padding-x);
|
||||
line-height: 1.4;
|
||||
}
|
||||
.fpicker {
|
||||
min-height: var(--input-height);
|
||||
font-size: var(--input-font-size);
|
||||
color: var(--ink);
|
||||
background: var(--surface-2);
|
||||
border-radius: var(--input-radius);
|
||||
padding: var(--input-padding-y) var(--input-padding-x);
|
||||
line-height: 1.4;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.fpicker.placeholder { color: var(--ink-3); }
|
||||
.fpicker .chev { color: var(--ink-3); font-size: var(--icon-size-sm); line-height: 1; }
|
||||
|
||||
.chips { display: flex; flex-wrap: wrap; gap: 16rpx; }
|
||||
.chip {
|
||||
font-size: var(--chip-font-size);
|
||||
padding: var(--chip-padding-y) var(--chip-padding-x);
|
||||
border-radius: var(--radius-pill);
|
||||
border: 1rpx solid var(--line-2);
|
||||
background: var(--surface-2);
|
||||
color: var(--ink);
|
||||
line-height: 1.4;
|
||||
}
|
||||
.chip.sel {
|
||||
background: var(--accent-soft);
|
||||
border-color: var(--accent);
|
||||
color: var(--accent-deep);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.size-tip { font-size: 21rpx; color: var(--ink-3); margin-top: 12rpx; }
|
||||
|
||||
.weight-row { display: flex; align-items: center; gap: 16rpx; }
|
||||
.weight-row .finput { flex: 1; }
|
||||
.weight-row .unit { font-size: var(--input-font-size); color: var(--ink-2); }
|
||||
|
||||
.submit { padding: 40rpx 32rpx 0; }
|
||||
Reference in New Issue
Block a user