feat(miniapp): align UI with H5 and harden device debugging
五个页面按 h5/css 的 style.css → ui-20261009 → ui-20261012 覆盖顺序逐条重排, 换算规则固定为 calc(N * var(--u)) → 2N rpx,固定 px 的字号保持 px。 - app.acss:换回 H5 设计 token(方角小倒角按钮 10rpx、卡片 14rpx、.chev 折线箭头) - splash/profile/history:底图与按钮文字图改用 H5 资源,隐私/政策弹窗按 H5 重排 - report:环形分用 conic-gradient、人脸裁切窗口叠加 face_maps、标记点百分比盒、 侧脸皱纹 pending/unavailable 文案;用 Playwright 抓 H5 94 个选择器几何比对, 整页高 2438.7 vs 2438.67 - camera:淘宝 <camera> 组件在真机整页崩溃(嵌了微信专有的 <cover-view>), 改为默认系统相机 + `config.nativeCamera` 开关 + pages/camtest 冒烟页验证组件 - permissions:淘宝用带前缀的 scope.camera(裸名返回 5022 Scope:camera信息不存在), 先试带前缀再退回裸名,拒绝后不再重复弹窗 - voice:非 HTTPS 资源导致的异常不再冒泡成整页崩溃;app.js 加开发版错误 toast - 开发版入口:权限诊断(启动页/相机页)、相机组件测试 - 测试 20/20(新增权限与相机能力用例)
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
/* ═════ 档案填写页:出生年月/性别/地区(原生 picker)+ 日常肤质选择(对齐 H5 #s-profile) ═════
|
||||
* 档案字段与 H5 一致:{ real_age, gender, region, daily_skin_type } */
|
||||
/* ═════ 档案填写页:出生年月/性别/地区 + 日常肤质轮播 → 拍照
|
||||
对照 H5 index.html #s-profile(L61-108)、#p-photoguide(L311-327)
|
||||
档案字段与 H5 一致:{ real_age, gender, region, daily_skin_type }
|
||||
选择器弹层保持现有实现(自绘 picker-view 滚轮 + 原生 selector),只调整触发控件外观。 ═════ */
|
||||
var api = require('../../utils/api.js');
|
||||
var REGION_DATA = require('../../utils/region-data.js');
|
||||
|
||||
// 肤质选项(与 H5 SKINS 一致,图片远程加载)
|
||||
// 肤质选项(与 H5 SKINS 一致,图片远程加载;第一条描述在 H5 里含 <br>,拆成两行)
|
||||
var SKINS = [
|
||||
{ img: 'img/ui-20261009/skin-0-dry.png', name: '干性肌肤', desc: '全脸干燥,容易紧绷、缺乏光泽' },
|
||||
{ img: 'img/ui-20261009/skin-0-dry.png', name: '干性肌肤', desc: '全脸干燥,容易紧绷、', desc2: '缺乏光泽' },
|
||||
{ img: 'img/ui-20261009/skin-1-mixeddry.png', name: '混合偏干肌肤', desc: '两颊偏干,T区油脂较少或偶尔出油' },
|
||||
{ img: 'img/ui-20261009/skin-2-neutral.png', name: '中性肌肤', desc: '水油平衡,肤感舒适,无明显干燥出油' },
|
||||
{ img: 'img/ui-20261009/skin-3-oily.png', name: '油性肌肤', desc: '全脸易出油,容易泛油光、毛孔明显' },
|
||||
@@ -21,7 +23,10 @@ function ageFromBirth(y, m) { return NOW_Y - y - (NOW_M < m ? 1 : 0); } // 未
|
||||
|
||||
Page({
|
||||
data: {
|
||||
bgUrl: api.assetUrl('img/bg-splash.jpg'),
|
||||
bgUrl: api.assetUrl('img/ui-20261009/bg-profile-h5.jpg'),
|
||||
guideBgUrl: api.assetUrl('img/ui-20261009/bg-splash-h5.jpg'),
|
||||
sloganUrl: api.assetUrl('img/ui-20261012/splash-slogan.png'),
|
||||
closeIconUrl: api.assetUrl('img/ui-20261009/icon-close.png'),
|
||||
|
||||
// 出生年月(两列滚轮:年+月,默认 30 岁 1 月)
|
||||
birthRange: [YEARS, MONTHS],
|
||||
@@ -44,11 +49,14 @@ Page({
|
||||
|
||||
// 肤质轮播
|
||||
skins: SKINS.map(function (s) {
|
||||
return { img: api.assetUrl(s.img), name: s.name, desc: s.desc };
|
||||
return { img: api.assetUrl(s.img), name: s.name, desc: s.desc, desc2: s.desc2 || '' };
|
||||
}),
|
||||
skinIndex: 0,
|
||||
skinPercent: 0,
|
||||
skinLastIndex: SKINS.length - 1,
|
||||
|
||||
showGuide: false, picker: '', pickerValue: [0, 0]
|
||||
showGuide: false, picker: '', pickerTitle: '', pickerValue: [0, 0],
|
||||
toastText: '', toastOn: false
|
||||
},
|
||||
onLoad: function () {
|
||||
if (!api.user()) { my.redirectTo({ url: '/pages/splash/splash' }); return; }
|
||||
@@ -60,6 +68,8 @@ Page({
|
||||
this.setData(saved);
|
||||
}
|
||||
} catch (_) {}
|
||||
// H5 goSkin(0) 的等价初始化:轨道位移与当前下标同步
|
||||
this.setData({ skinIndex: this.data.skinIndex || 0, skinPercent: (this.data.skinIndex || 0) * 100 });
|
||||
},
|
||||
onShow: function () {
|
||||
if (!api.user() || this.ownerId !== api.user().id) {
|
||||
@@ -67,11 +77,25 @@ Page({
|
||||
my.redirectTo({ url: '/pages/splash/splash' });
|
||||
}
|
||||
},
|
||||
onOpenBirth: function () { this.setData({ picker: 'birth', pickerValue: this.data.birthIndex.slice() }); },
|
||||
|
||||
// H5 .toast
|
||||
toast: function (msg) {
|
||||
var that = this;
|
||||
this.setData({ toastText: msg, toastOn: true });
|
||||
clearTimeout(this.toastTimer);
|
||||
this.toastTimer = setTimeout(function () {
|
||||
that.setData({ toastOn: false });
|
||||
}, Math.max(1800, String(msg).length * 130));
|
||||
},
|
||||
|
||||
onOpenBirth: function () {
|
||||
// H5 的 mobile-select title 为「出生年月」/「所在地区」
|
||||
this.setData({ picker: 'birth', pickerTitle: '出生年月', pickerValue: this.data.birthIndex.slice() });
|
||||
},
|
||||
onOpenRegion: function () {
|
||||
var index = this.data.regionIndex.slice();
|
||||
// A canceled draft may have changed the cities while the saved province stayed put.
|
||||
this.setData({ picker: 'region', pickerValue: index,
|
||||
this.setData({ picker: 'region', pickerTitle: '所在地区', pickerValue: index,
|
||||
regionRange: [REGION_DATA.map(function (p) { return p[0]; }), REGION_DATA[index[0]][1]] });
|
||||
},
|
||||
onPickerChange: function (e) {
|
||||
@@ -91,13 +115,13 @@ Page({
|
||||
/* ─── 出生年月 ─── */
|
||||
onBirthChange: function (e) {
|
||||
var idx = e.detail.value;
|
||||
var y = parseInt(YEARS[idx[0]], 10);
|
||||
var m = idx[1] + 1;
|
||||
var yv = parseInt(YEARS[idx[0]], 10);
|
||||
var mv = idx[1] + 1;
|
||||
this.setData({
|
||||
birthIndex: idx,
|
||||
birthText: y + '年' + m + '月',
|
||||
birth: y + '-' + (m < 10 ? '0' : '') + m,
|
||||
age: ageFromBirth(y, m)
|
||||
birthText: yv + '年' + mv + '月',
|
||||
birth: yv + '-' + (mv < 10 ? '0' : '') + mv,
|
||||
age: ageFromBirth(yv, mv)
|
||||
});
|
||||
},
|
||||
|
||||
@@ -121,30 +145,39 @@ Page({
|
||||
this.setData({ regionIndex: idx, regionText: text });
|
||||
},
|
||||
|
||||
/* ─── 肤质轮播 ─── */
|
||||
onSkinChange: function (e) {
|
||||
this.setData({ skinIndex: e.detail.current });
|
||||
/* ─── 肤质轮播(H5 goSkin 的等价实现:轨道 translateX) ─── */
|
||||
applySkin: function (index) {
|
||||
var i = Math.max(0, Math.min(SKINS.length - 1, index));
|
||||
this.setData({ skinIndex: i, skinPercent: i * 100 });
|
||||
},
|
||||
onSkinPrev: function () {
|
||||
if (this.data.skinIndex > 0) this.setData({ skinIndex: this.data.skinIndex - 1 });
|
||||
onSkinPrev: function () { this.applySkin(this.data.skinIndex - 1); },
|
||||
onSkinNext: function () { this.applySkin(this.data.skinIndex + 1); },
|
||||
onSkinTouchStart: function (e) {
|
||||
var t = (e.changedTouches || e.touches || [])[0];
|
||||
this.touchX = t ? (t.clientX != null ? t.clientX : t.pageX) : 0;
|
||||
},
|
||||
onSkinNext: function () {
|
||||
if (this.data.skinIndex < SKINS.length - 1) this.setData({ skinIndex: this.data.skinIndex + 1 });
|
||||
onSkinTouchEnd: function (e) {
|
||||
var t = (e.changedTouches || e.touches || [])[0];
|
||||
if (!t) return;
|
||||
var x = t.clientX != null ? t.clientX : t.pageX;
|
||||
var dx = x - (this.touchX || 0);
|
||||
if (Math.abs(dx) < 40) return;
|
||||
this.applySkin(this.data.skinIndex + (dx < 0 ? 1 : -1));
|
||||
},
|
||||
|
||||
/* ─── 提交 → 拍照引导弹窗 ─── */
|
||||
/* ─── 提交 → 拍照引导弹窗(H5 data-action="submit-profile") ─── */
|
||||
onSubmit: function () {
|
||||
var d = this.data;
|
||||
if (!d.birth || !(d.age >= 1 && d.age <= 99)) {
|
||||
my.showToast({ content: '请选择出生年月', type: 'none' });
|
||||
this.toast('请选择出生年月');
|
||||
return;
|
||||
}
|
||||
if (!d.genderText) {
|
||||
my.showToast({ content: '请选择性别', type: 'none' });
|
||||
this.toast('请选择性别');
|
||||
return;
|
||||
}
|
||||
if (!d.regionText) {
|
||||
my.showToast({ content: '请选择所在地区', type: 'none' });
|
||||
this.toast('请选择所在地区');
|
||||
return;
|
||||
}
|
||||
this.setData({ showGuide: true });
|
||||
@@ -154,7 +187,7 @@ Page({
|
||||
this.setData({ showGuide: false });
|
||||
},
|
||||
|
||||
// 「开始」:档案入全局态,进入拍照页
|
||||
// H5 data-action="start-camera":档案入全局态,进入拍照页
|
||||
onStartCamera: function () {
|
||||
if (!api.user()) { my.redirectTo({ url: '/pages/splash/splash' }); return; }
|
||||
var d = this.data;
|
||||
|
||||
Reference in New Issue
Block a user