菰城鸥鹭
2026-03-13
点 赞
0
热 度
13
评 论
0

第2章生成式人工智能实践课后练习

  1. 首页
  2. 第2章生成式人工智能实践课后练习

说到生成式人工智能这就不得不提及我常用的 kimi,DeepSeek 等一众 AI 工具了。
当前我用的有

kimi( www.kimi.com

360 智脑( chat.360.cn

DeepSeek( www.deepseek.com

TRAE( www.trae.cn

千问( www.qianwen.com

元宝( yuanbao.tencent.com

辅助开发的有 uni-agent CodeGenie 等


下面我将列举几个近期我通过这些 AI 工具衍生出来或者对我研发有帮助的一些示例

机制一班云APP的修改

此前将 vue3 的项目尝试使用 uni-app x 这个相对较新的框架重构

uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎
官方文档:https://doc.dcloud.net.cn/uni-app-x/

与 web 开发相比,uni-app x 在 App 平台最大的变化有 2 个:

  • 弱类型的 js 改为了强类型的 uts

  • 不再使用 webview 渲染,导致 css 有变化

这导致我的项目迁移在先前的很长一段时间进展缓慢,比如不同类型不能赋值、比较、运算等等。

我通过 Kimi、DeepSeek。在uni-agent 辅助下修复了问题,现在 AI 生成的质量真的比去年年初的时候高很多了,至少对于大多数的前端完全够用了。

如今的 机制一班云 APP V0.0.1 已经完成了大多数功能的迁移,配合 uniCloud 真的开发起来方便多了。

当我引入 升级中心 uni-upgrade-center,当我暂时不需要更新通过修改 layout.uvue 中的 checkForUpdate 方法,静默处理错误,避免控制台输出干扰,DeepSeek 可以为我提供逻辑清晰的代码。

async checkForUpdate() {
  console.log('[layout] checking for update...');
  try {
    await checkUpdate();
  } catch (error) {
    // 忽略无更新或配置错误,仅打印调试信息
    console.debug('[layout] checkUpdate result (can be ignored):', error);
  }
}

当然如果当你开发感到疲惫时也可以让其生成完整的页面源码

例如向 AI 提供如下

请为 jzyby-schedule 表数据添加一项控制是否显示到列表中,值为 0 时不显示在列表中,值为 1 时显示在 Schedule.uvue 列表中,Schedule.uvue 列表倒序显示,一次加载 10 条后续分页显示。

{
  "bsonType": "object",
  "required": [
    "title",
    "url",
    "sort"
  ],
  "permission": {
    "read": true,
    "create": false,
    "update": false,
    "delete": false
  },
  "properties": {
    "_id": {
      "description": "ID,系统自动生成"
    },
    "title": {
      "bsonType": "string",
      "description": "日程标题",
      "label": "标题",
      "trim": "both"
    },
    "url": {
      "bsonType": "string",
      "description": "关联网址",
      "label": "网址",
      "format": "url",
      "trim": "both"
    },
    "description": {
      "bsonType": "string",
      "description": "日程描述",
      "label": "描述"
    },
    "icon": {
      "bsonType": "string",
      "description": "图标 emoji 或图片路径",
      "default": "????"
    },
    "sort": {
      "bsonType": "int",
      "description": "排序序号",
      "minimum": 0
    },
    "createTime": {
      "bsonType": "timestamp",
      "description": "创建时间"
    },
    "updateTime": {
      "bsonType": "timestamp",
      "description": "更新时间"
    }
  }
}

此时等待一段时间 AI 便会生成如下的信息
jzyby-schedule 表添加 isShow 字段,并在 Schedule.uvue 中实现分页加载与显示控制。

jzyby-schedule 表添加 isShow 字段,并在 Schedule.uvue 中实现分页加载与显示控制。

1. 修改数据库表结构(可选但推荐)

在原表结构中增加 isShow 字段,用于控制是否在列表中显示:

{
  "bsonType": "object",
  "required": ["title", "url", "sort"],
  "permission": {
    "read": true,
    "create": false,
    "update": false,
    "delete": false
  },
  "properties": {
    "_id": { "description": "ID,系统自动生成" },
    "title": { "bsonType": "string", "description": "日程标题", "label": "标题", "trim": "both" },
    "url": { "bsonType": "string", "description": "关联网址", "label": "网址", "format": "url", "trim": "both" },
    "description": { "bsonType": "string", "description": "日程描述", "label": "描述" },
    "icon": { "bsonType": "string", "description": "图标 emoji 或图片路径", "default": "📅" },
    "sort": { "bsonType": "int", "description": "排序序号", "minimum": 0 },
    "isShow": { "bsonType": "int", "description": "是否显示(0不显示,1显示)", "default": 1, "minimum": 0, "maximum": 1 },
    "createTime": { "bsonType": "timestamp", "description": "创建时间" },
    "updateTime": { "bsonType": "timestamp", "description": "更新时间" }
  }
}

2. 修改 Schedule.uvue 实现分页与过滤

以下是完整代码,已添加分页逻辑、底部加载提示,并按 createTime 倒序排列。

<template>
  <view class="schedule-page" :class="{ 'night-mode': isNight }" :style="{ backgroundColor: bgColor }">
    <view class="schedule-header" :style="{ height: headerHeight + 'px' }">
      <text class="header-title">{{ tabTitles[currentTab] }}</text>
    </view>

    <scroll-view
      class="schedule-content"
      scroll-y
      :show-scrollbar="false"
      :style="{ top: headerHeight + 'px' }"
      @scrolltolower="loadMore"
      lower-threshold="100"
    >
      <view v-if="loading && scheduleList.length === 0" class="loading-container">
        <text class="loading-text">加载日程中...</text>
      </view>

      <view v-else-if="scheduleList.length > 0" class="list-container">
        <view
          v-for="(item, index) in scheduleList"
          :key="item._id != null ? item._id : index"
          class="list-item"
          :class="{ 'night-item': isNight }"
          @click="goToWebView(item)"
        >
          <view class="item-icon">
            <text class="icon-text">{{ item.icon != null ? item.icon : '📅' }}</text>
          </view>
          <view class="item-info">
            <text class="item-title">{{ item.title }}</text>
            <text class="item-desc">{{ item.description != null ? item.description : '暂无描述' }}</text>
          </view>
          <view class="item-arrow">
            <text class="arrow-icon">›</text>
          </view>
        </view>
        <!-- 底部加载状态 -->
        <view v-if="loadingMore" class="loading-more">
          <text class="loading-more-text">加载更多...</text>
        </view>
        <view v-if="!hasMore && scheduleList.length > 0" class="no-more">
          <text class="no-more-text">没有更多了</text>
        </view>
      </view>

      <view v-else class="empty-container">
        <text class="empty-icon">📭</text>
        <text class="empty-text">暂无日程安排</text>
      </view>
    </scroll-view>
  </view>
</template>

<script>
  import { getStoredTheme } from '@/store/theme';

  const DB_COLLECTION = 'jzyby-schedule';
  const PAGE_SIZE = 10; // 每页加载数量

  type ScheduleItem = {
    _id?: string | null;
    title: string;
    url: string;
    description?: string | null;
    icon?: string | null;
    sort?: number;
    createTime?: number; // 用于倒序排序
  }

  export default {
    props: {
      headerHeight: { type: Number, default: 0 },
      isNight: { type: Boolean, default: false }
    },
    data() {
      return {
        currentTab: 1,
        tabTitles: ['班级主页', '日程管理', '实用工具', '文档库', '更多'],
        loading: false,        // 首次加载
        loadingMore: false,    // 加载更多状态
        scheduleList: [] as ScheduleItem[],
        bgColor: '#667eea',
        pageNo: 1,
        hasMore: true,
        totalCount: 0,         // 总记录数(可选)
      };
    },
    mounted() {
      console.log('[Schedule] mounted');
      this.loadBgColor();
      this.loadFirstPage();
      uni.$on('backgroundColorChange', this.handleBgColorChange);
    },
    beforeUnmount() {
      uni.$off('backgroundColorChange', this.handleBgColorChange);
    },
    methods: {
      loadBgColor() {
        const color = uni.getStorageSync('background_color');
        if (color != null) {
          this.bgColor = '' + color;
        }
      },
      handleBgColorChange(color: string) {
        console.log('[Schedule] bgColor changed:', color);
        this.bgColor = color;
      },
      // 首次加载第一页
      async loadFirstPage() {
        this.loading = true;
        this.scheduleList = [];
        this.pageNo = 1;
        this.hasMore = true;
        await this.loadData(true);
        this.loading = false;
      },
      // 加载更多(滚动到底部触发)
      async loadMore() {
        if (this.loadingMore || !this.hasMore) return;
        await this.loadData(false);
      },
      // 核心加载函数
      async loadData(isFirstPage: boolean) {
        if (!isFirstPage) {
          this.loadingMore = true;
        }
        try {
          const db = uniCloud.databaseForJQL();
          const collection = db.collection(DB_COLLECTION);

          // 构建查询:只显示 isShow 为 1 的数据(如果字段不存在,则视为 0,不返回;但实际应确保数据库有该字段)
          // 如果数据库没有 isShow 字段,可以暂时注释掉 where 条件,或者先不限制,按需求调整
          const query = collection.where({
            isShow: 1
          }).orderBy('createTime', 'desc') // 按创建时间倒序
            .skip((this.pageNo - 1) * PAGE_SIZE)
            .limit(PAGE_SIZE);

          // 获取数据,同时获取总数(可选,用于判断是否有更多)
          const res = await query.get({ getCount: true });

          if (res != null && res.data != null && Array.isArray(res.data)) {
            const newList = res.data as ScheduleItem[];
            if (isFirstPage) {
              this.scheduleList = newList;
            } else {
              this.scheduleList = this.scheduleList.concat(newList);
            }

            // 判断是否还有更多
            if (newList.length < PAGE_SIZE) {
              this.hasMore = false;
            } else {
              this.pageNo++;
            }
          } else {
            console.log('[Schedule] 返回数据格式异常');
            if (isFirstPage) this.scheduleList = [];
          }
        } catch (error) {
          console.error('[Schedule] 加载失败:', error);
          uni.showToast({ title: '加载失败', icon: 'none' });
          if (isFirstPage) this.scheduleList = [];
        } finally {
          if (isFirstPage) {
            this.loading = false;
          } else {
            this.loadingMore = false;
          }
        }
      },
      goToWebView(item: ScheduleItem) {
        uni.navigateTo({
          url: `/pages/web/web?title=${encodeURIComponent(item.title)}&url=${encodeURIComponent(item.url)}`
        });
      }
    }
  };
</script>

<style lang="scss">
  .schedule-page {
    width: 100%;
    height: 100%;
    position: relative;
    transition: background-color 0.3s;

    &.night-mode {
      background-color: #0a1a3a !important;
    }
  }

  .schedule-header {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: transparent;
    z-index: 10;

    .header-title {
      font-size: 36rpx;
      font-weight: 500;
      color: #ffffff;
    }
  }

  .schedule-content {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 30rpx;
    padding-bottom: 160rpx;
  }

  .loading-container {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 300rpx;

    .loading-text {
      color: rgba(255, 255, 255, 0.8);
      font-size: 28rpx;
    }
  }

  .list-container {
    display: flex;
    flex-direction: column;
  }

  .list-item {
    display: flex;
    align-items: center;
    padding: 30rpx 24rpx;
    background-color: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(10rpx);
    border-radius: 24rpx;
    transition: background-color 0.3s;
    margin-bottom: 24rpx;

    &:last-child {
      margin-bottom: 0;
    }

    &.night-item {
      background-color: rgba(10, 26, 58, 0.6);
    }

    .item-icon {
      width: 80rpx;
      height: 80rpx;
      border-radius: 40rpx;
      background-color: rgba(255, 255, 255, 0.2);
      display: flex;
      align-items: center;
      justify-content: center;
      margin-right: 24rpx;
      flex-shrink: 0;

      .icon-text {
        font-size: 40rpx;
      }
    }

    .item-info {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-width: 0;

      .item-title {
        font-size: 32rpx;
        font-weight: 500;
        color: #ffffff;
        margin-bottom: 8rpx;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .item-desc {
        font-size: 26rpx;
        color: rgba(255, 255, 255, 0.7);
        line-height: 1.4;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }

    .item-arrow {
      width: 60rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;

      .arrow-icon {
        font-size: 48rpx;
        color: rgba(255, 255, 255, 0.5);
      }
    }
  }

  .loading-more, .no-more {
    padding: 30rpx 0;
    text-align: center;

    .loading-more-text, .no-more-text {
      font-size: 26rpx;
      color: rgba(255, 255, 255, 0.6);
    }
  }

  .empty-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 500rpx;

    .empty-icon {
      font-size: 80rpx;
      margin-bottom: 20rpx;
      opacity: 0.7;
    }

    .empty-text {
      color: rgba(255, 255, 255, 0.6);
      font-size: 28rpx;
    }
  }
</style>

3. 使用说明

  • 分页加载:首次加载第一页(10条),滚动到底部自动加载下一页。
  • 显示控制:只读取数据库中 isShow === 1 的记录。如需临时显示所有记录(如测试),可注释掉 where({ isShow: 1 }) 条件。
  • 排序:按 createTime 降序排列,最新的在前面。如需按其他字段(如 sort)排序,可调整 orderBy 参数。
  • 数据库字段:请确保 jzyby-schedule 表中已添加 isShow 字段,并设置默认值为 1。如果数据库中没有该字段,查询将返回空结果,建议使用云数据库的 update 命令批量添加字段,或在后台管理界面手动添加。

4. 后续优化建议

  • 可增加错误重试机制。
  • 当总数据量很大时,可使用 res.count 显示总条数。
  • 为提升体验,可在加载更多时显示骨架屏。

以上修改已满足你的需求。如有任何问题,欢迎继续交流。

AI音乐的制作

使用 AI 可以轻松的生成人声和曲,菰城鸥鹭 浙里星光 https://c6.y.qq.com/base/fcgi-bin/u?__=z6gBwQ0pxkUr


你好鸭!

菰城鸥鹭

istp 鉴赏家

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。

切换评论

目录

欢迎来到菰城鸥鹭的站点,为您导航全站动态

112 文章数
31 分类数
3 评论数
38标签数
最近评论
菰城鸥鹭

菰城鸥鹭


测试