62 changed files with 4637 additions and 279 deletions
@ -0,0 +1,134 @@ |
|||||||
|
# AGENTS.md - 信达小程序 (Xinda Mini Program) |
||||||
|
|
||||||
|
WeChat Mini Program for thyroid eye disease patient management. Dual-mode app serving both patients (患者端) and doctors (医生端). |
||||||
|
|
||||||
|
## Project Type |
||||||
|
|
||||||
|
- **Framework**: WeChat Mini Program v3.7.7 |
||||||
|
- **Language**: TypeScript (strict mode) |
||||||
|
- **Styling**: SCSS/Sass via `useCompilerPlugins` |
||||||
|
- **UI Library**: Vant Weapp (@vant/weapp) |
||||||
|
- **Renderer**: Skyline enabled |
||||||
|
- **App ID**: `wxf9ce8010f1ad24aa` (dev), `wx71ac9c27c3c3e3f4` (prod) |
||||||
|
|
||||||
|
## Directory Structure |
||||||
|
|
||||||
|
``` |
||||||
|
src/ |
||||||
|
├── pages/ # Doctor-side main pages (医生端) |
||||||
|
├── patient/pages/ # Patient-side pages (subpackage) |
||||||
|
├── gift/pages/ # DTP pharmacy pages (subpackage) |
||||||
|
├── doc/pages/ # Privacy/terms documentation (subpackage) |
||||||
|
├── components/ # Shared components |
||||||
|
├── utils/ # Request, page/component wrappers, utilities |
||||||
|
├── app.ts # App entry with global data |
||||||
|
└── config.ts # Environment configs per appId |
||||||
|
``` |
||||||
|
|
||||||
|
## Key Conventions |
||||||
|
|
||||||
|
### Path Aliases |
||||||
|
- `@/*` → `src/*` (configured in tsconfig.json and app.json `resolveAlias`) |
||||||
|
- Use `@/utils/request` not relative paths |
||||||
|
|
||||||
|
### User Types & Routing |
||||||
|
Login types enforced in `app.ts`: |
||||||
|
- `0`: Not logged in |
||||||
|
- `1`: Patient (患者) → routes to `/patient/pages/*` |
||||||
|
- `2`: Doctor (医生) → routes to `/pages/*` |
||||||
|
|
||||||
|
Use `app.zdWaitLogin()` to guard pages that require login. |
||||||
|
|
||||||
|
### Page/Component Wrappers |
||||||
|
`app.ts` overrides global `Page` and `Component` with wrappers from `utils/page.ts` and `utils/component.ts`: |
||||||
|
- Auto-sets `imageUrl` and `Timestamp` on page load |
||||||
|
- Auto-handles navbar background on scroll |
||||||
|
- Provides default share behavior |
||||||
|
|
||||||
|
### Modal Colors (Required) |
||||||
|
All `wx.showModal` must use: |
||||||
|
```ts |
||||||
|
wx.showModal({ |
||||||
|
confirmColor: '#8c75d0', |
||||||
|
cancelColor: '#141515', |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
## Available Commands |
||||||
|
|
||||||
|
```bash |
||||||
|
# Lint and auto-fix (only command available) |
||||||
|
npm run lint:fix |
||||||
|
|
||||||
|
# Install dependencies (pnpm preferred based on lockfile) |
||||||
|
pnpm install |
||||||
|
|
||||||
|
# Build: Use WeChat Developer Tools |
||||||
|
# - Import project with src/ as root |
||||||
|
# - project.config.json at repo root |
||||||
|
``` |
||||||
|
|
||||||
|
## NPM Dependencies |
||||||
|
|
||||||
|
**Critical**: After `npm install`, run **Tools → Build npm** in WeChat Developer Tools to generate `miniprogram_npm/`. This is required for Vant and other packages. |
||||||
|
|
||||||
|
Key dependencies: |
||||||
|
- `@vant/weapp`: UI components |
||||||
|
- `miniprogram-licia`: Utility library (available as `licia`) |
||||||
|
- `dayjs`: Date handling |
||||||
|
- `mp-html`: Rich HTML rendering |
||||||
|
|
||||||
|
## Images & Assets |
||||||
|
|
||||||
|
**Images are stored in SVN, not git.** |
||||||
|
- SVN URL: `svn://39.106.86.127:28386/projects/xd/proj_src/shop/frontend/web/xd/` |
||||||
|
- Local path: `src/images/` (gitignored) |
||||||
|
- Excluded from upload via `project.config.json` packOptions |
||||||
|
- Only `/images/tabbar/*` is included in uploads |
||||||
|
|
||||||
|
Image URL pattern: |
||||||
|
``` |
||||||
|
{{imageUrl}}/path/to/image.png?t={{Timestamp}} |
||||||
|
``` |
||||||
|
|
||||||
|
## TypeScript Configuration |
||||||
|
|
||||||
|
- Strict mode enabled |
||||||
|
- `noImplicitAny: false` (allows implicit any) |
||||||
|
- Paths: `@/*` mapped to `src/*` |
||||||
|
- Types: `miniprogram-api-typings` for WX API |
||||||
|
|
||||||
|
Global types in `typings/index.d.ts`: |
||||||
|
- `IAppOption`: Global app instance interface |
||||||
|
- `pageType`: 0 | 1 | 2 for user types |
||||||
|
- `wx.ajax`: Extended request method |
||||||
|
|
||||||
|
## ESLint & Formatting |
||||||
|
|
||||||
|
- Config: `@antfu/eslint-config` (flat config in `eslint.config.js`) |
||||||
|
- Prettier: 2-space tabs, no semis, single quotes, trailing commas |
||||||
|
- WXML files parsed as HTML, WXSS as CSS |
||||||
|
- Globals defined: `wx`, `App`, `Page`, `Component`, `getCurrentPages`, etc. |
||||||
|
|
||||||
|
## Environment Configuration |
||||||
|
|
||||||
|
Selected by App ID in `src/config.ts`: |
||||||
|
- `wxf9ce8010f1ad24aa`: Dev/Staging (hbraas.com) |
||||||
|
- `wx71ac9c27c3c3e3f4`: Production (hbsaas.com) |
||||||
|
|
||||||
|
App reads `wx.getAccountInfoSync().miniProgram.appId` on launch to select config. |
||||||
|
|
||||||
|
## Testing & Development |
||||||
|
|
||||||
|
- No unit test framework configured |
||||||
|
- Manual testing via WeChat Developer Tools |
||||||
|
- `project.private.config.json` has hot reload enabled (`compileHotReLoad: true`) |
||||||
|
- Predefined test pages in `project.private.config.json` condition list |
||||||
|
|
||||||
|
## Common Gotchas |
||||||
|
|
||||||
|
1. **NPM packages**: Must run "Build npm" in WeChat tools after install |
||||||
|
2. **Images**: Will 404 if SVN images not checked out to `src/images/` |
||||||
|
3. **Subpackages**: Patient pages are in `patient/` subpackage, not main package |
||||||
|
4. **Skyline**: Enabled in rendererOptions, some components may behave differently |
||||||
|
5. **Login flow**: App automatically calls `startLogin()` on launch; pages must wait via `app.zdWaitLogin()` |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
{ |
||||||
|
"component": true, |
||||||
|
"usingComponents": { |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
.preview-container { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
right: 0; |
||||||
|
bottom: 0; |
||||||
|
background: #000; |
||||||
|
z-index: 1000; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
opacity: 0; |
||||||
|
visibility: hidden; |
||||||
|
transition: |
||||||
|
opacity 0.3s, |
||||||
|
visibility 0.3s; |
||||||
|
|
||||||
|
&.show { |
||||||
|
opacity: 1; |
||||||
|
visibility: visible; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 图片展示区域 |
||||||
|
.image-wrapper { |
||||||
|
flex: 1; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
.preview-image { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 底部操作栏 |
||||||
|
.action-bar { |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
right: 0; |
||||||
|
padding: 40rpx; |
||||||
|
padding-bottom: calc(40rpx + env(safe-area-inset-bottom)); |
||||||
|
background: #fff; |
||||||
|
display: flex; |
||||||
|
gap: 32rpx; |
||||||
|
|
||||||
|
.btn { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
border-radius: 44rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
font-size: 32rpx; |
||||||
|
font-weight: 500; |
||||||
|
|
||||||
|
&-delete { |
||||||
|
border: 1px solid #b982ff; |
||||||
|
color: #b982ff; |
||||||
|
background: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
&-retake { |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
&:active { |
||||||
|
opacity: 0.8; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
Component({ |
||||||
|
properties: {}, |
||||||
|
|
||||||
|
data: { |
||||||
|
visible: false, |
||||||
|
src: '', |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
// 返回/关闭
|
||||||
|
handleBack() { |
||||||
|
this.triggerEvent('close') |
||||||
|
}, |
||||||
|
|
||||||
|
// 更多操作
|
||||||
|
handleMore() { |
||||||
|
this.triggerEvent('more') |
||||||
|
}, |
||||||
|
|
||||||
|
// 预览/查看
|
||||||
|
handlePreview(src) { |
||||||
|
if (src) { |
||||||
|
this.setData({ |
||||||
|
visible: true, |
||||||
|
src, |
||||||
|
}) |
||||||
|
} |
||||||
|
}, |
||||||
|
handleHidePreview() { |
||||||
|
this.setData({ |
||||||
|
visible: false, |
||||||
|
sec: '', |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
// 删除
|
||||||
|
handleDelete() { |
||||||
|
wx.showModal({ |
||||||
|
title: '提示', |
||||||
|
content: '确定要删除这张照片吗?', |
||||||
|
success: (res) => { |
||||||
|
if (res.confirm) { |
||||||
|
this.handleHidePreview() |
||||||
|
this.triggerEvent('delete') |
||||||
|
} |
||||||
|
}, |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
// 重拍
|
||||||
|
handleRetake() { |
||||||
|
this.handleHidePreview() |
||||||
|
this.triggerEvent('retake') |
||||||
|
}, |
||||||
|
}, |
||||||
|
}) |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
<view class="preview-container {{visible ? 'show' : ''}}"> |
||||||
|
<!-- 图片展示区域 --> |
||||||
|
<view class="image-wrapper"> |
||||||
|
<image class="preview-image" src="{{src}}" mode="aspectFit" /> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 底部操作栏 --> |
||||||
|
<view class="action-bar"> |
||||||
|
<view class="btn btn-delete" bindtap="handleDelete">删除</view> |
||||||
|
<view class="btn btn-retake" bindtap="handleRetake">重拍</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"usingComponents": { |
||||||
|
"navbar": "/components/navbar/index", |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "记录" |
||||||
|
} |
||||||
@ -0,0 +1,168 @@ |
|||||||
|
.page { |
||||||
|
.container { |
||||||
|
position: relative; |
||||||
|
padding: 40rpx 40rpx 240rpx; |
||||||
|
border-radius: 32rpx 32rpx 0 0; |
||||||
|
background-color: #fff; |
||||||
|
.benchmark { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
padding-top: 8rpx; |
||||||
|
text-align: center; |
||||||
|
width: 144rpx; |
||||||
|
height: 64rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #fff; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.date { |
||||||
|
font-size: 40rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.total { |
||||||
|
margin-top: 32rpx; |
||||||
|
padding-top: 48rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
border-top: 1px solid rgba(173, 172, 178, 0.1); |
||||||
|
display: flex; |
||||||
|
gap: 22rpx; |
||||||
|
align-items: center; |
||||||
|
.num { |
||||||
|
font-size: 40rpx; |
||||||
|
color: #b073ff; |
||||||
|
} |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.banner { |
||||||
|
margin-top: 24rpx; |
||||||
|
padding: 32rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 32rpx 32rpx 32rpx 32rpx; |
||||||
|
border: 2rpx solid #ffffff; |
||||||
|
.title { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.row { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: flex; |
||||||
|
gap: 24rpx; |
||||||
|
text-align: center; |
||||||
|
.col { |
||||||
|
padding: 24rpx; |
||||||
|
flex: 1; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 16rpx; |
||||||
|
.name { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 16rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: baseline; |
||||||
|
gap: 8rpx; |
||||||
|
.num { |
||||||
|
font-size: 56rpx; |
||||||
|
color: #b073ff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.sub { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.card { |
||||||
|
margin-top: 48rpx; |
||||||
|
.card-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.card-container { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(2, 320rpx); |
||||||
|
justify-content: space-between; |
||||||
|
gap: 30rpx; |
||||||
|
.card-item { |
||||||
|
.photo { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: 320rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
} |
||||||
|
.name { |
||||||
|
margin-top: 16rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #adacb2; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
padding: 20rpx 30rpx 60rpx; |
||||||
|
width: 100%; |
||||||
|
box-sizing: border-box; |
||||||
|
margin-top: 46rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 22rpx; |
||||||
|
background-color: #fff; |
||||||
|
box-shadow: 0 -10rpx 10rpx rgba(204, 204, 204, 0.1); |
||||||
|
.btn1 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #b982ff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
border: 1px solid #b982ff; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
.btn2 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #ffffff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,88 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
history: { |
||||||
|
frontend: [ |
||||||
|
{ |
||||||
|
title: '正面睁眼照', |
||||||
|
content: '平视,目光看向镜头方向,自然睁眼,不眯眼、不瞪眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面闭眼照', |
||||||
|
content: '正对镜头,面部居中,自然放松,双眼轻轻闭合,不皱眉、不挤眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面仰头照', |
||||||
|
content: '拍摄时,正对镜头,面部居中,头部自然向上仰至约 45°,双眼同步平视,保持自然睁眼、不眯眼。', |
||||||
|
}, |
||||||
|
], |
||||||
|
backend: [ |
||||||
|
{ |
||||||
|
title: '左侧-90°', |
||||||
|
content: '身体与头部完全转向右侧,呈标准 90° 侧面,仅可见左侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-90°', |
||||||
|
content: '身体与头部完全转向左侧,呈标准 90° 侧面,仅可见右侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '左侧-45°', |
||||||
|
content: '身体与头部转向右前方 45°。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-45°', |
||||||
|
content: '身体与头部转向左前方 45°', |
||||||
|
}, |
||||||
|
], |
||||||
|
other: [ |
||||||
|
{ |
||||||
|
title: '正面眼睛上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
onLoad() {}, |
||||||
|
|
||||||
|
handlePopupOk() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handlePopupCancel() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,74 @@ |
|||||||
|
<navbar fixed title="记录" custom-style="background:{{background}}"> |
||||||
|
<van-icon name="arrow-left" slot="left" size="18px" color="#000" bind:tap="handleBack" /> |
||||||
|
</navbar> |
||||||
|
|
||||||
|
<view |
||||||
|
class="page" |
||||||
|
style="background: url('{{imageUrl}}bg10.png?t={{Timestamp}}') no-repeat top center/100% 610rpx;padding-top:{{pageTop+16}}px;" |
||||||
|
> |
||||||
|
<view class="container"> |
||||||
|
<view class="benchmark" style="background: url('/images/bg56.png') no-repeat top center/100%">基准照</view> |
||||||
|
<view class="date">2026-04-02</view> |
||||||
|
<view class="total"> |
||||||
|
当前记录对应的替妥尤单抗使用次数: |
||||||
|
<text class="num">1</text> |
||||||
|
</view> |
||||||
|
<view class="banner"> |
||||||
|
<view class="title">眼球突出度测量记录</view> |
||||||
|
<view class="row"> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">右眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">眶间距</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">左眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">正面</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.frontend}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">侧面</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.backend}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">眼球运动八个方向</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.other}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<view class="btn1">眼突度 对比</view> |
||||||
|
<view class="btn2">照片 对比</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
{ |
||||||
|
"navigationBarTitleText": "xxx的眼突度对比", |
||||||
|
"navigationStyle": "default", |
||||||
|
"usingComponents": {} |
||||||
|
} |
||||||
@ -0,0 +1,148 @@ |
|||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #f6f8f9; |
||||||
|
padding: 16rpx 30rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
|
||||||
|
.table-wrapper { |
||||||
|
background-color: #eee2ff; |
||||||
|
border-radius: 13rpx; |
||||||
|
border: 1rpx solid #fff; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
|
||||||
|
/* 表头样式 */ |
||||||
|
.table-header { |
||||||
|
display: flex; |
||||||
|
background-color: #f7f0ff; |
||||||
|
|
||||||
|
&.sticky { |
||||||
|
position: sticky; |
||||||
|
top: 0; |
||||||
|
z-index: 100; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.th { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
color: #b982ff; |
||||||
|
font-size: 28rpx; |
||||||
|
font-weight: 500; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
|
||||||
|
.th-date { |
||||||
|
width: 200rpx; |
||||||
|
height: 120rpx; |
||||||
|
border-right: 1rpx solid #eee4ff; |
||||||
|
justify-content: flex-end; |
||||||
|
padding-bottom: 20rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.th-eye { |
||||||
|
flex: 1; |
||||||
|
padding: 0; |
||||||
|
border-right: 1rpx solid #eee4ff; |
||||||
|
} |
||||||
|
|
||||||
|
.th-eye-title { |
||||||
|
text-align: center; |
||||||
|
padding: 16rpx 0; |
||||||
|
border-bottom: 1rpx solid #eee4ff; |
||||||
|
width: 100%; |
||||||
|
font-size: 28rpx; |
||||||
|
height: 60rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
|
||||||
|
.th-eye-sub { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
height: 60rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.th-sub-item { |
||||||
|
flex: 1; |
||||||
|
text-align: center; |
||||||
|
border-right: 1rpx solid #eee4ff; |
||||||
|
font-size: 28rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
|
||||||
|
&:last-child { |
||||||
|
border-right: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.th-count { |
||||||
|
width: 120rpx; |
||||||
|
text-align: center; |
||||||
|
line-height: 1.3; |
||||||
|
font-size: 28rpx; |
||||||
|
height: 120rpx; |
||||||
|
justify-content: center; |
||||||
|
} |
||||||
|
|
||||||
|
/* 表格内容样式 */ |
||||||
|
.table-body { |
||||||
|
background-color: #eee2ff; |
||||||
|
} |
||||||
|
|
||||||
|
.tr { |
||||||
|
display: flex; |
||||||
|
height: 100rpx; |
||||||
|
|
||||||
|
&:last-child { |
||||||
|
.td-date, |
||||||
|
.td-eye, |
||||||
|
.td-count { |
||||||
|
border-bottom: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.td { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
color: #211d2e; |
||||||
|
font-size: 32rpx; |
||||||
|
font-weight: 500; |
||||||
|
box-sizing: border-box; |
||||||
|
height: 100rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.td-date { |
||||||
|
width: 200rpx; |
||||||
|
background-color: #ffffff; |
||||||
|
border-right: 1rpx solid #eee4ff; |
||||||
|
border-bottom: 1rpx solid #eee4ff; |
||||||
|
} |
||||||
|
|
||||||
|
.td-eye { |
||||||
|
flex: 1; |
||||||
|
display: flex; |
||||||
|
background-color: #fff; |
||||||
|
border-bottom: 1rpx solid #eee4ff; |
||||||
|
} |
||||||
|
|
||||||
|
.td-eye-item { |
||||||
|
flex: 1; |
||||||
|
text-align: center; |
||||||
|
border-right: 1rpx solid #eee4ff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
height: 100rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.td-count { |
||||||
|
width: 120rpx; |
||||||
|
background-color: #ffffff; |
||||||
|
border-bottom: 1rpx solid #eee4ff; |
||||||
|
} |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
const _app = getApp<IAppOption>(); |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
dataList: [ |
||||||
|
{ |
||||||
|
date: '2026.1.5', |
||||||
|
left: '40', |
||||||
|
spacing: '40', |
||||||
|
right: '40', |
||||||
|
count: '30', |
||||||
|
}, |
||||||
|
{ |
||||||
|
date: '2025.12.30', |
||||||
|
left: '30', |
||||||
|
spacing: '30', |
||||||
|
right: '30', |
||||||
|
count: '20', |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
onLoad() {}, |
||||||
|
}); |
||||||
|
|
||||||
|
export {}; |
||||||
@ -0,0 +1,35 @@ |
|||||||
|
<view class="container"> |
||||||
|
<!-- 表格区域 --> |
||||||
|
<view class="table-wrapper"> |
||||||
|
<!-- 吸顶表头 --> |
||||||
|
<view class="table-header sticky"> |
||||||
|
<view class="th th-date">日期</view> |
||||||
|
<view class="th th-eye"> |
||||||
|
<view class="th-eye-title">眼突度(mm)</view> |
||||||
|
<view class="th-eye-sub"> |
||||||
|
<view class="th-sub-item">左侧</view> |
||||||
|
<view class="th-sub-item">眶间距</view> |
||||||
|
<view class="th-sub-item">右侧</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="th th-count"> |
||||||
|
<view>替妥尤</view> |
||||||
|
<view>输注</view> |
||||||
|
<view>次数</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 表格内容 --> |
||||||
|
<view class="table-body"> |
||||||
|
<view class="tr" wx:for="{{dataList}}" wx:key="date"> |
||||||
|
<view class="td td-date">{{item.date}}</view> |
||||||
|
<view class="td td-eye"> |
||||||
|
<view class="td-eye-item">{{item.left}}</view> |
||||||
|
<view class="td-eye-item">{{item.spacing}}</view> |
||||||
|
<view class="td-eye-item">{{item.right}}</view> |
||||||
|
</view> |
||||||
|
<view class="td td-count">{{item.count}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"navigationStyle": "default", |
||||||
|
"usingComponents": { |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "记录" |
||||||
|
} |
||||||
@ -0,0 +1,106 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
.page { |
||||||
|
.total { |
||||||
|
padding: 32rpx 40rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
.history-list { |
||||||
|
padding: 0 40rpx 240rpx; |
||||||
|
.list-item { |
||||||
|
margin-bottom: 24rpx; |
||||||
|
position: relative; |
||||||
|
border-radius: 32rpx; |
||||||
|
background-color: #fff; |
||||||
|
padding: 32rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
gap: 24rpx; |
||||||
|
.benchmark { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
padding-top: 8rpx; |
||||||
|
text-align: center; |
||||||
|
width: 124rpx; |
||||||
|
height: 64rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.photo { |
||||||
|
width: 140rpx; |
||||||
|
height: 140rpx; |
||||||
|
border-radius: 16rpx; |
||||||
|
} |
||||||
|
.wrap { |
||||||
|
flex: 1; |
||||||
|
.date { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.tag { |
||||||
|
margin-top: 16rpx; |
||||||
|
padding: 4rpx 12rpx; |
||||||
|
display: inline-block; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #b073ff; |
||||||
|
background: rgba(176, 115, 255, 0.16); |
||||||
|
border-radius: 6rpx 6rpx 6rpx 6rpx; |
||||||
|
} |
||||||
|
.rotate { |
||||||
|
margin-top: 28rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #adacb2; |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
.more { |
||||||
|
align-self: center; |
||||||
|
width: 44rpx; |
||||||
|
height: 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
padding: 20rpx 30rpx 60rpx; |
||||||
|
width: 100%; |
||||||
|
box-sizing: border-box; |
||||||
|
margin-top: 46rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 22rpx; |
||||||
|
background-color: #fff; |
||||||
|
box-shadow: 0 -10rpx 10rpx rgba(204, 204, 204, 0.1); |
||||||
|
.btn1 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #b982ff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
border: 1px solid #b982ff; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
.btn2 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #ffffff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,93 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
history: { |
||||||
|
frontend: [ |
||||||
|
{ |
||||||
|
title: '正面睁眼照', |
||||||
|
content: '平视,目光看向镜头方向,自然睁眼,不眯眼、不瞪眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面闭眼照', |
||||||
|
content: '正对镜头,面部居中,自然放松,双眼轻轻闭合,不皱眉、不挤眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面仰头照', |
||||||
|
content: '拍摄时,正对镜头,面部居中,头部自然向上仰至约 45°,双眼同步平视,保持自然睁眼、不眯眼。', |
||||||
|
}, |
||||||
|
], |
||||||
|
backend: [ |
||||||
|
{ |
||||||
|
title: '左侧-90°', |
||||||
|
content: '身体与头部完全转向右侧,呈标准 90° 侧面,仅可见左侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-90°', |
||||||
|
content: '身体与头部完全转向左侧,呈标准 90° 侧面,仅可见右侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '左侧-45°', |
||||||
|
content: '身体与头部转向右前方 45°。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-45°', |
||||||
|
content: '身体与头部转向左前方 45°', |
||||||
|
}, |
||||||
|
], |
||||||
|
other: [ |
||||||
|
{ |
||||||
|
title: '正面眼睛上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
onLoad() {}, |
||||||
|
handleDiffData() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/pages/d_noteDiffData/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
handlePopupOk() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handlePopupCancel() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
<view class="page"> |
||||||
|
<view class="total">共X条日记记录</view> |
||||||
|
<view class="history-list"> |
||||||
|
<view class="list-item" bind:tap="handleHistory"> |
||||||
|
<view class="benchmark" style="background: url('{{imageUrl}}bg50.png?t={{Timestamp}}') no-repeat top center/100%"> |
||||||
|
基准照 |
||||||
|
</view> |
||||||
|
<image class="photo" src="{{imageUrl}}icon143.png?t={{Timestamp}}"></image> |
||||||
|
<view class="wrap"> |
||||||
|
<view class="date">2026-04-01</view> |
||||||
|
<view class="tag">替妥尤单抗:2</view> |
||||||
|
<view class="rotate">已上传1个角度</view> |
||||||
|
</view> |
||||||
|
<image class="more" src="{{imageUrl}}icon148.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<view class="btn1" bind:tap="handleDiffData">眼突度 对比</view> |
||||||
|
<view class="btn2">照片 对比</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -1,41 +1,102 @@ |
|||||||
<view class="camera-container" wx:if="{{visible}}"> |
<view class="camera-container" wx:if="{{visible}}"> |
||||||
<camera |
<camera class="camera" device-position="{{devicePosition}}" flash="{{flash}}" binderror="onCameraError"> |
||||||
class="camera" |
<view |
||||||
device-position="{{devicePosition}}" |
class="camera-container" |
||||||
flash="{{flash}}" |
style="background: url('{{imageUrl}}camera-bg.png?t={{Timestamp}}') no-repeat center/100%" |
||||||
binderror="onCameraError" |
> |
||||||
> |
<view class="example {{exampleShow && 'active'}}" bind:tap="handleExample"> |
||||||
<view class="camera-frame"> |
<image class="icon" src="{{imageUrl}}icon159.png?t={{Timestamp}}"></image> |
||||||
<view class="frame-corner left-top"></view> |
查看示范 |
||||||
<view class="frame-corner right-top"></view> |
<view class="example-popup" hidden="{{!exampleShow}}"> |
||||||
<view class="frame-corner left-bottom"></view> |
<view class="content">平视,目光看向镜头方向,自然睁眼,不眯眼、不瞪眼。</view> |
||||||
<view class="frame-corner right-bottom"></view> |
<view class="photo-wrap"> |
||||||
|
<image class="photo" src="{{imageUrl}}{{frame[type].exampleSrc}}.png?t={{Timestamp}}"></image> |
||||||
|
<image class="label" src="{{imageUrl}}icon162.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view |
||||||
|
class="camera-frame" |
||||||
|
style="background: url('{{imageUrl}}{{frame[type].src}}.png?t={{Timestamp}}') no-repeat top center/100%" |
||||||
|
> |
||||||
|
<image wx:if="{{type==8}}" class="icon8" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<block wx:elif="{{type==9}}"> |
||||||
|
<image class="icon9-1" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<image class="icon9-2" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
</block> |
||||||
|
<image wx:elif="{{type==10}}" class="icon10" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<image wx:elif="{{type==11}}" class="icon11" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<image wx:elif="{{type==12}}" class="icon12" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<image wx:elif="{{type==13}}" class="icon13" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<block wx:elif="{{type==14}}"> |
||||||
|
<image class="icon14-1" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
<image class="icon14-2" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
</block> |
||||||
|
<image wx:elif="{{type==15}}" class="icon15" src="{{imageUrl}}icon163.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view> |
||||||
|
<view class="tip">请将眼睛置于虚线框中心位置</view> |
||||||
|
</view> |
||||||
|
<view> |
||||||
|
<view class="order"> |
||||||
|
正面睁眼 |
||||||
|
<view class="num">1</view> |
||||||
|
<view class="m-num">/3</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="controls"> |
||||||
|
<view class="switch-btn" bindtap="switchCamera"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon160.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">翻转</view> |
||||||
|
</view> |
||||||
|
<view class="control-btn" bindtap="takePhoto"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon161.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="block"></view> |
||||||
|
</view> |
||||||
</view> |
</view> |
||||||
</camera> |
</camera> |
||||||
|
|
||||||
<view class="close-btn" bindtap="closeCamera"> |
<!-- <view class="controls"> --> |
||||||
<van-icon name="cross" size="20px" color="#fff" /> |
<!-- <view class="control-btn switch-btn" bindtap="switchCamera"> --> |
||||||
</view> |
<!-- <van-icon name="reload" size="24px" color="#fff" /> --> |
||||||
|
<!-- </view> --> |
||||||
<view class="controls"> |
<!----> |
||||||
<view class="control-btn switch-btn" bindtap="switchCamera"> |
<!-- <view class="control-btn capture-btn" bindtap="takePhoto"> --> |
||||||
<van-icon name="reload" size="24px" color="#fff" /> |
<!-- <view class="capture-inner"></view> --> |
||||||
</view> |
<!-- </view> --> |
||||||
|
<!----> |
||||||
<view class="control-btn capture-btn" bindtap="takePhoto"> |
<!-- <view class="control-btn flash-btn" bindtap="toggleFlash"> --> |
||||||
<view class="capture-inner"></view> |
<!-- <van-icon name="{{flash === 'off' ? 'closed-eye' : 'eye'}}" size="24px" color="#fff" /> --> |
||||||
</view> |
<!-- </view> --> |
||||||
|
<!-- </view> --> |
||||||
|
</view> |
||||||
|
|
||||||
<view class="control-btn flash-btn" bindtap="toggleFlash"> |
<van-popup |
||||||
<van-icon name="{{flash === 'off' ? 'closed-eye' : 'eye'}}" size="24px" color="#fff" /> |
wx:if="{{selectShow}}" |
||||||
|
bind:click-overlay="handleCancel" |
||||||
|
round |
||||||
|
z-index="{{100000}}" |
||||||
|
show="{{ true }}" |
||||||
|
custom-style="background:transparent;" |
||||||
|
position="bottom" |
||||||
|
safe-area-inset-bottom="{{false}}" |
||||||
|
root-portal |
||||||
|
> |
||||||
|
<view class="popup-container"> |
||||||
|
<view class="title"> |
||||||
|
选择上传方式 |
||||||
|
<van-icon name="cross" /> |
||||||
</view> |
</view> |
||||||
</view> |
<view class="select"> |
||||||
|
<view class="item" bind:tap="handleCamera"> |
||||||
<view class="preview-section" wx:if="{{previewImage}}"> |
<image class="icon" src="{{imageUrl}}icon157.png?t={{Timestamp}}"></image> |
||||||
<image class="preview-image" src="{{previewImage}}" mode="aspectFit" /> |
<view class="name">拍摄</view> |
||||||
<view class="preview-actions"> |
</view> |
||||||
<van-button type="default" round bindtap="retake">重拍</van-button> |
<view class="item" bind:tap="handlePicture"> |
||||||
<van-button type="primary" round custom-style="margin-left: 30rpx;" bindtap="usePhoto">使用照片</van-button> |
<image class="icon" src="{{imageUrl}}icon158.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">从相册选择</view> |
||||||
|
</view> |
||||||
</view> |
</view> |
||||||
</view> |
</view> |
||||||
</view> |
</van-popup> |
||||||
|
|||||||
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"usingComponents": { |
||||||
|
"navbar": "/components/navbar/index", |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "突眼日记" |
||||||
|
} |
||||||
@ -0,0 +1,269 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
.container { |
||||||
|
padding: 20rpx 30rpx; |
||||||
|
min-height: 100vh; |
||||||
|
} |
||||||
|
|
||||||
|
// 基准照片设置卡片 |
||||||
|
.setting-card-empty { |
||||||
|
background: #fff; |
||||||
|
border-radius: 32rpx; |
||||||
|
padding: 32rpx; |
||||||
|
margin-bottom: 32rpx; |
||||||
|
box-shadow: 0rpx 4rpx 32rpx 0rpx rgba(0, 0, 0, 0.04); |
||||||
|
.setting-header { |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 20rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.setting-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 12rpx; |
||||||
|
.icon { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
|
||||||
|
text { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.setting-status { |
||||||
|
background: linear-gradient(90deg, #ffd650 0%, #f8a61a 100%); |
||||||
|
color: #fff; |
||||||
|
font-size: 24rpx; |
||||||
|
padding: 6rpx 16rpx; |
||||||
|
border-radius: 6rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.setting-desc { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #69686e; |
||||||
|
line-height: 48rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
padding: 32rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.setting-card { |
||||||
|
padding: 32rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 32rpx; |
||||||
|
padding: 32rpx; |
||||||
|
margin-bottom: 32rpx; |
||||||
|
box-shadow: 0rpx 4rpx 32rpx 0rpx rgba(0, 0, 0, 0.04); |
||||||
|
.setting-header { |
||||||
|
.setting-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 12rpx; |
||||||
|
.icon { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
|
||||||
|
text { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.setting-body { |
||||||
|
margin-top: 32rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
gap: 24rpx; |
||||||
|
.photo { |
||||||
|
width: 120rpx; |
||||||
|
height: 120rpx; |
||||||
|
border-radius: 16rpx; |
||||||
|
} |
||||||
|
.wrap { |
||||||
|
flex: 1; |
||||||
|
.name { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.date { |
||||||
|
margin-top: 24rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #69686e; |
||||||
|
} |
||||||
|
} |
||||||
|
.more { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #b073ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 功能按钮区 |
||||||
|
.action-buttons { |
||||||
|
display: flex; |
||||||
|
gap: 30rpx; |
||||||
|
margin-bottom: 56rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.action-btn { |
||||||
|
flex: 1; |
||||||
|
height: 320rpx; |
||||||
|
border-radius: 20rpx; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
gap: 20rpx; |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
&.primary { |
||||||
|
background: linear-gradient(180deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
|
||||||
|
.btn-text { |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
.corner-fold { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
width: 60rpx; |
||||||
|
height: 60rpx; |
||||||
|
background: linear-gradient(45deg, #e5d2ff 0%, #f6f8f9 50%, #f6f8f9 100%); |
||||||
|
border-radius: 0 0 0 18rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&.secondary { |
||||||
|
background: #fff; |
||||||
|
box-shadow: 0 2rpx 12rpx rgba(14, 0, 32, 0.19); |
||||||
|
|
||||||
|
.btn-text { |
||||||
|
color: #a855f7; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.btn-icon { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
width: 108rpx; |
||||||
|
height: 108rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.btn-text { |
||||||
|
font-size: 32rpx; |
||||||
|
font-weight: 500; |
||||||
|
} |
||||||
|
|
||||||
|
.history-section { |
||||||
|
.section-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
margin-bottom: 30rpx; |
||||||
|
|
||||||
|
.title-bar { |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #a855f7; |
||||||
|
border-radius: 4rpx; |
||||||
|
} |
||||||
|
|
||||||
|
text { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.history-empty { |
||||||
|
background: #fff; |
||||||
|
border-radius: 32rpx; |
||||||
|
padding: 30rpx; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
padding: 80rpx 0; |
||||||
|
gap: 24rpx; |
||||||
|
.icon { |
||||||
|
width: 64rpx; |
||||||
|
height: 64rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.empty-text { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #adacb2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.history-list { |
||||||
|
.list-item { |
||||||
|
position: relative; |
||||||
|
margin-top: 24rpx; |
||||||
|
border-radius: 32rpx; |
||||||
|
background-color: #fff; |
||||||
|
padding: 32rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
gap: 24rpx; |
||||||
|
.benchmark { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
padding-top: 8rpx; |
||||||
|
text-align: center; |
||||||
|
width: 124rpx; |
||||||
|
height: 64rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.photo { |
||||||
|
width: 140rpx; |
||||||
|
height: 140rpx; |
||||||
|
border-radius: 16rpx; |
||||||
|
} |
||||||
|
.wrap { |
||||||
|
flex: 1; |
||||||
|
.date { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.tag { |
||||||
|
margin-top: 16rpx; |
||||||
|
padding: 4rpx 12rpx; |
||||||
|
display: inline-block; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #b073ff; |
||||||
|
background: rgba(176, 115, 255, 0.16); |
||||||
|
border-radius: 6rpx 6rpx 6rpx 6rpx; |
||||||
|
} |
||||||
|
.rotate { |
||||||
|
margin-top: 28rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #adacb2; |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
.more { |
||||||
|
align-self: center; |
||||||
|
width: 44rpx; |
||||||
|
height: 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,35 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
background: '#fff', |
||||||
|
}, |
||||||
|
|
||||||
|
onLoad() { |
||||||
|
// 页面加载时的初始化
|
||||||
|
}, |
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
handleBack() { |
||||||
|
wx.navigateBack() |
||||||
|
}, |
||||||
|
|
||||||
|
// 新增记录
|
||||||
|
addRecord() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/patient/pages/noteAdd/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleHistory() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/patient/pages/noteHistory/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
comparePhotos() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/patient/pages/noteDiff/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,70 @@ |
|||||||
|
<navbar fixed title="突眼日记" custom-style="background:{{background}}"> |
||||||
|
<van-icon name="arrow-left" slot="left" size="18px" color="#000" bind:tap="handleBack" /> |
||||||
|
</navbar> |
||||||
|
|
||||||
|
<view class="container" style="padding-top:{{pageTop+20}}px"> |
||||||
|
<!-- 基准照片设置卡片 --> |
||||||
|
<view class="setting-card-empty" bindtap="addRecord"> |
||||||
|
<view class="setting-header"> |
||||||
|
<view class="setting-title"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon144.png?t={{Timestamp}}"></image> |
||||||
|
<text>基准照片设置</text> |
||||||
|
</view> |
||||||
|
<view class="setting-status">待设置</view> |
||||||
|
</view> |
||||||
|
<view class="setting-desc">请先上传一组完整的照片作为基准,后续记录将以此为参照进行对比。</view> |
||||||
|
</view> |
||||||
|
<view class="setting-card"> |
||||||
|
<view class="setting-header"> |
||||||
|
<view class="setting-title"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon143.png?t={{Timestamp}}"></image> |
||||||
|
<text>基准照片设置</text> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="setting-body"> |
||||||
|
<image class="photo" src="{{imageUrl}}icon143.png?t={{Timestamp}}"></image> |
||||||
|
<view class="wrap"> |
||||||
|
<view class="name">已设置基准照</view> |
||||||
|
<view class="date">记录日期:2026-04-01</view> |
||||||
|
</view> |
||||||
|
<view class="more">查看</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 功能按钮区 --> |
||||||
|
<view class="action-buttons"> |
||||||
|
<view class="action-btn primary" bindtap="addRecord"> |
||||||
|
<view class="corner-fold"></view> |
||||||
|
<image class="btn-icon" src="{{imageUrl}}icon147.png?t={{Timestamp}}"></image> |
||||||
|
<text class="btn-text">新增记录</text> |
||||||
|
</view> |
||||||
|
<view class="action-btn secondary" bindtap="comparePhotos"> |
||||||
|
<image class="btn-icon" src="{{imageUrl}}icon145.png?t={{Timestamp}}"></image> |
||||||
|
<text class="btn-text">照片对比</text> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 历史记录 --> |
||||||
|
<view class="history-section"> |
||||||
|
<view class="section-title"> |
||||||
|
<view class="title-bar"></view> |
||||||
|
<text>历史记录</text> |
||||||
|
</view> |
||||||
|
<view class="history-empty"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon146.png?t={{Timestamp}}"></image> |
||||||
|
<text class="empty-text">暂无记录,点击上方按钮开始</text> |
||||||
|
</view> |
||||||
|
<view class="history-list"> |
||||||
|
<view class="list-item" bind:tap="handleHistory"> |
||||||
|
<view class="benchmark" style="background: url('{{imageUrl}}bg50.png?t={{Timestamp}}') no-repeat top center/100%">基准照</view> |
||||||
|
<image class="photo" src="{{imageUrl}}icon143.png?t={{Timestamp}}"></image> |
||||||
|
<view class="wrap"> |
||||||
|
<view class="date">2026-04-01</view> |
||||||
|
<view class="tag">替妥尤单抗:2</view> |
||||||
|
<view class="rotate">已上传1个角度</view> |
||||||
|
</view> |
||||||
|
<image class="more" src="{{imageUrl}}icon148.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
{ |
||||||
|
"usingComponents": { |
||||||
|
"navbar": "/components/navbar/index", |
||||||
|
"van-icon": "@vant/weapp/icon/index", |
||||||
|
"popup": "/components/popup/index", |
||||||
|
"noteImagePreview": "/components/noteImagePreview/index", |
||||||
|
"camera": "/patient/components/camera/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "记录新照片" |
||||||
|
} |
||||||
@ -0,0 +1,309 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
|
||||||
|
.page { |
||||||
|
.benchmark { |
||||||
|
margin-top: 32rpx; |
||||||
|
padding: 0 40rpx 28rpx; |
||||||
|
.checkbox { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
.wx-checkbox-input { |
||||||
|
background: rgba(173, 172, 178, 0.36); |
||||||
|
border-color: transparent; |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.form { |
||||||
|
margin: 0 40rpx 24rpx; |
||||||
|
padding: 32rpx; |
||||||
|
background: #ffffff; |
||||||
|
border-radius: 32rpx 32rpx 32rpx 32rpx; |
||||||
|
.form-title { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.form-title-gap { |
||||||
|
margin-top: 48rpx; |
||||||
|
} |
||||||
|
.select { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
padding: 26rpx 32rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
.content { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
&:empty::after { |
||||||
|
content: attr(data-place); |
||||||
|
color: rgba(173, 172, 178, 0.6); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.dobule { |
||||||
|
margin-top: 44rpx; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
display: flex; |
||||||
|
gap: 26rpx; |
||||||
|
.item { |
||||||
|
.name { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
.i-content { |
||||||
|
margin-top: 24rpx; |
||||||
|
padding: 26rpx 32rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
.num { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.container { |
||||||
|
margin-top: 72rpx; |
||||||
|
padding: 32rpx 40rpx 0; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 32rpx 32rpx 0 0; |
||||||
|
.c-title { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.options { |
||||||
|
margin-top: 30rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 22rpx; |
||||||
|
.btn { |
||||||
|
flex: 1; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
padding: 26rpx; |
||||||
|
border-radius: 18rpx; |
||||||
|
.icon { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
font-size: 32rpx; |
||||||
|
&.btn1 { |
||||||
|
color: #b982ff; |
||||||
|
background: rgba(185, 130, 255, 0.12); |
||||||
|
} |
||||||
|
&.btn2 { |
||||||
|
color: #ffffff; |
||||||
|
background: linear-gradient(180deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.card { |
||||||
|
margin-top: 32rpx; |
||||||
|
padding: 32rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
.card-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
.order { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #b982ff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: rgba(185, 130, 255, 0.1); |
||||||
|
border-radius: 8rpx 8rpx 8rpx 8rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.upload-container { |
||||||
|
margin-top: 32rpx; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(3, 1fr); |
||||||
|
justify-content: space-between; |
||||||
|
gap: 24rpx; |
||||||
|
.upload-item { |
||||||
|
$degs: ( |
||||||
|
1: -45deg, |
||||||
|
2: 0deg, |
||||||
|
3: 45deg, |
||||||
|
4: -90deg, |
||||||
|
5: 90deg, |
||||||
|
6: -135deg, |
||||||
|
7: -180deg, |
||||||
|
8: 135deg, |
||||||
|
); |
||||||
|
@each $index, $deg in $degs { |
||||||
|
&:nth-of-type(#{$index}) { |
||||||
|
.arrow { |
||||||
|
transform: rotate(#{$deg}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&:nth-of-type(3), |
||||||
|
&:nth-of-type(5), |
||||||
|
&:nth-of-type(8) { |
||||||
|
.name { |
||||||
|
flex-direction: row-reverse; |
||||||
|
} |
||||||
|
} |
||||||
|
.upload-place { |
||||||
|
border: 1px dashed #b982ff; |
||||||
|
border-radius: 16rpx; |
||||||
|
width: 186rpx; |
||||||
|
height: 186rpx; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
gap: 24rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
.icon { |
||||||
|
width: 52rpx; |
||||||
|
height: 52rpx; |
||||||
|
} |
||||||
|
.name { |
||||||
|
font-size: 24rpx; |
||||||
|
display: flex; |
||||||
|
align-items: flex-end; |
||||||
|
gap: 8rpx; |
||||||
|
color: #211d2e; |
||||||
|
line-height: 1; |
||||||
|
.arrow { |
||||||
|
width: 24rpx; |
||||||
|
height: 24rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.upload-preview { |
||||||
|
position: relative; |
||||||
|
width: 186rpx; |
||||||
|
height: 186rpx; |
||||||
|
.photo { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
border-radius: 16rpx; |
||||||
|
} |
||||||
|
.status { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
border-radius: 16rpx; |
||||||
|
background: rgba(9, 9, 9, 0.45); |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
.icon { |
||||||
|
margin-top: 32rpx; |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 8rpx; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #ffffff; |
||||||
|
} |
||||||
|
.guide { |
||||||
|
margin-top: 26rpx; |
||||||
|
width: 100%; |
||||||
|
height: 40rpx; |
||||||
|
text-align: center; |
||||||
|
line-height: 40rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffffff; |
||||||
|
border-radius: 0 0 16rpx 16rpx; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.card3 .upload-container { |
||||||
|
.upload-item:nth-child(1) { |
||||||
|
grid-area: 1 / 1; |
||||||
|
} /* 左上 */ |
||||||
|
.upload-item:nth-child(2) { |
||||||
|
grid-area: 1 / 2; |
||||||
|
} /* 上 */ |
||||||
|
.upload-item:nth-child(3) { |
||||||
|
grid-area: 1 / 3; |
||||||
|
} /* 右上 */ |
||||||
|
.upload-item:nth-child(4) { |
||||||
|
grid-area: 2 / 1; |
||||||
|
} /* 左 */ |
||||||
|
.upload-item:nth-child(5) { |
||||||
|
grid-area: 2 / 3; |
||||||
|
} /* 右 */ |
||||||
|
.upload-item:nth-child(6) { |
||||||
|
grid-area: 3 / 1; |
||||||
|
} /* 左下 */ |
||||||
|
.upload-item:nth-child(7) { |
||||||
|
grid-area: 3 / 2; |
||||||
|
} /* 下 */ |
||||||
|
.upload-item:nth-child(8) { |
||||||
|
grid-area: 3 / 3; |
||||||
|
} /* 右下 */ |
||||||
|
} |
||||||
|
} |
||||||
|
.c-footer { |
||||||
|
position: sticky; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
background-color: #fff; |
||||||
|
padding: 32rpx 0 60rpx; |
||||||
|
.btn { |
||||||
|
height: 88rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #ffffff; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
box-shadow: 0rpx 16rpx 32rpx 0rpx rgba(185, 130, 255, 0.25); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.place { |
||||||
|
color: rgba(173, 172, 178, 0.6); |
||||||
|
} |
||||||
@ -0,0 +1,132 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
popupShow: false, |
||||||
|
popupType: 'popup16', // 提示保存弹窗
|
||||||
|
popupParams: { |
||||||
|
close: false, |
||||||
|
position: 'bottom', |
||||||
|
} as any, |
||||||
|
|
||||||
|
imagePreview: false, |
||||||
|
|
||||||
|
imageSrc: '', |
||||||
|
|
||||||
|
cameraList: { |
||||||
|
frontend: [ |
||||||
|
{ |
||||||
|
name: '睁眼', |
||||||
|
type: 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '闭眼', |
||||||
|
type: 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '仰头', |
||||||
|
type: 3, |
||||||
|
}, |
||||||
|
], |
||||||
|
backend: [ |
||||||
|
{ |
||||||
|
name: '左侧-90°', |
||||||
|
type: 4, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '右侧-90°', |
||||||
|
type: 5, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '左侧-45°', |
||||||
|
type: 6, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '右侧-45°', |
||||||
|
type: 7, |
||||||
|
}, |
||||||
|
], |
||||||
|
other: [ |
||||||
|
{ |
||||||
|
name: '左上', |
||||||
|
type: 8, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '向上', |
||||||
|
type: 9, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '左下', |
||||||
|
type: 10, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '向左', |
||||||
|
type: 11, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '向右', |
||||||
|
type: 12, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '右上', |
||||||
|
type: 13, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '向下', |
||||||
|
type: 14, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '右下', |
||||||
|
type: 15, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
onLoad() {}, |
||||||
|
handleDemo() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/patient/pages/noteDemo/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleImageRetake() { |
||||||
|
this.setData({ |
||||||
|
imagePreview: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleImageDel() { |
||||||
|
this.setData({ |
||||||
|
imagePreview: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleCamera(e) { |
||||||
|
const { type } = e.currentTarget.dataset |
||||||
|
const cameraComponent = this.selectComponent('#camera-component') |
||||||
|
cameraComponent.handleSelect(type) |
||||||
|
}, |
||||||
|
onUploadSuccess(e) { |
||||||
|
this.setData({ |
||||||
|
imageSrc: e.detail.url, |
||||||
|
}) |
||||||
|
}, |
||||||
|
onUploadError(e) { |
||||||
|
console.log('DEBUGPRINT[221]: index.ts:34: e=', e) |
||||||
|
}, |
||||||
|
handlePreview() { |
||||||
|
this.selectComponent('#note-image-preview').handlePreview(this.data.imageSrc) |
||||||
|
}, |
||||||
|
handlePopupOk() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handlePopupCancel() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleBack() { |
||||||
|
wx.navigateBack() |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,146 @@ |
|||||||
|
<page-meta page-style="{{ popupShow || visible ? 'overflow: hidden;' : '' }}" /> |
||||||
|
|
||||||
|
<navbar fixed title="记录新照片" custom-style="background:{{background}}"> |
||||||
|
<van-icon name="arrow-left" slot="left" size="18px" color="#000" bind:tap="handleBack" /> |
||||||
|
</navbar> |
||||||
|
|
||||||
|
<view class="page" style="padding-top: {{pageTop+20}}px;"> |
||||||
|
<view class="benchmark"> |
||||||
|
<checkbox class="checkbox" color="#fff">设置为基准记录,用于对比</checkbox> |
||||||
|
</view> |
||||||
|
<view class="form"> |
||||||
|
<view class="form-title">记录日期</view> |
||||||
|
<picker mode="date"> |
||||||
|
<view class="select"> |
||||||
|
<view class="content" data-place="请选择记录日期"></view> |
||||||
|
<van-icon class="more" name="arrow-down" /> |
||||||
|
</view> |
||||||
|
</picker> |
||||||
|
<view class="form-title form-title-gap">当前记录对应的替妥尤单抗使用次数</view> |
||||||
|
<picker mode="selector"> |
||||||
|
<view class="select"> |
||||||
|
<view class="content" data-place="请选择使用次数"></view> |
||||||
|
<van-icon class="more" name="arrow-down" /> |
||||||
|
</view> |
||||||
|
</picker> |
||||||
|
</view> |
||||||
|
<view class="form"> |
||||||
|
<view class="form-title">记录本次突眼度</view> |
||||||
|
<view class="dobule"> |
||||||
|
<view class="item"> |
||||||
|
<view class="name">右眼</view> |
||||||
|
<view class="i-content"> |
||||||
|
<input type="digit" class="num" placeholder-class="place" placeholder="填写" /> |
||||||
|
MM |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="name">眶间距</view> |
||||||
|
<view class="i-content"> |
||||||
|
<input type="digit" class="num" placeholder-class="place" placeholder="填写" /> |
||||||
|
MM |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="name">左眼</view> |
||||||
|
<view class="i-content"> |
||||||
|
<input type="digit" class="num" placeholder-class="place" placeholder="填写" /> |
||||||
|
MM |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="container"> |
||||||
|
<view class="c-title">持续追踪、固定位置拍摄,以便对比评估变化</view> |
||||||
|
<view class="options"> |
||||||
|
<view class="btn btn1" bind:tap="handleDemo"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon149.png?t={{Timestamp}}"></image> |
||||||
|
标准拍摄示范 |
||||||
|
</view> |
||||||
|
<view class="btn btn2"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon150.png?t={{Timestamp}}"></image> |
||||||
|
一键顺序拍摄 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title"> |
||||||
|
<view class="order">1</view> |
||||||
|
正面 |
||||||
|
</view> |
||||||
|
<view class="upload-container"> |
||||||
|
<view class="upload-item" wx:for="{{cameraList.frontend}}" wx:key="index"> |
||||||
|
<view class="upload-preview" wx:if="{{imageSrc}}" bind:tap="handlePreview"> |
||||||
|
<image class="photo" src="{{imageSrc}}"></image> |
||||||
|
<view class="status"> |
||||||
|
<image class="icon" src="/images/icon164.png"></image> |
||||||
|
<view class="content">不符合规范</view> |
||||||
|
<view class="guide">重新上传</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="upload-place" wx:else bind:tap="handleCamera" data-type="{{item.type}}"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon151.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.name}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title"> |
||||||
|
<view class="order">2</view> |
||||||
|
侧面 |
||||||
|
</view> |
||||||
|
<view class="upload-container"> |
||||||
|
<view class="upload-item" wx:for="{{cameraList.backend}}" wx:key="index"> |
||||||
|
<view class="upload-preview" wx:if="{{imageSrc}}" bind:tap="handlePreview"> |
||||||
|
<image class="photo" src="{{imageSrc}}"></image> |
||||||
|
</view> |
||||||
|
<view class="upload-place" wx:else bind:tap="handleCamera" data-type="{{item.type}}"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon151.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.name}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card card3"> |
||||||
|
<view class="card-title"> |
||||||
|
<view class="order">3</view> |
||||||
|
眼球运动八个方向 |
||||||
|
</view> |
||||||
|
<view class="upload-container"> |
||||||
|
<view class="upload-item" wx:for="{{cameraList.other}}" wx:key="index"> |
||||||
|
<view class="upload-preview" wx:if="{{imageSrc}}" bind:tap="handlePreview"> |
||||||
|
<image class="photo" src="{{imageSrc}}"></image> |
||||||
|
</view> |
||||||
|
<view class="upload-place" wx:else bind:tap="handleCamera" data-type="{{item.type}}"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon151.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name"> |
||||||
|
<image class="arrow" src="/images/icon167.png"></image> |
||||||
|
{{item.name}} |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="c-footer"> |
||||||
|
<view class="btn">诺和益托管视频</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<camera id="camera-component" bind:uploadsuccess="onUploadSuccess" bind:uploaderror="onUploadError" /> |
||||||
|
|
||||||
|
<noteImagePreview |
||||||
|
id="note-image-preview" |
||||||
|
visible="{{imagePreview}}" |
||||||
|
src="{{imageUrl}}note-demo10.png?t={{Timestamp}}" |
||||||
|
bind:delete="handleImageDel" |
||||||
|
bind:retake="handleImageRetake" |
||||||
|
></noteImagePreview> |
||||||
|
|
||||||
|
<popup |
||||||
|
show="{{popupShow}}" |
||||||
|
type="{{popupType}}" |
||||||
|
params="{{popupParams}}" |
||||||
|
bind:ok="handlePopupOk" |
||||||
|
bind:cancel="handlePopupCancel" |
||||||
|
></popup> |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"usingComponents": { |
||||||
|
"navbar": "/components/navbar/index", |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "标准拍照示范" |
||||||
|
} |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
.page { |
||||||
|
padding: 0 40rpx 40rpx; |
||||||
|
.card { |
||||||
|
margin-bottom: 32rpx; |
||||||
|
padding: 116rpx 32rpx 32rpx; |
||||||
|
border-radius: 32rpx; |
||||||
|
background-color: #fff; |
||||||
|
.tip { |
||||||
|
background: #f7f1ff; |
||||||
|
padding: 32rpx; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
border: 2rpx solid #b982ff; |
||||||
|
} |
||||||
|
.item { |
||||||
|
margin-top: 36rpx; |
||||||
|
.title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 12rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 6rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: linear-gradient(344deg, #ffbcf9 0%, #b982ff 100%); |
||||||
|
border-radius: 6rpx 6rpx 6rpx 6rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 22rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #69686e; |
||||||
|
line-height: 48rpx; |
||||||
|
} |
||||||
|
.photo { |
||||||
|
margin-top: 32rpx; |
||||||
|
width: 100%; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
&.card-dobule { |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(2, 1fr); |
||||||
|
gap: 48rpx 30rpx; |
||||||
|
.item { |
||||||
|
margin: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: {}, |
||||||
|
onLoad() {}, |
||||||
|
handleBack() { |
||||||
|
wx.navigateBack() |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,86 @@ |
|||||||
|
<navbar fixed title="记录新照片" custom-style="background:{{background}}"> |
||||||
|
<van-icon name="arrow-left" slot="left" size="18px" color="#000" bind:tap="handleBack" /> |
||||||
|
</navbar> |
||||||
|
|
||||||
|
<view |
||||||
|
class="page" |
||||||
|
style="background: url('{{imageUrl}}bg51.png?t={{Timestamp}}') no-repeat top center/100% 716rpx;padding-top: {{pageTop+120}}px;" |
||||||
|
> |
||||||
|
<view class="card" style="background: #fff url('{{imageUrl}}bg52.png?t={{Timestamp}}') no-repeat top center/100% 210rpx"> |
||||||
|
<view class="tip">拍摄时,正对镜头,面部居中,露出完整双眼及眼眶;光线均匀无阴影。</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面睁眼照</view> |
||||||
|
<view class="content">平视,目光看向镜头方向,自然睁眼,不眯眼、不瞪眼。</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面闭眼照</view> |
||||||
|
<view class="content">正对镜头,面部居中,自然放松,双眼轻轻闭合,不皱眉、不挤眼。</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo2.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面仰头照</view> |
||||||
|
<view class="content"> |
||||||
|
拍摄时,正对镜头,面部居中,头部自然向上仰至约 45°,双眼同步平视,保持自然睁眼、不眯眼。 |
||||||
|
</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo3.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card" style="background: #fff url('{{imageUrl}}bg53.png?t={{Timestamp}}') no-repeat top center/100% 210rpx"> |
||||||
|
<view class="tip">拍摄时,头部保持水平,不仰头、不低头,双眼平视前方;光线均匀无阴影。</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">左侧-90°</view> |
||||||
|
<view class="content">身体与头部完全转向右侧,呈标准 90° 侧面,仅可见左侧眼睛。</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo4.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">右侧-90°</view> |
||||||
|
<view class="content">身体与头部完全转向左侧,呈标准 90° 侧面,仅可见右侧眼睛。</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo5.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">左侧-45°</view> |
||||||
|
<view class="content">身体与头部转向右前方 45°。</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo6.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">右侧-45°</view> |
||||||
|
<view class="content">身体与头部转向左前方 45°</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo7.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card card-dobule" style="background: #fff url('{{imageUrl}}bg54.png?t={{Timestamp}}') no-repeat top center/100% 210rpx"> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛上看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo8.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛下看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo9.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛左看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo10.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛右看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo11.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛左上看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo12.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛右上看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo13.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛左下看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo14.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<view class="title">正面眼睛右下看</view> |
||||||
|
<image class="photo" mode="widthFix" src="{{imageUrl}}note-demo15.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"navigationStyle": "default", |
||||||
|
"usingComponents": { |
||||||
|
"van-icon": "@vant/weapp/icon/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "照片对比分析" |
||||||
|
} |
||||||
@ -0,0 +1,284 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
.page-none { |
||||||
|
padding: 290rpx 76rpx 0; |
||||||
|
.icon { |
||||||
|
display: block; |
||||||
|
margin: 0 auto; |
||||||
|
width: 458rpx; |
||||||
|
height: 218rpx; |
||||||
|
} |
||||||
|
.title { |
||||||
|
margin-top: 26rpx; |
||||||
|
font-size: 38rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 24rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #69686e; |
||||||
|
line-height: 48rpx; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.btn { |
||||||
|
margin: 88rpx 0 0; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #ffffff; |
||||||
|
height: 88rpx; |
||||||
|
text-align: center; |
||||||
|
line-height: 88rpx; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
box-shadow: 0rpx 16rpx 32rpx 0rpx rgba(185, 130, 255, 0.25); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.page { |
||||||
|
padding-bottom: 80rpx; |
||||||
|
.page-tip { |
||||||
|
padding: 24rpx 28rpx; |
||||||
|
background-color: #fff7e9; |
||||||
|
display: flex; |
||||||
|
.icon { |
||||||
|
margin-top: 6rpx; |
||||||
|
flex-shrink: 0; |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-left: 16rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.form { |
||||||
|
margin: 32rpx 40rpx 0; |
||||||
|
padding: 38rpx 32rpx 32rpx; |
||||||
|
background: #ffffff; |
||||||
|
border-radius: 32rpx 32rpx 32rpx 32rpx; |
||||||
|
.form-item { |
||||||
|
margin-bottom: 48rpx; |
||||||
|
&:last-of-type { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
.title { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.select { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
padding: 26rpx 32rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
.content { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
&:empty::after { |
||||||
|
content: attr(data-place); |
||||||
|
color: rgba(173, 172, 178, 0.6); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.multiple { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(2, 1fr); |
||||||
|
gap: 24rpx 22rpx; |
||||||
|
.item { |
||||||
|
padding: 16rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
&.active { |
||||||
|
color: #fff; |
||||||
|
background: linear-gradient(180deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.container { |
||||||
|
margin: 76rpx 40rpx 0; |
||||||
|
.title { |
||||||
|
padding-bottom: 40rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
.date { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #adacb2; |
||||||
|
font-weight: normal; |
||||||
|
align-self: flex-end; |
||||||
|
} |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.card { |
||||||
|
display: flex; |
||||||
|
.aside { |
||||||
|
flex-shrink: 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
.line-bottom { |
||||||
|
border: 1px dashed #b982ff; |
||||||
|
} |
||||||
|
.line-bottom { |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
.circle { |
||||||
|
position: relative; |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
border-radius: 50%; |
||||||
|
background: rgba(185, 130, 255, 0.29); |
||||||
|
&::after { |
||||||
|
position: relative; |
||||||
|
top: 50%; |
||||||
|
left: 50%; |
||||||
|
transform: translate(-50%, -50%); |
||||||
|
display: block; |
||||||
|
content: ''; |
||||||
|
width: 18rpx; |
||||||
|
height: 18rpx; |
||||||
|
border-radius: 50%; |
||||||
|
background-color: #b982ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.c-container { |
||||||
|
margin-top: -6rpx; |
||||||
|
margin-left: 14rpx; |
||||||
|
flex: 1; |
||||||
|
padding-bottom: 48rpx; |
||||||
|
.c-header { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
.date { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
.btn { |
||||||
|
width: 164rpx; |
||||||
|
height: 56rpx; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
border-radius: 124rpx 124rpx 124rpx 124rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
gap: 12rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #ffffff; |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.tags { |
||||||
|
margin-top: 12rpx; |
||||||
|
.tag { |
||||||
|
display: inline-block; |
||||||
|
margin-right: 16rpx; |
||||||
|
padding: 2rpx 12rpx; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 32rpx; |
||||||
|
border-radius: 6rpx; |
||||||
|
&.tag1 { |
||||||
|
background: rgba(255, 163, 0, 0.17); |
||||||
|
color: #ffa300; |
||||||
|
} |
||||||
|
&.tag2 { |
||||||
|
background: rgba(176, 115, 255, 0.16); |
||||||
|
color: #b073ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.photo-card { |
||||||
|
margin-top: 24rpx; |
||||||
|
.photo { |
||||||
|
border-radius: 32rpx 32rpx 0 0; |
||||||
|
height: 352rpx; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
.row { |
||||||
|
display: flex; |
||||||
|
gap: 24rpx; |
||||||
|
text-align: center; |
||||||
|
border-radius: 0 0 32rpx 32rpx; |
||||||
|
background-color: #fff; |
||||||
|
.col { |
||||||
|
padding: 24rpx; |
||||||
|
flex: 1; |
||||||
|
.name { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 16rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: baseline; |
||||||
|
gap: 8rpx; |
||||||
|
.num { |
||||||
|
font-size: 56rpx; |
||||||
|
color: #b073ff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.sub { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
margin-top: 46rpx; |
||||||
|
.btn1 { |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #ffffff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: {}, |
||||||
|
onLoad() {}, |
||||||
|
handleEdit() { |
||||||
|
wx.navigateTo({ |
||||||
|
url: '/patient/pages/noteDiffEdit/index', |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
<view class="page-none" wx:if="{{false}}"> |
||||||
|
<image class="icon" src="{{imageUrl}}none3.png?t={{Timestamp}}"></image> |
||||||
|
<view class="title">未设置基准照片</view> |
||||||
|
<view class="content"> |
||||||
|
请先上传一组照片并将其设为基准 |
||||||
|
<view></view> |
||||||
|
以便进行对比分析 |
||||||
|
</view> |
||||||
|
<view class="btn">去设置</view> |
||||||
|
</view> |
||||||
|
<view class="page"> |
||||||
|
<view class="page-tip"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon154.png?t={{Timestamp}}"></image> |
||||||
|
<view class="content"> |
||||||
|
您可以同时选择多个日期,系统将按时间顺序排列照片。点击右上角按钮可预览并保存生成的对比长图。 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="form"> |
||||||
|
<view class="form-item"> |
||||||
|
<view class="title">选择对比角度</view> |
||||||
|
<picker mode="selector"> |
||||||
|
<view class="select"> |
||||||
|
<view class="content" data-place="请选择对比角度"></view> |
||||||
|
<van-icon class="more" name="arrow-down" /> |
||||||
|
</view> |
||||||
|
</picker> |
||||||
|
</view> |
||||||
|
<view class="form-item"> |
||||||
|
<view class="title">选择对比日期(可多选)</view> |
||||||
|
<view class="multiple"> |
||||||
|
<view class="item {{index==0&&'active'}}" wx:for="{{8}}" wx:key="index">2026-04-02</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="container"> |
||||||
|
<view class="title"> |
||||||
|
正面睁眼时间线对比 |
||||||
|
<view class="date">生成日期:2026-04-02</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="aside"> |
||||||
|
<view class="circle"></view> |
||||||
|
<view class="line-bottom"></view> |
||||||
|
</view> |
||||||
|
<view class="c-container"> |
||||||
|
<view class="c-header"> |
||||||
|
<view class="date">基准照片 2026-04-02</view> |
||||||
|
</view> |
||||||
|
<view class="tags"> |
||||||
|
<view class="tag tag1">基准照片</view> |
||||||
|
<view class="tag tag2">替妥尤单抗:2</view> |
||||||
|
</view> |
||||||
|
<view class="photo-card"> |
||||||
|
<image class="photo" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="row"> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">右眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">眶间距</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">左眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<view class="btn1" bind:tap="handleEdit">生成对比图</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
{ |
||||||
|
"navigationStyle": "default", |
||||||
|
"usingComponents": { |
||||||
|
"van-icon": "@vant/weapp/icon/index", |
||||||
|
"imageMerge": "/patient/components/image-merge/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "照片对比分析" |
||||||
|
} |
||||||
@ -0,0 +1,157 @@ |
|||||||
|
page { |
||||||
|
background-color: #f6f8f9; |
||||||
|
} |
||||||
|
.page { |
||||||
|
padding-bottom: 80rpx; |
||||||
|
.container { |
||||||
|
margin: 40rpx 40rpx 0; |
||||||
|
.title { |
||||||
|
padding-bottom: 40rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
.date { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #adacb2; |
||||||
|
font-weight: normal; |
||||||
|
align-self: flex-end; |
||||||
|
} |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.card { |
||||||
|
display: flex; |
||||||
|
.aside { |
||||||
|
flex-shrink: 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
.line-bottom { |
||||||
|
border: 1px dashed #b982ff; |
||||||
|
} |
||||||
|
.line-bottom { |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
.circle { |
||||||
|
position: relative; |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
border-radius: 50%; |
||||||
|
background: rgba(185, 130, 255, 0.29); |
||||||
|
&::after { |
||||||
|
position: relative; |
||||||
|
top: 50%; |
||||||
|
left: 50%; |
||||||
|
transform: translate(-50%, -50%); |
||||||
|
display: block; |
||||||
|
content: ''; |
||||||
|
width: 18rpx; |
||||||
|
height: 18rpx; |
||||||
|
border-radius: 50%; |
||||||
|
background-color: #b982ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.c-container { |
||||||
|
margin-top: -6rpx; |
||||||
|
margin-left: 14rpx; |
||||||
|
flex: 1; |
||||||
|
padding-bottom: 48rpx; |
||||||
|
.c-header { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
.date { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
} |
||||||
|
.tags { |
||||||
|
margin-top: 12rpx; |
||||||
|
.tag { |
||||||
|
display: inline-block; |
||||||
|
margin-right: 16rpx; |
||||||
|
padding: 2rpx 12rpx; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 32rpx; |
||||||
|
border-radius: 6rpx; |
||||||
|
&.tag1 { |
||||||
|
background: rgba(255, 163, 0, 0.17); |
||||||
|
color: #ffa300; |
||||||
|
} |
||||||
|
&.tag2 { |
||||||
|
background: rgba(176, 115, 255, 0.16); |
||||||
|
color: #b073ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.photo-card { |
||||||
|
margin-top: 24rpx; |
||||||
|
position: relative; |
||||||
|
.photo { |
||||||
|
border-radius: 32rpx 32rpx 0 0; |
||||||
|
height: 352rpx; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
.mask { |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
height: 85rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
gap: 16rpx; |
||||||
|
background: rgba(0, 0, 0, 0.3); |
||||||
|
font-size: 32rpx; |
||||||
|
color: #ffffff; |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
margin-top: 46rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 22rpx; |
||||||
|
.btn1 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #b982ff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
border: 1px solid #b982ff; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
.btn2 { |
||||||
|
flex: 1; |
||||||
|
height: 88rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #ffffff; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: linear-gradient(0deg, #e98ff8 0%, #b073ff 100%); |
||||||
|
border-radius: 100rpx 100rpx 100rpx 100rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: {}, |
||||||
|
onLoad() {}, |
||||||
|
handleMergePreview() { |
||||||
|
const mergeComponent = this.selectComponent('#merge') |
||||||
|
console.log("DEBUGPRINT[224]: index.ts:7: mergeComponent=", mergeComponent) |
||||||
|
if (mergeComponent) { |
||||||
|
mergeComponent.mergeImages([ |
||||||
|
{ src: 'https://picsum.photos/400/300', time: '2024-01-01 10:00' }, |
||||||
|
{ src: 'https://picsum.photos/400/301', time: '2024-01-01 12:00' }, |
||||||
|
{ src: 'https://picsum.photos/400/302' }, |
||||||
|
]) |
||||||
|
} |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
<view class="page"> |
||||||
|
<view class="container"> |
||||||
|
<view class="title"> |
||||||
|
正面睁眼时间线对比 |
||||||
|
<view class="date">生成日期:2026-04-02</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="aside"> |
||||||
|
<view class="circle"></view> |
||||||
|
<view class="line-bottom"></view> |
||||||
|
</view> |
||||||
|
<view class="c-container"> |
||||||
|
<view class="c-header"> |
||||||
|
<view class="date">基准照片 2026-04-02</view> |
||||||
|
</view> |
||||||
|
<view class="tags"> |
||||||
|
<view class="tag tag1">基准照片</view> |
||||||
|
<view class="tag tag2">替妥尤单抗:2</view> |
||||||
|
</view> |
||||||
|
<view class="photo-card"> |
||||||
|
<image class="photo" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="mask" wx:if="{{false}}"> |
||||||
|
<image class="icon" src="/images/icon165.png"></image> |
||||||
|
点击裁剪 |
||||||
|
</view> |
||||||
|
<view class="mask" wx:else> |
||||||
|
<image class="icon" src="/images/icon166.png"></image> |
||||||
|
点击还原 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<view class="btn1" bind:tap="handleMergePreview">对比图预览</view> |
||||||
|
<view class="btn2">保存到相册</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<imageMerge id="merge" bindsave="onMergeSave" binderror="onMergeError" /> |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
{ |
||||||
|
"usingComponents": { |
||||||
|
"navbar": "/components/navbar/index", |
||||||
|
"van-icon": "@vant/weapp/icon/index", |
||||||
|
"popup": "/components/popup/index" |
||||||
|
}, |
||||||
|
"navigationBarTitleText": "记录" |
||||||
|
} |
||||||
@ -0,0 +1,183 @@ |
|||||||
|
.page { |
||||||
|
.header { |
||||||
|
padding: 52rpx 32rpx 40rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
.wrap { |
||||||
|
.date { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.tags { |
||||||
|
margin-top: 16rpx; |
||||||
|
.tag { |
||||||
|
display: inline-block; |
||||||
|
margin-right: 16rpx; |
||||||
|
padding: 2rpx 12rpx; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #ffa300; |
||||||
|
line-height: 32rpx; |
||||||
|
border-radius: 6rpx; |
||||||
|
&.tag1 { |
||||||
|
background: rgba(255, 163, 0, 0.17); |
||||||
|
color: #ffa300; |
||||||
|
} |
||||||
|
&.tag2 { |
||||||
|
background: rgba(176, 115, 255, 0.16); |
||||||
|
color: #b073ff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.opt { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 24rpx; |
||||||
|
.item { |
||||||
|
width: 64rpx; |
||||||
|
height: 64rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: #ffffff; |
||||||
|
border-radius: 50%; |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.container { |
||||||
|
padding: 40rpx; |
||||||
|
border-radius: 32rpx 32rpx 0 0; |
||||||
|
background-color: #fff; |
||||||
|
.tip-card { |
||||||
|
padding: 24rpx 32rpx; |
||||||
|
border-radius: 32rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
background: #fff7e9; |
||||||
|
gap: 16rpx; |
||||||
|
.tip-icon { |
||||||
|
margin-top: 6rpx; |
||||||
|
align-self: flex-start; |
||||||
|
flex-shrink: 0; |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
} |
||||||
|
.wrap { |
||||||
|
flex: 1; |
||||||
|
line-height: 44rpx; |
||||||
|
.title { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffa300; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.content { |
||||||
|
font-size: 24rpx; |
||||||
|
color: #ffa300; |
||||||
|
} |
||||||
|
} |
||||||
|
.btn { |
||||||
|
flex-shrink: 0; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ffffff; |
||||||
|
width: 148rpx; |
||||||
|
height: 56rpx; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
background: #ffa300; |
||||||
|
border-radius: 92rpx 92rpx 92rpx 92rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.banner { |
||||||
|
margin-top: 24rpx; |
||||||
|
padding: 32rpx; |
||||||
|
background: #f6f8f9; |
||||||
|
border-radius: 32rpx 32rpx 32rpx 32rpx; |
||||||
|
border: 2rpx solid #ffffff; |
||||||
|
.title { |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.row { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: flex; |
||||||
|
gap: 24rpx; |
||||||
|
text-align: center; |
||||||
|
.col { |
||||||
|
padding: 24rpx; |
||||||
|
flex: 1; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 16rpx; |
||||||
|
.name { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
line-height: 32rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
margin-top: 16rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: baseline; |
||||||
|
gap: 8rpx; |
||||||
|
.num { |
||||||
|
font-size: 56rpx; |
||||||
|
color: #b073ff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
.sub { |
||||||
|
font-size: 28rpx; |
||||||
|
color: #211d2e; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.card { |
||||||
|
margin-top: 48rpx; |
||||||
|
.card-title { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
gap: 16rpx; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #211d2e; |
||||||
|
font-weight: bold; |
||||||
|
&::before { |
||||||
|
content: ''; |
||||||
|
width: 8rpx; |
||||||
|
height: 32rpx; |
||||||
|
background: #b982ff; |
||||||
|
border-radius: 44rpx 44rpx 44rpx 44rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.card-container { |
||||||
|
margin-top: 24rpx; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: repeat(2, 320rpx); |
||||||
|
justify-content: space-between; |
||||||
|
gap: 30rpx; |
||||||
|
.card-item { |
||||||
|
.photo { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: 320rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
} |
||||||
|
.name{ |
||||||
|
margin-top: 16rpx; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #ADACB2; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
const _app = getApp<IAppOption>() |
||||||
|
|
||||||
|
Page({ |
||||||
|
data: { |
||||||
|
popupShow: true, |
||||||
|
popupType: 'popup15', // 确认删除弹窗
|
||||||
|
popupParams: { |
||||||
|
close: false, |
||||||
|
} as any, |
||||||
|
|
||||||
|
history: { |
||||||
|
frontend: [ |
||||||
|
{ |
||||||
|
title: '正面睁眼照', |
||||||
|
content: '平视,目光看向镜头方向,自然睁眼,不眯眼、不瞪眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面闭眼照', |
||||||
|
content: '正对镜头,面部居中,自然放松,双眼轻轻闭合,不皱眉、不挤眼。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面仰头照', |
||||||
|
content: '拍摄时,正对镜头,面部居中,头部自然向上仰至约 45°,双眼同步平视,保持自然睁眼、不眯眼。', |
||||||
|
}, |
||||||
|
], |
||||||
|
backend: [ |
||||||
|
{ |
||||||
|
title: '左侧-90°', |
||||||
|
content: '身体与头部完全转向右侧,呈标准 90° 侧面,仅可见左侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-90°', |
||||||
|
content: '身体与头部完全转向左侧,呈标准 90° 侧面,仅可见右侧眼睛。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '左侧-45°', |
||||||
|
content: '身体与头部转向右前方 45°。', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '右侧-45°', |
||||||
|
content: '身体与头部转向左前方 45°', |
||||||
|
}, |
||||||
|
], |
||||||
|
other: [ |
||||||
|
{ |
||||||
|
title: '正面眼睛上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右上看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛左下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '正面眼睛右下看', |
||||||
|
content: '', |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
onLoad() {}, |
||||||
|
|
||||||
|
handlePopupOk() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
handlePopupCancel() { |
||||||
|
this.setData({ |
||||||
|
popupShow: false, |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export {} |
||||||
@ -0,0 +1,98 @@ |
|||||||
|
<navbar fixed title="记录" custom-style="background:{{background}}"> |
||||||
|
<van-icon name="arrow-left" slot="left" size="18px" color="#000" bind:tap="handleBack" /> |
||||||
|
</navbar> |
||||||
|
|
||||||
|
<view |
||||||
|
class="page" |
||||||
|
style="background: url('{{imageUrl}}bg10.png?t={{Timestamp}}') no-repeat top center/100% 610rpx;padding-top:{{pageTop}}px;" |
||||||
|
> |
||||||
|
<view class="header"> |
||||||
|
<view class="wrap"> |
||||||
|
<view class="date">2026-04-02</view> |
||||||
|
<view class="tags"> |
||||||
|
<view class="tag tag1">基准照片</view> |
||||||
|
<view class="tag tag2">替妥尤单抗:2</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="opt"> |
||||||
|
<view class="item"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon152.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
<view class="item"> |
||||||
|
<image class="icon" src="{{imageUrl}}icon153.png?t={{Timestamp}}"></image> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<view class="container"> |
||||||
|
<view class="tip-card"> |
||||||
|
<image class="tip-icon" src="{{imageUrl}}icon154.png?t={{Timestamp}}"></image> |
||||||
|
<view class="wrap"> |
||||||
|
<view class="title">记录未录入完全</view> |
||||||
|
<view class="content">当前已录入1/15个角度。您可以点击右上角的编辑按钮继续补充照片。</view> |
||||||
|
</view> |
||||||
|
<view class="btn">去补充</view> |
||||||
|
</view> |
||||||
|
<view class="banner"> |
||||||
|
<view class="title">眼球突出度测量记录</view> |
||||||
|
<view class="row"> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">右眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">眶间距</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="col"> |
||||||
|
<view class="name">左眼</view> |
||||||
|
<view class="content"> |
||||||
|
<view class="num">12</view> |
||||||
|
<view class="sub">MM</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">正面</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.frontend}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">侧面</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.backend}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="card"> |
||||||
|
<view class="card-title">眼球运动八个方向</view> |
||||||
|
<view class="card-container"> |
||||||
|
<view class="card-item" wx:for="{{history.other}}" wx:key="index"> |
||||||
|
<image class="photo" mode="aspectFill" src="{{imageUrl}}note-demo1.png?t={{Timestamp}}"></image> |
||||||
|
<view class="name">{{item.title}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<popup |
||||||
|
show="{{popupShow}}" |
||||||
|
type="{{popupType}}" |
||||||
|
params="{{popupParams}}" |
||||||
|
bind:ok="handlePopupOk" |
||||||
|
bind:cancel="handlePopupCancel" |
||||||
|
></popup> |
||||||
@ -0,0 +1,220 @@ |
|||||||
|
/** |
||||||
|
* 阿里云验证码2.0工具模块 |
||||||
|
* 用于小程序发送验证码前的行为验证 |
||||||
|
*/ |
||||||
|
|
||||||
|
// 验证码插件实例
|
||||||
|
let AliyunCaptchaPluginInterface: any = null |
||||||
|
|
||||||
|
// 计时器
|
||||||
|
let timer: number | null = null |
||||||
|
|
||||||
|
// 页面实例引用
|
||||||
|
let pageInstance: any = null |
||||||
|
|
||||||
|
// 发送验证码的接口配置
|
||||||
|
interface SendCodeConfig { |
||||||
|
url: string |
||||||
|
mobileField?: string |
||||||
|
extraData?: Record<string, any> |
||||||
|
} |
||||||
|
|
||||||
|
// 验证码配置选项
|
||||||
|
interface CaptchaOptions { |
||||||
|
sceneId: string |
||||||
|
sendCodeConfig: SendCodeConfig |
||||||
|
onSendSuccess?: () => void |
||||||
|
onSendFail?: (err: any) => void |
||||||
|
countdown?: number |
||||||
|
} |
||||||
|
|
||||||
|
// 当前配置
|
||||||
|
let currentOptions: CaptchaOptions | null = null |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化验证码插件 |
||||||
|
*/ |
||||||
|
function initPlugin() { |
||||||
|
if (!AliyunCaptchaPluginInterface) { |
||||||
|
AliyunCaptchaPluginInterface = requirePlugin('AliyunCaptcha') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 验证通过回调函数 |
||||||
|
* @param captchaVerifyParam 验证码验证参数 |
||||||
|
*/ |
||||||
|
async function successCallback(captchaVerifyParam: string) { |
||||||
|
if (!pageInstance || !currentOptions) return |
||||||
|
|
||||||
|
const { sendCodeConfig, onSendSuccess, onSendFail, countdown = 60 } = currentOptions |
||||||
|
const mobileField = sendCodeConfig.mobileField || 'mobile' |
||||||
|
const mobile = pageInstance.data[mobileField] |
||||||
|
|
||||||
|
try { |
||||||
|
const res = await wx.ajax({ |
||||||
|
method: 'POST', |
||||||
|
url: sendCodeConfig.url, |
||||||
|
data: { |
||||||
|
[mobileField]: mobile, |
||||||
|
captchaVerifyParam, |
||||||
|
...sendCodeConfig.extraData, |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
wx.showToast({ |
||||||
|
icon: 'none', |
||||||
|
title: '验证码已发送~', |
||||||
|
}) |
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
|
startCountdown(countdown) |
||||||
|
|
||||||
|
// 执行成功回调
|
||||||
|
onSendSuccess?.() |
||||||
|
|
||||||
|
return res |
||||||
|
} |
||||||
|
catch (err: any) { |
||||||
|
wx.showToast({ |
||||||
|
title: err.data?.msg || '发送失败,请重试', |
||||||
|
icon: 'none', |
||||||
|
}) |
||||||
|
onSendFail?.(err) |
||||||
|
throw err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 验证失败回调函数 |
||||||
|
* @param error 错误信息 |
||||||
|
*/ |
||||||
|
function failCallback(error: any) { |
||||||
|
console.error('阿里云验证码验证失败:', error) |
||||||
|
wx.showToast({ |
||||||
|
title: '验证失败,请重试', |
||||||
|
icon: 'none', |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 开始倒计时 |
||||||
|
* @param seconds 倒计时秒数 |
||||||
|
*/ |
||||||
|
function startCountdown(seconds: number) { |
||||||
|
if (timer) { |
||||||
|
clearInterval(timer) |
||||||
|
timer = null |
||||||
|
} |
||||||
|
|
||||||
|
let time = seconds |
||||||
|
updateCountdownText(`${time}s后重新发送`) |
||||||
|
|
||||||
|
timer = setInterval(() => { |
||||||
|
time-- |
||||||
|
if (time <= 0) { |
||||||
|
clearInterval(timer as number) |
||||||
|
timer = null |
||||||
|
updateCountdownText('发送验证码') |
||||||
|
} |
||||||
|
else { |
||||||
|
updateCountdownText(`${time}s后重新发送`) |
||||||
|
} |
||||||
|
}, 1000) as unknown as number |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新倒计时文本 |
||||||
|
* @param text 显示的文本 |
||||||
|
*/ |
||||||
|
function updateCountdownText(text: string) { |
||||||
|
if (pageInstance) { |
||||||
|
pageInstance.setData({ codeText: text }) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化验证码功能 |
||||||
|
* @param page 页面实例 |
||||||
|
* @param options 配置选项 |
||||||
|
* @returns 插件配置对象 |
||||||
|
*/ |
||||||
|
export function initCaptcha(page: any, options: CaptchaOptions) { |
||||||
|
initPlugin() |
||||||
|
pageInstance = page |
||||||
|
currentOptions = options |
||||||
|
|
||||||
|
const pluginProps = { |
||||||
|
SceneId: options.sceneId, |
||||||
|
mode: 'popup', |
||||||
|
success: successCallback.bind(page), |
||||||
|
fail: failCallback.bind(page), |
||||||
|
slideStyle: { |
||||||
|
width: 540, |
||||||
|
height: 60, |
||||||
|
}, |
||||||
|
language: 'cn', |
||||||
|
region: 'cn', |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
loadCaptcha: true, |
||||||
|
pluginProps, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 显示验证码弹窗 |
||||||
|
* @returns 是否成功触发 |
||||||
|
*/ |
||||||
|
export function showCaptcha(): boolean { |
||||||
|
if (!AliyunCaptchaPluginInterface) { |
||||||
|
initPlugin() |
||||||
|
} |
||||||
|
|
||||||
|
if (isCountingDown()) { |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
AliyunCaptchaPluginInterface.show() |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 检查是否正在倒计时 |
||||||
|
* @returns 是否正在倒计时 |
||||||
|
*/ |
||||||
|
export function isCountingDown(): boolean { |
||||||
|
return timer !== null |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清除倒计时 |
||||||
|
*/ |
||||||
|
export function clearCountdown() { |
||||||
|
if (timer) { |
||||||
|
clearInterval(timer) |
||||||
|
timer = null |
||||||
|
} |
||||||
|
updateCountdownText('发送验证码') |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取验证码插件接口 |
||||||
|
* @returns 插件接口 |
||||||
|
*/ |
||||||
|
export function getCaptchaPlugin() { |
||||||
|
if (!AliyunCaptchaPluginInterface) { |
||||||
|
initPlugin() |
||||||
|
} |
||||||
|
return AliyunCaptchaPluginInterface |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 页面卸载时清理资源 |
||||||
|
*/ |
||||||
|
export function destroyCaptcha() { |
||||||
|
clearCountdown() |
||||||
|
pageInstance = null |
||||||
|
currentOptions = null |
||||||
|
} |
||||||
Loading…
Reference in new issue