您的位置:首页 > 游戏 > 游戏 > 使用uniapp+Django开发的在线工具网站

使用uniapp+Django开发的在线工具网站

2024/11/15 15:48:07 来源:https://blog.csdn.net/m0_63533079/article/details/140905836  浏览:    关键词:使用uniapp+Django开发的在线工具网站

引言

在当今数字化时代,在线工具网站为用户提供了便捷的服务和功能,本文分享了我使用UniApp和Django开发的一款多平台在线工具网站。通过这个项目,我探索了跨平台开发与强大的后端框架结合的优势,实现了用户友好的界面和稳健的功能。

技术选型

我选择UniApp作为前端开发工具,主要因为它能够高效地实现同时支持多个平台(Web、小程序、App)的开发需求。而Django作为后端框架,则因其快速开发能力、自带后台管理系统、优秀的安全性和灵活的数据管理而备受推崇。

项目环境

前端框架:uniapp

前端编辑器:HbuilderX 版本号4.24

编辑器官网:HBuilderX-高效极客技巧

后端解释器版本:python 3.10.5

后端框架:django==3.0

后端编辑器:vscode 版本1.92.0

项目创建

前端uniapp项目创建可参考

1 uniapp创建项目前的准备工作 及 创建项目 - 云里知音 - 博客园

后端django项目创建可参考:
怎样安装和创建Django项目?

项目概述

我的在线工具网站旨在为用户提供各种实用工具和服务,包括但不限于实用工具、查询工具、休闲娱乐工具、在线转换、在线游戏、在线加密等功能。用户可以通过Web浏览器、微信小程序或安卓访问和使用这些工具。

前端开发(UniApp)

页面设计与布局

在UniApp中,我采用了简洁直观的页面设计,保证了用户操作的流畅性和友好性。每个工具都有清晰的功能入口,以便用户快速上手。

功能实现

项目采用屏幕自适应,当屏幕宽度小于600px的时候,则一行三个工具,如果屏幕尺寸够大,则一行四个工具,可以完美在移动端适配

主界面代码:

<template><!-- 加载动画 --><view class="loading" v-if="!dataLoaded"><view class="item item-1"></view><view class="item item-2"></view><view class="item item-3"></view><view class="item item-4"></view></view><!-- 主要容器 --><view class="container" v-if="dataLoaded"><view class="search-box"><image class="search-icon" src="/static/search.png"></image><input v-model="keyword" @input="handleSearch" placeholder="请输入搜索关键词" class="search-input" /></view><!-- 循环渲染多个盒子 --><view v-for="(category, index) in filteredToolCategories" :key="index" class="category-box"><view class="category-name">{{ category.title }}</view><!-- 使用循环渲染每个工具 --><view class="tool-list"><view v-for="(tool, idx) in category.tools" :key="idx" class="tool-item"@click="handleToolClick(tool.link)"><image :src="tool.icon" class="tool-icon"></image><text class="tool-name">{{ tool.name }}</text></view></view></view><!-- 底部米白色色块 --><view class="footer-block"><!-- 底部文字信息 --><view class="footer-text">本站工具严禁用于非法用途,本站不承担任何因使用工具造成的损失及责任。</view><!-- 底部导航链接 --><view class="footer-links"><navigator url="/pages/about/about" open-type="navigate">关于我们</navigator><navigator url="/pages/serviceAgreement/serviceAgreement" open-type="navigate">服务条款</navigator><navigator url="/pages/PrivacyPolicy/PrivacyPolicy" open-type="navigate">隐私政策</navigator><a href="https://support.qq.com/products/660601" target="_blank">反馈建议</a></view><!-- 版权信息 --><view class="footer-text">Copyright © 2024 TT在线工具 All Rights Reserved 滇ICP备2024034889号-1 </view></view></view>
</template>

script:

<script>export default {data() {return {toolCategories: [],keyword: '', // 查找工具dataLoaded: false, // 标记数据是否加载完成// 弹出提示modalConfig: {showModal: 'false', //弹出组件是否显示title: '提示', // 弹窗标题content: '提示内容', // 弹窗内容}};},computed: {filteredToolCategories() {if (!this.keyword) {return this.toolCategories;}return this.toolCategories.map(category => {return {...category,tools: category.tools.filter(tool => tool.name.includes(this.keyword))};}).filter(category => category.tools.length > 0);}},created() {this.fetchToolData();},// 加载完成后调用方法mounted() {// 判断是否为ture 是的话调用函数 否则不调用if (this.modalConfig.showModal === 'true') {this.showModalDialog();} else {console.log('加载动画函数未被调用');}},methods: {async fetchToolData() {try {const res = await uni.request({url: 'https://ttgj.top/tools/',method: 'GET',});const data = res.data;// 对分类根据返回的sort字段进行排序data.sort((a, b) => a.category.sort - b.category.sort);data.forEach(item => {const title = item.category.title;const name = item.name;const link = item.link;const icon = item.icon;let existingCategory = this.toolCategories.find(category => category.title === title);if (!existingCategory) {existingCategory = {title: title,tools: []};this.toolCategories.push(existingCategory);}existingCategory.tools.push({name: name,link: link,icon: icon});});this.dataLoaded = true; // 数据加载完成后显示页面内容} catch (error) {console.error('获取工具列表错误:', error);}},handleSearch() {// 由于已在 computed 中实现过滤,此处无需额外代码},handleToolClick(link) {console.log('跳转值:', link);//如果小于768则认为移动端const isMobile = window.innerWidth < 768;//判断isMobile是否为true 是的话执行这个条件if (isMobile) {if (link.startsWith('http')) {console.log('http链接', link);window.open(link, '_blank'); // 新标签页打开外部链接} else {// 移动端,使用uni.navigateTo方法uni.navigateTo({url: "/pages/" + link,animationType: 'push',});}//不为true执行这个条件} else {// 非移动端(假设是PC端),使用window.open方法if (link.startsWith('http')) {console.log('http链接', link);window.open(link, '_blank'); // 新标签页打开外部链接} else {console.log('path路径');const currentOrigin = window.location.origin; // 获取当前页面的 origin,例如:http://localhost:5173window.open(currentOrigin + '/pages/' + link, '_blank'); // 新标签页打开内部链接}}},showModalDialog() {uni.showModal({title: this.modalConfig.title,content: this.modalConfig.content,showCancel: true,cancelText: '取消',confirmText: '确认',success: (res) => {if (res.confirm) {console.log('用户点击了确认按钮');// 可以在这里添加确认按钮的逻辑处理} else if (res.cancel) {console.log('用户点击了取消按钮');// 可以在这里添加取消按钮的逻辑处理}// 关闭模态弹窗后,将 isModalVisible 设置为 falsethis.isModalVisible = false;}});}}};
</script>

style:

<style scoped lang="scss">.container {display: flex;flex-wrap: wrap;padding: 50rpx;}.search-box {margin-bottom: 20px;width: 100%;display: flex;align-items: center;background-color: #F9F7F7;border-radius: 15rpx;padding: 10rpx 20rpx;}.search-icon {width: 35rpx;height: 35rpx;margin-right: 10rpx;/* 设置搜索图标与输入框之间的间距 */}.search-input {flex: 1;font-size: 35rpx;color: #333333;border: none;background: none;outline: none;}.category-box {width: 100%;margin-bottom: 20px;padding: 10px;border: 1px solid #ccc;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);border-radius: 10px;}// 分类名字.category-name {font-size: 16px;color: #F9F7F7;margin-bottom: 10px;background-color: #71C9CE;padding: 5px 10px;display: inline-block;border-radius: 5px;}// 工具列表父元素.tool-list {display: flex;flex-wrap: wrap;}// 工具名字和图标.tool-item {width: calc(25% - 10px);/*表示将父容器的宽度分成四等份(每份占25%),然后再从每份中减去10像素的间距*//* 一行四个工具,间隔为10px */margin-right: 10px;margin-bottom: 10px;margin-top: 20px;/* 添加工具和标题之间 */display: flex;flex-direction: column;align-items: center;}// 当页面宽度小于500px 则执行这个代码@media (max-width: 500px) {.tool-item {width: calc(33% - 10px);/*表示将父容器的宽度分成四等份(每份占33%),然后再从每份中减去10像素的间距*//* 一行三个工具,间隔为10px */margin-right: 10px;margin-bottom: 10px;margin-top: 20px;/* 添加工具和标题之间 */display: flex;flex-direction: column;align-items: center;}}// 工具图标.tool-icon {width: 40px;height: 40px;margin-bottom: 5px;}// 工具名字.tool-name {font-size: 14px;text-align: center;white-space: nowrap;/* 防止换行 */overflow: hidden;/* 隐藏超出部分 */text-overflow: ellipsis;/* 如果文本超出部分被隐藏,则显示省略号 */display: inline-block;}// 当页面宽度小于500px 则执行这个代码@media (max-width: 500px) {.tool-name {font-size: 14px;text-align: center;width: 99%;/* 宽度超过99%则显示省略号 */white-space: nowrap;/* 防止换行 */overflow: hidden;/* 隐藏超出部分 */text-overflow: ellipsis;/* 如果文本超出部分被隐藏,则显示省略号 */display: inline-block;}}.footer-block {bottom: 0;/* 固定在底部 */box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.1);/* 添加轻微阴影效果 */padding: 20px;text-align: center;margin: 0 auto;/* 居中 */width: 100%;/* 控制宽度,左右展开 */}.footer-text {font-size: 14px;color: #666;margin-bottom: 10px;}.footer-links {display: flex;/* 使用 Flexbox 布局 */justify-content: center;/* 居中对齐 */gap: 20px;/* 设置子元素之间的间距 */margin-bottom: 10px;}a {text-decoration: none;font-size: 14px;color: #007bff;}a:hover {text-decoration: underline;/* 悬停时下划线效果 */}.footer-links navigator {font-size: 14px;color: #007bff;/* 链接颜色 */}.footer-links navigator:hover {text-decoration: underline;/* 悬停时下划线效果 */}.loading {position: absolute;width: 200px;height: 200px;top: 0;bottom: 0;left: 0;right: 0;margin: auto;}.item {width: 100px;height: 100px;position: absolute;}.item-1 {background-color: #FA5667;top: 0;left: 0;z-index: 1;animation: item-1_move 1.8s cubic-bezier(.6, .01, .4, 1) infinite;}.item-2 {background-color: #7A45E5;top: 0;right: 0;animation: item-2_move 1.8s cubic-bezier(.6, .01, .4, 1) infinite;}.item-3 {background-color: #1B91F7;bottom: 0;right: 0;z-index: 1;animation: item-3_move 1.8s cubic-bezier(.6, .01, .4, 1) infinite;}.item-4 {background-color: #FAC24C;bottom: 0;left: 0;animation: item-4_move 1.8s cubic-bezier(.6, .01, .4, 1) infinite;}@keyframes item-1_move {0%,100% {transform: translate(0, 0)}25% {transform: translate(0, 100px)}50% {transform: translate(100px, 100px)}75% {transform: translate(100px, 0)}}@keyframes item-2_move {0%,100% {transform: translate(0, 0)}25% {transform: translate(-100px, 0)}50% {transform: translate(-100px, 100px)}75% {transform: translate(0, 100px)}}@keyframes item-3_move {0%,100% {transform: translate(0, 0)}25% {transform: translate(0, -100px)}50% {transform: translate(-100px, -100px)}75% {transform: translate(-100px, 0)}}@keyframes item-4_move {0%,100% {transform: translate(0, 0)}25% {transform: translate(100px, 0)}50% {transform: translate(100px, -100px)}75% {transform: translate(0, -100px)}}
</style>

运行效果:

后端开发(Django)

数据库设计

我使用Django自带的ORM设计了数据库,包括工具分类名、工具名字及图片,确保了数据的安全和可靠性。以下是一个简化的模型示例:


from django.db import models  class ToolCategory(models.Model):  title = models.CharField(max_length=100,verbose_name='分类名')sort = models.IntegerField(default=1, verbose_name='排序')class Meta:# admin后台显示的子标题verbose_name='分类'   #增加按钮显示增加用户以及标题verbose_name_plural='工具分类列表'def __str__(self):  return self.titleclass Tool(models.Model):  name = models.CharField(max_length=100,verbose_name='工具名')icon = models.ImageField(upload_to='tool_ico',verbose_name='图标')  #从本地上传link = models.CharField(max_length=100,default='pathname/pathname',verbose_name='工具路径-链接')category = models.ForeignKey(ToolCategory, on_delete=models.CASCADE,verbose_name='工具分类')# 其他字段,如描述、使用方法等  class Meta:verbose_name='工具'   #增加按钮显示增加用户以及标题verbose_name_plural='工具列表'def __str__(self):  return self.name

API开发:

通过Django的视图函数和路由设置,我设计了一组RESTful API来处理前端请求,并与数据库进行交互。以下是一个简化的视图函数示例:

from django.shortcuts import render# Create your views here.from rest_framework import viewsets, mixins
from rest_framework.response import Response
from .models import Tool, ToolCategory
from .serializers import ToolSerializer, ToolCategorySerializer  # 假设你创建了这些序列化器class ToolCategoryViewSet(viewsets.ReadOnlyModelViewSet):queryset = ToolCategory.objects.all()serializer_class = ToolCategorySerializerclass ToolViewSet(viewsets.ModelViewSet):queryset = Tool.objects.all().select_related('category')  # 预加载关联的ToolCategory对象serializer_class = ToolSerializerdef get_queryset(self):# 你可以在这里添加额外的查询逻辑,比如过滤等return super().get_queryset()

在后端数据库添加数据后返回工具名字、工具图片、工具分类等信息:

成果展示与用户体验

经过不懈努力,我的在线工具网站已正式上线并稳定运行。该网站支持多平台访问,无论是PC端还是移动端,用户都能轻松使用。网站的用户体验得到了广大用户的积极反馈,特别是其界面设计的友好性和功能的完备性,更是获得了用户的高度认可。

总结与展望

通过此次项目,我不仅在技术上取得了显著的进步,还深刻体会到了UniApp和Django这两个框架在实际项目中的强大应用价值。它们为我提供了灵活的开发方式和高效的开发效率,使得我能够更专注于实现项目的核心功能。展望未来,我计划继续对在线工具网站进行优化和扩展,引入更多实用的功能和服务,以进一步提升用户体验,满足用户多样化的需求。

结语

如果你也对使用UniApp和Django开发项目充满兴趣,或者想要了解更多关于我的项目细节和技术实现,我非常欢迎你的联系。让我们携手共进,共同探索更多前沿技术和创新应用!

项目访问方式

为了让你更便捷地体验我的在线工具网站,以下是访问方式:

  • 项目网站地址:项目网址:TT工具-在线工具
  • 微信小程序访问二维码

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com