You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
5.0 KiB
Vue
272 lines
5.0 KiB
Vue
<template>
|
|
<view class="page-container">
|
|
<view class="page-toolbar">
|
|
<button class="btn btn-ghost back-btn" @click="goBack">
|
|
<uni-icons type="arrow-left" size="18" color="#1e3a8a"></uni-icons>
|
|
返回
|
|
</button>
|
|
<view class="toolbar-title-wrap">
|
|
<text class="toolbar-title">待办事项</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="add-bar">
|
|
<input
|
|
v-model="draft"
|
|
class="add-input"
|
|
confirm-type="done"
|
|
placeholder="请输入待办内容"
|
|
@confirm="addTodo"
|
|
/>
|
|
<button class="btn btn-primary add-btn" @click="addTodo">添加</button>
|
|
</view>
|
|
|
|
<scroll-view class="todo-list" scroll-y>
|
|
<view v-if="todos.length === 0" class="empty-text">暂无待办事项</view>
|
|
<view v-for="item in todos" :key="item.id" class="todo-item">
|
|
<view class="todo-check" @click="toggleTodo(item.id)">
|
|
<uni-icons
|
|
:type="item.done ? 'checkbox-filled' : 'smallcircle'"
|
|
size="22"
|
|
:color="item.done ? '#2563eb' : '#94a3b8'"
|
|
></uni-icons>
|
|
</view>
|
|
<input
|
|
class="todo-input"
|
|
:class="{ 'todo-input-done': item.done }"
|
|
:value="item.text"
|
|
@blur="onTodoBlur(item.id, $event)"
|
|
/>
|
|
<button class="btn btn-ghost del-btn" @click="removeTodo(item.id)">
|
|
删除
|
|
</button>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
createDutyTodo,
|
|
loadDutyTodos,
|
|
saveDutyTodos,
|
|
} from "@/utils/dutyTodos.js";
|
|
import { onShow } from "@dcloudio/uni-app";
|
|
import { ref } from "vue";
|
|
|
|
const draft = ref("");
|
|
const todos = ref([]);
|
|
|
|
const persist = (next) => {
|
|
todos.value = saveDutyTodos(next);
|
|
};
|
|
|
|
const addTodo = () => {
|
|
const text = String(draft.value || "").trim();
|
|
if (!text) {
|
|
uni.showToast({
|
|
title: "请输入待办内容",
|
|
icon: "none",
|
|
});
|
|
return;
|
|
}
|
|
persist([createDutyTodo(text), ...todos.value]);
|
|
draft.value = "";
|
|
};
|
|
|
|
const updateTodo = (id, value) => {
|
|
const text = String(value || "").trim();
|
|
persist(
|
|
todos.value
|
|
.map((item) => (item.id === id ? { ...item, text } : item))
|
|
.filter((item) => item.text),
|
|
);
|
|
};
|
|
|
|
const onTodoBlur = (id, event) => {
|
|
updateTodo(id, event?.detail?.value);
|
|
};
|
|
|
|
const toggleTodo = (id) => {
|
|
persist(
|
|
todos.value.map((item) =>
|
|
item.id === id ? { ...item, done: !item.done } : item,
|
|
),
|
|
);
|
|
};
|
|
|
|
const removeTodo = (id) => {
|
|
persist(todos.value.filter((item) => item.id !== id));
|
|
};
|
|
|
|
const goBack = () => {
|
|
uni.navigateBack({
|
|
fail: () => {
|
|
uni.navigateTo({ url: "/pages/index/index" });
|
|
},
|
|
});
|
|
};
|
|
|
|
onShow(() => {
|
|
todos.value = loadDutyTodos();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.page-container {
|
|
height: var(--pad-h);
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: #eef3f9;
|
|
}
|
|
|
|
.page-toolbar {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
gap: 12px;
|
|
padding: calc(env(safe-area-inset-top) + 10px) 20px 10px;
|
|
background: #fff;
|
|
border-bottom: 1px solid #d7e2ee;
|
|
box-shadow: 0 8px 24px rgba(30, 58, 138, 0.06);
|
|
z-index: 20;
|
|
}
|
|
|
|
.page-toolbar button {
|
|
width: auto;
|
|
flex: none;
|
|
}
|
|
|
|
.back-btn {
|
|
width: auto;
|
|
min-width: 84px;
|
|
height: 40px;
|
|
padding: 0 14px;
|
|
margin: 0;
|
|
gap: 4px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.toolbar-title-wrap {
|
|
flex-shrink: 0;
|
|
padding-left: 10px;
|
|
border-left: 3px solid #1d4ed8;
|
|
}
|
|
|
|
.toolbar-title {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: #1e3a8a;
|
|
}
|
|
|
|
.add-bar {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 14px 20px;
|
|
background: #fff;
|
|
border-bottom: 1px solid #d7e2ee;
|
|
}
|
|
|
|
.add-input {
|
|
flex: 1;
|
|
height: 42px;
|
|
padding: 0 12px;
|
|
background: #f4f7fb;
|
|
border: 1px solid #d7e2ee;
|
|
border-radius: 10px;
|
|
font-size: 15px;
|
|
color: #1e293b;
|
|
}
|
|
|
|
.add-btn {
|
|
width: 88px;
|
|
height: 42px;
|
|
}
|
|
|
|
.todo-list {
|
|
flex: 1;
|
|
min-height: 0;
|
|
padding: 12px 20px 20px;
|
|
}
|
|
|
|
.empty-text {
|
|
padding: 48px 0;
|
|
text-align: center;
|
|
color: #94a3b8;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.todo-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
padding: 10px 12px;
|
|
background: #fff;
|
|
border: 1px solid #d7e2ee;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.todo-check {
|
|
flex-shrink: 0;
|
|
width: 28px;
|
|
height: 28px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.todo-input {
|
|
flex: 1;
|
|
min-width: 0;
|
|
height: 36px;
|
|
font-size: 15px;
|
|
color: #1e293b;
|
|
}
|
|
|
|
.todo-input-done {
|
|
color: #94a3b8;
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.del-btn {
|
|
width: auto;
|
|
min-width: 64px;
|
|
height: 32px;
|
|
padding: 0 12px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.btn {
|
|
width: auto;
|
|
min-width: 84px;
|
|
height: 32px;
|
|
margin: 0;
|
|
border-radius: 10px;
|
|
font-size: 14px;
|
|
border: none;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.btn::after {
|
|
border: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: #2563eb;
|
|
color: #fff;
|
|
}
|
|
|
|
.btn-ghost {
|
|
background: #fff;
|
|
color: #1e3a8a;
|
|
border: 1px solid #c7d7ea;
|
|
}
|
|
</style>
|