<修改> 1、增加用户选项,可以为多用户记录数据

This commit is contained in:
ypc 2026-06-06 22:26:09 +08:00
parent d9d3833d92
commit a015ee7de3
15 changed files with 689 additions and 78 deletions

112
app.js
View File

@ -1,36 +1,95 @@
App({ App({
globalData: { globalData: {
items: ["血红蛋白", "尿素", "肌酐", "尿酸", "血钾", "血钙", "血磷", "β2微球蛋白", "体重"], currentPersonId: null,
records: [] persons: [],
dataMap: {}
}, },
onLaunch() { onLaunch() {
const defaults = ["血红蛋白", "尿素", "肌酐", "尿酸", "血钾", "血钙", "血磷", "β2微球蛋白", "体重"] // 清除旧版存储,避免残留
const data = wx.getStorageSync("health_data") wx.removeStorageSync("health_data")
var data = wx.getStorageSync("health_data_v2")
if (data) { if (data) {
// 合并:保留用户自定义项目,同时补上新增的默认项目 this.globalData.persons = data.persons || []
const storedItems = data.items || [] this.globalData.dataMap = data.dataMap || {}
const merged = [...defaults] this.globalData.currentPersonId = data.currentPersonId || (this.globalData.persons[0] && this.globalData.persons[0].id) || null
storedItems.forEach(item => {
if (!merged.includes(item)) merged.push(item)
})
this.globalData.items = merged
this.globalData.records = data.records || []
} else {
this.globalData.items = [...defaults]
} }
this.saveData() // 无存储或 persons 为空时,由首页弹窗引导创建首个用户
},
_defaultItems() {
return ["血红蛋白", "尿素", "肌酐", "尿酸", "血钾", "血钙", "血磷", "β2微球蛋白", "体重"]
}, },
saveData() { saveData() {
wx.setStorageSync("health_data", { wx.setStorageSync("health_data_v2", {
items: this.globalData.items, persons: this.globalData.persons,
records: this.globalData.records dataMap: this.globalData.dataMap,
currentPersonId: this.globalData.currentPersonId
}) })
}, },
getCurrentData() {
var id = this.globalData.currentPersonId
if (!id || !this.globalData.dataMap[id]) return { items: [], records: [] }
return this.globalData.dataMap[id]
},
getCurrentPerson() {
var id = this.globalData.currentPersonId
var persons = this.globalData.persons
for (var i = 0; i < persons.length; i++) {
if (persons[i].id === id) return persons[i]
}
return null
},
switchPerson(id) {
if (!this.globalData.dataMap[id]) return false
this.globalData.currentPersonId = id
this.saveData()
return true
},
addPerson(name) {
var id = Date.now().toString(36) + Math.random().toString(36).slice(2, 6)
this.globalData.persons.push({ id: id, name: name })
// 新用户默认有一份默认项目列表
this.globalData.dataMap[id] = {
items: this._defaultItems(),
records: []
}
this.saveData()
return id
},
removePerson(id) {
var persons = this.globalData.persons
if (persons.findIndex(function(p){return p.id===id}) < 0) return false
this.globalData.persons = persons.filter(function (p) { return p.id !== id })
delete this.globalData.dataMap[id]
if (this.globalData.currentPersonId === id) {
this.globalData.currentPersonId = this.globalData.persons.length > 0 ? this.globalData.persons[0].id : null
}
this.saveData()
return true
},
renamePerson(id, newName) {
var persons = this.globalData.persons
for (var i = 0; i < persons.length; i++) {
if (persons[i].id === id) {
persons[i].name = newName
this.saveData()
return true
}
}
return false
},
addRecord(record) { addRecord(record) {
this.globalData.records.push({ var data = this.getCurrentData()
data.records.push({
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6), id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6),
item: record.item, item: record.item,
date: record.date, date: record.date,
@ -40,20 +99,23 @@
}, },
deleteRecord(id) { deleteRecord(id) {
this.globalData.records = this.globalData.records.filter(r => r.id !== id) var data = this.getCurrentData()
data.records = data.records.filter(function (r) { return r.id !== id })
this.saveData() this.saveData()
}, },
addItem(name) { addItem(name) {
if (!this.globalData.items.includes(name)) { var data = this.getCurrentData()
this.globalData.items.push(name) if (data.items.indexOf(name) === -1) {
data.items.push(name)
this.saveData() this.saveData()
} }
}, },
removeItem(name) { removeItem(name) {
this.globalData.items = this.globalData.items.filter(i => i !== name) var data = this.getCurrentData()
this.globalData.records = this.globalData.records.filter(r => r.item !== name) data.items = data.items.filter(function (i) { return i !== name })
data.records = data.records.filter(function (r) { return r.item !== name })
this.saveData() this.saveData()
} }
}) })

View File

@ -25,6 +25,23 @@ page {
min-height: 100vh; min-height: 100vh;
} }
/* ===== 用户标识栏(各页面顶部) ===== */
.user-info-bar {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding: 16rpx 24rpx;
background: #fff;
border-radius: 10rpx;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.user-info-text {
font-size: 28rpx;
font-weight: 500;
color: #2c7a7b;
}
/* ===== 通用卡片 ===== */ /* ===== 通用卡片 ===== */
.card { .card {
background: #fff; background: #fff;

View File

@ -2,6 +2,8 @@ var app = getApp()
Page({ Page({
data: { data: {
persons: [],
currentPersonName: "",
items: [], items: [],
viewMode: "month", viewMode: "month",
filterMonth: "", filterMonth: "",
@ -18,8 +20,11 @@ Page({
var today = this.formatDate(new Date(), "day") var today = this.formatDate(new Date(), "day")
var month = today.slice(0, 7) var month = today.slice(0, 7)
var year = today.slice(0, 4) var year = today.slice(0, 4)
var person = app.getCurrentPerson()
this.setData({ this.setData({
items: app.globalData.items, persons: app.globalData.persons,
currentPersonName: person ? person.name : "",
items: app.getCurrentData().items,
filterMonth: month, filterMonth: month,
filterYear: year, filterYear: year,
customStart: month, customStart: month,
@ -29,7 +34,12 @@ Page({
}, },
onShow: function () { onShow: function () {
var items = app.globalData.items var items = app.getCurrentData().items
var person = app.getCurrentPerson()
this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : ""
})
if (items.length !== this.data.items.length || if (items.length !== this.data.items.length ||
items.some(function (v, i) { return v !== this.data.items[i] }, this)) { items.some(function (v, i) { return v !== this.data.items[i] }, this)) {
this.setData({ items: items }) this.setData({ items: items })
@ -69,7 +79,8 @@ Page({
}, },
refreshData: function () { refreshData: function () {
var records = app.globalData.records var data = app.getCurrentData()
var records = data.records
var items = this.data.items var items = this.data.items
var range = this.getDateRange() var range = this.getDateRange()
var start = range.start var start = range.start
@ -140,7 +151,8 @@ Page({
confirmColor: "#e53e3e", confirmColor: "#e53e3e",
success: function (res) { success: function (res) {
if (!res.confirm) return if (!res.confirm) return
app.globalData.records = app.globalData.records.filter(function (r) { return r.date !== dateKey }) var data = app.getCurrentData()
data.records = data.records.filter(function (r) { return r.date !== dateKey })
app.saveData() app.saveData()
that.refreshData() that.refreshData()
wx.showToast({ title: "已删除", icon: "success", duration: 1000 }) wx.showToast({ title: "已删除", icon: "success", duration: 1000 })
@ -185,15 +197,16 @@ Page({
var items = this.data.items var items = this.data.items
var savedCount = 0 var savedCount = 0
var that = this var that = this
var data = app.getCurrentData()
app.globalData.records = app.globalData.records.filter(function (r) { return r.date !== editingDate }) data.records = data.records.filter(function (r) { return r.date !== editingDate })
items.forEach(function (item) { items.forEach(function (item) {
var raw = editValues[item] var raw = editValues[item]
if (!raw || raw.trim() === "") return if (!raw || raw.trim() === "") return
var v = parseFloat(raw) var v = parseFloat(raw)
if (isNaN(v) || v <= 0) return if (isNaN(v) || v <= 0) return
app.globalData.records.push({ data.records.push({
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6), id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6),
item: item, item: item,
date: editingDate, date: editingDate,

View File

@ -1,5 +1,10 @@
<!-- 数据详细信息 --> <!-- 数据详细信息 -->
<view class="container"> <view class="container">
<!-- 用户信息 -->
<view class="user-info-bar" wx:if="{{persons.length > 0}}">
<text class="user-info-text">👤 {{currentPersonName}}</text>
</view>
<!-- 时间范围选择 --> <!-- 时间范围选择 -->
<view class="card card-filter"> <view class="card card-filter">
<view class="mode-tabs"> <view class="mode-tabs">

View File

@ -2,6 +2,8 @@ var app = getApp()
Page({ Page({
data: { data: {
persons: [],
currentPersonName: "",
items: [], items: [],
inputDate: "", inputDate: "",
values: {}, values: {},
@ -10,12 +12,23 @@ Page({
onLoad: function () { onLoad: function () {
var today = this.formatDate(new Date()) var today = this.formatDate(new Date())
this.setData({ inputDate: today, items: app.globalData.items }) var person = app.getCurrentPerson()
this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : "",
inputDate: today,
items: app.getCurrentData().items
})
this.loadExisting(today) this.loadExisting(today)
}, },
onShow: function () { onShow: function () {
var items = app.globalData.items var person = app.getCurrentPerson()
var items = app.getCurrentData().items
this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : ""
})
if (items.length !== this.data.items.length || if (items.length !== this.data.items.length ||
items.some(function (v, i) { return v !== this.data.items[i] }, this)) { items.some(function (v, i) { return v !== this.data.items[i] }, this)) {
this.setData({ items: items }) this.setData({ items: items })
@ -24,7 +37,8 @@ Page({
}, },
loadExisting: function (date) { loadExisting: function (date) {
var records = app.globalData.records.filter(function (r) { return r.date === date }) var data = app.getCurrentData()
var records = data.records.filter(function (r) { return r.date === date })
this.setData({ existingRecords: records }) this.setData({ existingRecords: records })
}, },
@ -48,6 +62,7 @@ Page({
var values = this.data.values var values = this.data.values
var savedCount = 0 var savedCount = 0
var that = this var that = this
var data = app.getCurrentData()
items.forEach(function (item) { items.forEach(function (item) {
var raw = values[item] var raw = values[item]
@ -55,7 +70,7 @@ Page({
var v = parseFloat(raw) var v = parseFloat(raw)
if (isNaN(v) || v <= 0) return if (isNaN(v) || v <= 0) return
var existing = app.globalData.records.find(function (r) { return r.item === item && r.date === inputDate }) var existing = data.records.find(function (r) { return r.item === item && r.date === inputDate })
if (existing) { if (existing) {
existing.value = v existing.value = v
} else { } else {

View File

@ -1,5 +1,10 @@
<!-- 录入检查数据 --> <!-- 录入检查数据 -->
<view class="container"> <view class="container">
<!-- 用户信息 -->
<view class="user-info-bar" wx:if="{{persons.length > 0}}">
<text class="user-info-text">👤 {{currentPersonName}}</text>
</view>
<!-- 日期选择 --> <!-- 日期选择 -->
<view class="card card-date"> <view class="card card-date">
<view class="card-title">选择日期</view> <view class="card-title">选择日期</view>

View File

@ -1,6 +1,44 @@
var app = getApp() var app = getApp()
Page({ Page({
data: {
persons: [],
personNames: [],
currentPersonName: "",
currentPersonIndex: 0,
showAddInput: false,
newPersonName: "",
showForceModal: false,
forceName: "",
showPersonModal: false,
editingPersonId: "",
editingPersonName: ""
},
onShow: function () {
this.refreshView()
},
refreshView: function () {
var persons = app.globalData.persons
var names = persons.map(function (p) { return p.name })
var person = app.getCurrentPerson()
var idx = persons.findIndex(function (p) { return p && person && p.id === person.id })
this.setData({
persons: persons,
personNames: names,
currentPersonName: person ? person.name : "",
currentPersonIndex: idx >= 0 ? idx : 0
})
if (persons.length === 0) {
this.setData({ showForceModal: true })
} else {
this.setData({ showForceModal: false })
}
},
noop: function () {},
goEntry: function () { goEntry: function () {
wx.navigateTo({ url: '/pages/entry/entry' }) wx.navigateTo({ url: '/pages/entry/entry' })
}, },
@ -13,19 +51,151 @@ Page({
goDetails: function () { goDetails: function () {
wx.navigateTo({ url: '/pages/details/details' }) wx.navigateTo({ url: '/pages/details/details' })
}, },
onClearAll: function () { onClearAll: function () {
var that = this var that = this
wx.showModal({ wx.showModal({
title: "⚠️ 危险操作", title: "⚠️ 危险操作",
content: "确定要清除所有检查记录吗?\n此操作将删除所有历史数据但保留检查项目且不可恢复", content: "确定要清除「" + this.data.currentPersonName + "」的所有检查记录吗?\n此操作将删除所有历史数据但保留检查项目且不可恢复",
confirmText: "确认清除", confirmText: "确认清除",
confirmColor: "#e53e3e", confirmColor: "#e53e3e",
success: function (res) { success: function (res) {
if (!res.confirm) return if (!res.confirm) return
app.globalData.records = [] var data = app.getCurrentData()
data.records = []
app.saveData() app.saveData()
wx.showToast({ title: "已清除全部记录", icon: "success", duration: 1500 }) wx.showToast({ title: "已清除全部记录", icon: "success", duration: 1500 })
} }
}) })
},
// ===== 切换用户 =====
onSwitchPerson: function (e) {
var idx = parseInt(e.detail.value)
var persons = this.data.persons
if (idx === this.data.currentPersonIndex) return
var person = persons[idx]
if (!person) return
app.switchPerson(person.id)
this.refreshView()
wx.showToast({ title: "已切换至" + person.name, icon: "success", duration: 1000 })
},
// ===== 新增用户(首页行内) =====
onShowAddInput: function () {
this.setData({ showAddInput: true, newPersonName: "" })
},
onCancelAddPerson: function () {
this.setData({ showAddInput: false, newPersonName: "" })
},
onAddNameInput: function (e) {
this.setData({ newPersonName: e.detail.value })
},
onConfirmAddPerson: function () {
var name = this.data.newPersonName.trim()
if (!name) {
wx.showToast({ title: "请输入用户名", icon: "none" })
return
}
if (name.length > 10) {
wx.showToast({ title: "用户名最多10个字符", icon: "none" })
return
}
app.addPerson(name)
app.switchPerson(app.globalData.persons[app.globalData.persons.length - 1].id)
this.setData({ showAddInput: false, newPersonName: "" })
this.refreshView()
wx.showToast({ title: "已添加" + name, icon: "success", duration: 1000 })
},
// ===== 强制创建首个用户(无用户弹窗) =====
onForceNameInput: function (e) {
this.setData({ forceName: e.detail.value })
},
onConfirmForceCreate: function () {
var name = this.data.forceName.trim()
if (!name) {
wx.showToast({ title: "请先创建用户", icon: "none" })
return
}
if (name.length > 10) {
wx.showToast({ title: "用户名最多10个字符", icon: "none" })
return
}
var id = app.addPerson(name)
app.switchPerson(id)
this.setData({ showForceModal: false, forceName: "" })
this.refreshView()
wx.showToast({ title: "欢迎," + name, icon: "success", duration: 1200 })
},
onCancelForceCreate: function () {
// 取消了,但仍无用户,弹窗不退
wx.showToast({ title: "请先创建用户", icon: "none" })
},
// ===== 用户管理弹窗(重命名/删除) =====
onTogglePersonModal: function () {
this.setData({
showPersonModal: !this.data.showPersonModal,
editingPersonId: "",
editingPersonName: ""
})
},
onStartRename: function (e) {
var id = e.currentTarget.dataset.id
var person = this.data.persons.find(function (p) { return p.id === id })
this.setData({
editingPersonId: id,
editingPersonName: person ? person.name : ""
})
},
onEditNameInput: function (e) {
this.setData({ editingPersonName: e.detail.value })
},
onConfirmRename: function () {
var name = this.data.editingPersonName.trim()
if (!name) {
wx.showToast({ title: "请输入新名称", icon: "none" })
return
}
if (name.length > 10) {
wx.showToast({ title: "用户名最多10个字符", icon: "none" })
return
}
app.renamePerson(this.data.editingPersonId, name)
this.setData({ editingPersonId: "", editingPersonName: "" })
this.refreshView()
wx.showToast({ title: "已重命名", icon: "success", duration: 1000 })
},
onDeletePerson: function (e) {
var id = e.currentTarget.dataset.id
var person = this.data.persons.find(function (p) { return p.id === id })
if (!person) return
var that = this
wx.showModal({
title: "确认删除",
content: "确定删除用户「" + person.name + "」吗?\n该用户的所有数据将被永久删除。",
confirmColor: "#e53e3e",
success: function (res) {
if (!res.confirm) return
app.removePerson(id)
that.setData({ editingPersonId: "", editingPersonName: "" })
// 删完后如无用户,关闭管理弹窗并强制展示创建弹窗
if (app.globalData.persons.length === 0) {
that.setData({ showPersonModal: false })
}
that.refreshView()
wx.showToast({ title: "已删除", icon: "success", duration: 1000 })
}
})
} }
}) })

View File

@ -1,12 +1,42 @@
<!-- 首页 - 功能入口 --> <!-- 首页 - 功能入口 -->
<view class="container home"> <view class="container home">
<!-- 用户栏:左下拉切换 + 右添加/管理 -->
<view class="person-bar">
<picker wx:if="{{persons.length > 0}}" mode="selector" range="{{personNames}}" bindchange="onSwitchPerson" value="{{currentPersonIndex}}">
<view class="person-selector">
<text class="person-icon">👤</text>
<text class="person-name">{{currentPersonName}}</text>
<text class="person-arrow">▼</text>
</view>
</picker>
<view class="person-bar-right" wx:if="{{persons.length > 0}}">
<view class="person-bar-btn" bindtap="onShowAddInput"></view>
<view class="person-bar-btn person-bar-btn--manage" bindtap="onTogglePersonModal">⚙</view>
</view>
</view>
<!-- 行内新增用户输入 -->
<view wx:if="{{showAddInput}}" class="add-person-row">
<input
class="add-person-input"
placeholder="请输入用户名称"
value="{{newPersonName}}"
bindinput="onAddNameInput"
bindconfirm="onConfirmAddPerson"
confirm-type="done"
maxlength="10"
focus="{{true}}"
/>
<text class="add-person-btn add-person-btn--confirm" bindtap="onConfirmAddPerson">确认</text>
<text class="add-person-btn add-person-btn--cancel" bindtap="onCancelAddPerson">取消</text>
</view>
<view class="home-header"> <view class="home-header">
<text class="home-title">健康数据追踪</text> <text class="home-title">健康数据追踪</text>
<text class="home-desc">选择您需要的功能</text> <text class="home-desc">选择您需要的功能</text>
</view> </view>
<view class="home-grid"> <view class="home-grid">
<!-- 录入检查数据 -->
<view class="home-card" bindtap="goEntry"> <view class="home-card" bindtap="goEntry">
<view class="home-card-icon home-card-icon--entry"> <view class="home-card-icon home-card-icon--entry">
<text class="home-card-emoji">📝</text> <text class="home-card-emoji">📝</text>
@ -15,7 +45,6 @@
<text class="home-card-desc">记录每日健康指标</text> <text class="home-card-desc">记录每日健康指标</text>
</view> </view>
<!-- 管理检查项目 -->
<view class="home-card" bindtap="goItems"> <view class="home-card" bindtap="goItems">
<view class="home-card-icon home-card-icon--items"> <view class="home-card-icon home-card-icon--items">
<text class="home-card-emoji">⚙️</text> <text class="home-card-emoji">⚙️</text>
@ -24,7 +53,6 @@
<text class="home-card-desc">自定义追踪指标</text> <text class="home-card-desc">自定义追踪指标</text>
</view> </view>
<!-- 数据趋势 -->
<view class="home-card" bindtap="goTrend"> <view class="home-card" bindtap="goTrend">
<view class="home-card-icon home-card-icon--trend"> <view class="home-card-icon home-card-icon--trend">
<text class="home-card-emoji">📈</text> <text class="home-card-emoji">📈</text>
@ -33,7 +61,6 @@
<text class="home-card-desc">查看变化趋势图</text> <text class="home-card-desc">查看变化趋势图</text>
</view> </view>
<!-- 数据详细信息 -->
<view class="home-card" bindtap="goDetails"> <view class="home-card" bindtap="goDetails">
<view class="home-card-icon home-card-icon--details"> <view class="home-card-icon home-card-icon--details">
<text class="home-card-emoji">📋</text> <text class="home-card-emoji">📋</text>
@ -43,11 +70,74 @@
</view> </view>
</view> </view>
<!-- 清除所有数据 --> <view class="clear-section" wx:if="{{persons.length > 0}}">
<view class="clear-section">
<view class="clear-btn" bindtap="onClearAll"> <view class="clear-btn" bindtap="onClearAll">
<text class="clear-icon">🗑️</text> <text class="clear-icon">🗑️</text>
<text class="clear-text">清除所有历史数据</text> <text class="clear-text">清除{{currentPersonName}}的历史数据</text>
</view>
</view>
</view>
<!-- ===== 无用户弹窗(强制创建) ===== -->
<view wx:if="{{showForceModal && persons.length === 0}}" class="modal-wrap">
<view class="modal-box" catchtap="noop">
<view class="modal-title">欢迎使用健康数据追踪</view>
<view class="modal-desc">请先创建您的第一位用户</view>
<view class="force-input-row">
<input
class="force-input"
placeholder="请输入用户名称"
value="{{forceName}}"
bindinput="onForceNameInput"
bindconfirm="onConfirmForceCreate"
confirm-type="done"
maxlength="10"
focus="{{true}}"
/>
</view>
<view class="btn-row">
<button class="btn-primary" style="flex:1;" bindtap="onConfirmForceCreate">确认创建</button>
</view>
</view>
</view>
<!-- ===== 用户管理弹窗 ===== -->
<view wx:if="{{showPersonModal && persons.length > 0}}" class="modal-wrap" catchtap="onTogglePersonModal">
<view class="modal-box" catchtap="noop">
<view class="modal-title">用户管理</view>
<view class="person-list">
<view
class="person-list-item {{app.globalData.currentPersonId === item.id ? 'person-list-item--active' : ''}}"
wx:for="{{persons}}"
wx:key="id"
>
<view class="person-list-left">
<text class="person-list-name">{{item.name}}</text>
</view>
<view class="person-list-right">
<text class="person-list-action" bindtap="onStartRename" data-id="{{item.id}}">✏️</text>
<text class="person-list-action" bindtap="onDeletePerson" data-id="{{item.id}}">🗑️</text>
</view>
</view>
</view>
<!-- 重命名输入行 -->
<view wx:if="{{editingPersonId}}" class="person-edit-row">
<input
class="person-edit-input"
placeholder="修改用户名"
value="{{editingPersonName}}"
bindinput="onEditNameInput"
bindconfirm="onConfirmRename"
confirm-type="done"
maxlength="10"
/>
<button class="btn-primary person-edit-btn" bindtap="onConfirmRename">保存</button>
</view>
<view class="btn-row">
<button class="btn-cancel" bindtap="onTogglePersonModal">关闭</button>
</view> </view>
</view> </view>
</view> </view>

View File

@ -4,9 +4,119 @@
background: linear-gradient(180deg, #e6f2f2 0%, #f5f7fa 30%); background: linear-gradient(180deg, #e6f2f2 0%, #f5f7fa 30%);
} }
/* ===== 用户栏 ===== */
.person-bar {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
margin: 20rpx 24rpx 0;
padding: 16rpx 28rpx;
border-radius: 12rpx;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.person-selector {
display: flex;
align-items: center;
gap: 12rpx;
}
.person-icon {
font-size: 32rpx;
}
.person-name {
font-size: 30rpx;
font-weight: 600;
color: #2c7a7b;
}
.person-arrow {
font-size: 20rpx;
color: #a0aec0;
}
.person-bar-right {
display: flex;
align-items: center;
gap: 20rpx;
}
.person-bar-btn {
width: 48rpx;
height: 48rpx;
line-height: 48rpx;
text-align: center;
font-size: 32rpx;
font-weight: 600;
color: #2c7a7b;
background: #e6f2f2;
border-radius: 50%;
}
.person-bar-btn:active {
background: #d0e8e8;
}
.person-bar-btn--manage {
font-size: 26rpx;
color: #718096;
background: #f7fafc;
}
/* ===== 行内新增用户输入 ===== */
.add-person-row {
display: flex;
align-items: center;
gap: 16rpx;
margin: 16rpx 24rpx 0;
padding: 16rpx 20rpx;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.add-person-input {
flex: 1;
padding: 14rpx 16rpx;
border: 1rpx solid #2c7a7b;
border-radius: 8rpx;
font-size: 28rpx;
height: 52rpx;
box-sizing: border-box;
}
.add-person-btn {
flex-shrink: 0;
font-size: 26rpx;
font-weight: 500;
padding: 12rpx 20rpx;
border-radius: 8rpx;
}
.add-person-btn--confirm {
color: #fff;
background: #2c7a7b;
}
.add-person-btn--confirm:active {
background: #1a5c5d;
}
.add-person-btn--cancel {
color: #718096;
background: #edf2f7;
}
.add-person-btn--cancel:active {
background: #e2e8f0;
}
/* ===== 页面标题 ===== */
.home-header { .home-header {
text-align: center; text-align: center;
padding: 60rpx 0 40rpx; padding: 50rpx 0 0;
} }
.home-title { .home-title {
@ -26,7 +136,7 @@
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
gap: 20rpx; gap: 20rpx;
padding: 0 24rpx; padding: 40rpx 24rpx 0;
} }
.home-card { .home-card {
@ -58,21 +168,10 @@
line-height: 1; line-height: 1;
} }
.home-card-icon--entry { .home-card-icon--entry { background: #e6f7ff; }
background: #e6f7ff; .home-card-icon--items { background: #f0f5ff; }
} .home-card-icon--trend { background: #f6ffed; }
.home-card-icon--details { background: #fff7e6; }
.home-card-icon--items {
background: #f0f5ff;
}
.home-card-icon--trend {
background: #f6ffed;
}
.home-card-icon--details {
background: #fff7e6;
}
.home-card-title { .home-card-title {
display: block; display: block;
@ -103,16 +202,106 @@
background: #fff5f5; background: #fff5f5;
} }
.clear-btn:active { .clear-btn:active { background: #ffe0e0; }
background: #ffe0e0;
}
.clear-icon { .clear-icon { font-size: 32rpx; }
font-size: 32rpx;
}
.clear-text { .clear-text {
font-size: 26rpx; font-size: 26rpx;
color: #e53e3e; color: #e53e3e;
font-weight: 500; font-weight: 500;
} }
/* ===== 无用户强制弹窗 ===== */
.modal-desc {
font-size: 28rpx;
color: #718096;
text-align: center;
margin-bottom: 24rpx;
}
.force-input-row { margin-bottom: 8rpx; }
.force-input {
width: 100%;
padding: 18rpx 20rpx;
border: 2rpx solid #2c7a7b;
border-radius: 10rpx;
font-size: 30rpx;
text-align: center;
box-sizing: border-box;
height: 60rpx;
}
/* ===== 用户管理弹窗 ===== */
.person-list { margin-bottom: 20rpx; }
.person-list-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 22rpx 16rpx;
border-radius: 10rpx;
margin-bottom: 8rpx;
background: #f7fafc;
border: 1rpx solid #edf2f7;
}
.person-list-item--active {
background: #e6f2f2;
border-color: #2c7a7b;
}
.person-list-left {
display: flex;
align-items: center;
gap: 12rpx;
}
.person-list-name {
font-size: 28rpx;
font-weight: 500;
color: #2d3748;
}
.person-list-item--active .person-list-name {
color: #2c7a7b;
font-weight: 600;
}
.person-list-right {
display: flex;
gap: 20rpx;
}
.person-list-action {
font-size: 28rpx;
padding: 4rpx;
}
.person-edit-row {
display: flex;
gap: 16rpx;
align-items: center;
margin-bottom: 8rpx;
}
.person-edit-input {
flex: 1;
padding: 16rpx 20rpx;
border: 1rpx solid #e2e8f0;
border-radius: 8rpx;
background: #f7fafc;
font-size: 28rpx;
height: 56rpx;
box-sizing: border-box;
}
.person-edit-btn {
flex-shrink: 0;
width: 130rpx;
height: 56rpx;
line-height: 56rpx;
padding: 0;
font-size: 26rpx;
}

View File

@ -2,12 +2,19 @@ var app = getApp()
Page({ Page({
data: { data: {
persons: [],
currentPersonName: "",
items: [], items: [],
newItemName: "" newItemName: ""
}, },
onShow: function () { onShow: function () {
this.setData({ items: app.globalData.items }) var person = app.getCurrentPerson()
this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : "",
items: app.getCurrentData().items
})
}, },
onNameInput: function (e) { onNameInput: function (e) {
@ -20,13 +27,14 @@ Page({
wx.showToast({ title: "请输入项目名称", icon: "none" }) wx.showToast({ title: "请输入项目名称", icon: "none" })
return return
} }
if (app.globalData.items.indexOf(name) > -1) { var data = app.getCurrentData()
if (data.items.indexOf(name) > -1) {
wx.showToast({ title: "该项目已存在", icon: "none" }) wx.showToast({ title: "该项目已存在", icon: "none" })
return return
} }
app.addItem(name) app.addItem(name)
this.setData({ this.setData({
items: app.globalData.items, items: app.getCurrentData().items,
newItemName: "" newItemName: ""
}) })
wx.showToast({ title: "已添加", icon: "success", duration: 1000 }) wx.showToast({ title: "已添加", icon: "success", duration: 1000 })
@ -42,7 +50,7 @@ Page({
success: function (res) { success: function (res) {
if (!res.confirm) return if (!res.confirm) return
app.removeItem(item) app.removeItem(item)
that.setData({ items: app.globalData.items }) that.setData({ items: app.getCurrentData().items })
wx.showToast({ title: "已删除", icon: "success", duration: 1000 }) wx.showToast({ title: "已删除", icon: "success", duration: 1000 })
} }
}) })

View File

@ -1,5 +1,10 @@
<!-- 管理检查项目 --> <!-- 管理检查项目 -->
<view class="container"> <view class="container">
<!-- 用户信息 -->
<view class="user-info-bar" wx:if="{{persons.length > 0}}">
<text class="user-info-text">👤 {{currentPersonName}}</text>
</view>
<!-- 新增项目 --> <!-- 新增项目 -->
<view class="card card-add"> <view class="card card-add">
<view class="card-title">新增检查项目</view> <view class="card-title">新增检查项目</view>

View File

@ -5,6 +5,8 @@ var COLORS = ["#e53e3e", "#3182ce", "#38a169", "#d69e2e", "#805ad5", "#dd6b20",
Page({ Page({
data: { data: {
persons: [],
currentPersonName: "",
items: [], items: [],
filterItems: [], filterItems: [],
viewMode: "month", viewMode: "month",
@ -20,8 +22,11 @@ Page({
var today = this.formatDate(new Date(), "day") var today = this.formatDate(new Date(), "day")
var month = today.slice(0, 7) var month = today.slice(0, 7)
var year = today.slice(0, 4) var year = today.slice(0, 4)
var items = app.globalData.items var items = app.getCurrentData().items
var person = app.getCurrentPerson()
this.setData({ this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : "",
items: items, items: items,
filterItems: items.slice(), filterItems: items.slice(),
filterMonth: month, filterMonth: month,
@ -36,7 +41,12 @@ Page({
}, },
onShow: function () { onShow: function () {
var items = app.globalData.items var items = app.getCurrentData().items
var person = app.getCurrentPerson()
this.setData({
persons: app.globalData.persons,
currentPersonName: person ? person.name : ""
})
if (items.length !== this.data.items.length || if (items.length !== this.data.items.length ||
items.some(function (v, i) { return v !== this.data.items[i] }, this)) { items.some(function (v, i) { return v !== this.data.items[i] }, this)) {
this.setData({ items: items }) this.setData({ items: items })
@ -99,7 +109,7 @@ Page({
}, },
refreshChart: function () { refreshChart: function () {
var records = app.globalData.records var records = app.getCurrentData().records
var filterItems = this.data.filterItems var filterItems = this.data.filterItems
var range = this.getDateRange() var range = this.getDateRange()
var start = range.start var start = range.start

View File

@ -1,5 +1,10 @@
<!-- 数据趋势 --> <!-- 数据趋势 -->
<view class="container"> <view class="container">
<!-- 用户信息 -->
<view class="user-info-bar" wx:if="{{persons.length > 0}}">
<text class="user-info-text">👤 {{currentPersonName}}</text>
</view>
<!-- 时间范围选择 --> <!-- 时间范围选择 -->
<view class="card card-filter"> <view class="card card-filter">
<view class="mode-tabs"> <view class="mode-tabs">

View File

@ -12,7 +12,16 @@
"outputPath": "" "outputPath": ""
}, },
"useCompilerPlugins": false, "useCompilerPlugins": false,
"minifyWXML": true "minifyWXML": true,
"compileWorklet": false,
"uploadWithSourceMap": true,
"packNpmManually": false,
"minifyWXSS": true,
"localPlugins": false,
"disableUseStrict": false,
"condition": false,
"swc": false,
"disableSWC": true
}, },
"compileType": "miniprogram", "compileType": "miniprogram",
"simulatorPluginLibVersion": {}, "simulatorPluginLibVersion": {},
@ -22,5 +31,6 @@
}, },
"appid": "wxefee3681fb349e54", "appid": "wxefee3681fb349e54",
"editorSetting": {}, "editorSetting": {},
"testRoot": "minitest/" "testRoot": "minitest/",
"libVersion": "3.15.2"
} }

View File

@ -1,6 +1,6 @@
{ {
"libVersion": "3.15.2", "libVersion": "3.15.2",
"projectname": "%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F", "projectname": "weixinxiaochengxu",
"setting": { "setting": {
"urlCheck": true, "urlCheck": true,
"coverView": true, "coverView": true,
@ -9,6 +9,13 @@
"preloadBackgroundData": false, "preloadBackgroundData": false,
"autoAudits": false, "autoAudits": false,
"showShadowRootInWxmlPanel": true, "showShadowRootInWxmlPanel": true,
"compileHotReLoad": true "compileHotReLoad": true,
"useApiHook": true,
"useStaticServer": false,
"useLanDebug": false,
"showES6CompileOption": false,
"checkInvalidKey": true,
"ignoreDevUnusedFiles": true,
"bigPackageSizeSupport": false
} }
} }