uniapp学习3,简易记事本

html 复制代码
<template>
  <view class="wrap">
    <!-- 顶部 -->
    <view class="header">
      <text class="title">简易记事本</text>
    </view>

    <!-- 搜索 -->
    <view class="search-box">
      <input v-model="keyword" placeholder="搜索笔记..." @input="doSearch" />
    </view>

    <!-- 列表 -->
    <view class="list">
      <view class="item" v-for="(item, idx) in showList" :key="idx">
        <view class="content" @click="toEdit(item)">
          <text class="txt">{{ item.title }}</text>
          <text class="time">{{ item.time }}</text>
        </view>
        <view class="del" @click="delNote(idx)">删除</view>
      </view>

      <view class="empty" v-if="showList.length === 0">
        暂无笔记,点击右下角新增
      </view>
    </view>

    <!-- 悬浮新增按钮 -->
    <view class="add-float-btn" @click="toEdit">
      <text class="add-icon">+</text>
    </view>

    <!-- 编辑弹窗 -->
    <view class="modal" v-show="showModal">
      <view class="card">
        <view class="modal-head">
          <text>{{ currentItem.idx > -1 ? '编辑笔记' : '新增笔记' }}</text>
          <view @click="closeModal">×</view>
        </view>
        <textarea v-model="form.title" placeholder="请输入内容" class="area"></textarea>
        <view class="btns">
          <button @click="closeModal">取消</button>
          <button @click="saveNote">保存</button>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      noteList: [],
      showList: [],
      keyword: '',
      showModal: false,
      form: { title: '' },
      currentItem: { idx: -1 }
    }
  },
  onLoad() {
    this.getList()
  },
  methods: {
    // 读取本地
    getList() {
      let list = uni.getStorageSync('noteList') || []
      this.noteList = list
      this.showList = list
    },
    // 保存本地
    setList(list) {
      this.noteList = list
      this.showList = list
      uni.setStorageSync('noteList', list)
    },
    // 搜索
    doSearch() {
      let k = this.keyword.trim()
      if (!k) {
        this.showList = this.noteList
        return
      }
      this.showList = this.noteList.filter(item => {
        return item.title.includes(k)
      })
    },
    // 打开编辑
    toEdit(item) {
      if (item) {
        this.currentItem = item
        this.form.title = item.title
      } else {
        this.currentItem = { idx: -1 }
        this.form.title = ''
      }
      this.showModal = true
    },
    // 关闭
    closeModal() {
      this.showModal = false
      this.form.title = ''
    },
    // 保存
    saveNote() {
      let title = this.form.title.trim()
      if (!title) return uni.showToast({ title: '请输入内容', icon: 'none' })

      let time = new Date().toLocaleString()
      let list = JSON.parse(JSON.stringify(this.noteList))

      if (this.currentItem.idx > -1) {
        // 编辑
        list[this.currentItem.idx] = { title, time }
      } else {
        // 新增
        list.unshift({ title, time })
      }

      this.setList(list)
      this.closeModal()
      uni.showToast({ title: '保存成功' })
    },
    // 删除
    delNote(idx) {
      uni.showModal({
        title: '提示',
        content: '确定删除该笔记?',
        success: res => {
          if (res.confirm) {
            let list = JSON.parse(JSON.stringify(this.noteList))
            list.splice(idx, 1)
            this.setList(list)
            uni.showToast({ title: '删除成功' })
          }
        }
      })
    }
  }
}
</script>

<style scoped>
.wrap {
  padding: 20rpx;
  background: #f7f8fa;
  min-height: 100vh;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
}
.title {
  font-size: 38rpx;
  font-weight: bold;
}
/* 悬浮圆形新增按钮 */
.add-float-btn {
  position: fixed;
  right: 40rpx;
  bottom: 40rpx;
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  background-color: #42b983;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8rpx 16rpx rgba(66, 185, 131, 0.3);
  z-index: 99;
}

.add-icon {
  font-size: 50rpx;
  color: #fff;
  font-weight: bold;
  line-height: 1;
}
.search-box {
  background: #fff;
  border-radius: 12rpx;
  padding: 20rpx;
  margin-bottom: 20rpx;
}
.search-box input {
  font-size: 28rpx;
}
.list {
  background: #fff;
  border-radius: 12rpx;
  overflow: hidden;
}
.item {
  display: flex;
  padding: 30rpx;
  border-bottom: 1rpx solid #eee;
}
.content {
  flex: 1;
}
.txt {
  font-size: 30rpx;
  display: block;
  margin-bottom: 10rpx;
}
.time {
  font-size: 24rpx;
  color: #999;
}
.del {
  color: #ff4d4f;
  font-size: 26rpx;
  align-self: center;
  padding: 10rpx;
}
.empty {
  padding: 60rpx;
  text-align: center;
  color: #999;
}
.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}
.card {
  width: 80%;
  background: #fff;
  border-radius: 20rpx;
  overflow: hidden;
}
.modal-head {
  padding: 30rpx;
  display: flex;
  justify-content: space-between;
  font-size: 32rpx;
  border-bottom: 1rpx solid #eee;
}
.area {
  padding: 30rpx;
  min-height: 300rpx;
  font-size: 30rpx;
}
.btns {
  display: flex;
  padding: 20rpx;
  justify-content: flex-end;
  gap: 20rpx;
}
.btns button {
  padding: 15rpx 30rpx;
  border-radius: 10rpx;
  font-size: 28rpx;
}
.btns button:first-child {
  background: #f5f5f5;
}
.btns button:last-child {
  background: #42b983;
  color: #fff;
}
</style>
相关推荐
程序员雷欧2 小时前
大模型应用开发学习第一天
学习
星幻元宇VR2 小时前
VR航空航天学习机|一场触手可及的太空之旅
科技·学习·安全·vr·虚拟现实
Можно2 小时前
uni-app 三端上线全流程指南:H5 / 小程序 / App 完整发布手册
小程序·uni-app
be to FPGAer2 小时前
低功耗设计的考虑因素
学习
chase。2 小时前
【学习笔记】RoboForge:让文本指令“落地”到人形机器人——一个物理优化与隐式驱动的端到端框架
笔记·学习·机器人
chase。2 小时前
【学习笔记】从经典算法到通用神经运动规划器
笔记·学习·算法
cskywit3 小时前
【TMI2025】赋予AI医生“解耦思维”:基于概率属性学习(PAL)的皮肤病变分割框架拆解
人工智能·学习
莱茶荼菜3 小时前
LLM学习
学习
啥咕啦呛3 小时前
java打卡学习6:集合框架 Collection
java·windows·学习