微信小程序-游记分享

微信小程序-游记分享,第1张

微信小程序-游记分享(无后台) 游记分享 博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020 作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11334 作业目标 1. 编写一个小程序,可以全新编写,也可以学习别人的小程序进行修改 2. 熟悉git代码管理流程,将源代码上传到到github 3. 在博客园班级中写一篇相应的博文 作业源代码 [email protected]:wfs2018/software-engineering.git 学号 31801131 翁芳胜 院系 浙大城市学院计算分院 项目描述

本项目的灵感来自于小红书和大众点评,年轻人常常在这些平台上发布吃喝玩乐的心得和推荐。


假期是时候想出去游玩却难以选择游玩地点。


于是想到做一个旅游日记共享平台,可以看他人的游玩经历和心得。


从而选择自己喜欢的游玩地点。


由于是第一次做小程序,没有相关知识和经验,本项目只完成了首页游记展示,发布,收藏和喜欢的简单前端搭建,后续随着进一步的学习会完善相关功能。




参考:https://github.com/harveyqing/BearDiary.git

项目页面展示






{
"pages": [
"pages/list/list",
"pages/mine/mine",
"pages/new/new",
"pages/entry/entry"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#5566aa",
"navigationBarTitleText": "游记分享",
"navigationBarTextStyle": "white",
"backgroundColor": "#eceff4"
},
"tabBar": {
"color": "#858585",
"selectedColor": "#39b5de",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/list/list",
"iconPath": "images/icons/mark.png",
"selectedIconPath": "images/icons/markHL.png",
"text": "印记"
},
{
"pagePath": "pages/mine/mine",
"iconPath": "images/icons/mine.png",
"selectedIconPath": "images/icons/mineHL.png",
"text": "我的"
}
]
},
"debug": true,
"sitemapLocation": "sitemap.json"
}

各页面代码

首页

wxml文件

<!-- dairy.wxml -->

<template name="content-item">
<block wx:if="{{content.type == 'TEXT'}}">
<view style="margin-top:30rpx">
<text wx:if="{{content.type == 'TEXT'}}" class="text">{{content.content}}</text>
</view>
</block>
<block wx:if="{{content.type == 'IMAGE'}}">
<image class="media" mode="aspectFill" src="{{content.content}}" bindtap="enterPreviewMode" data-src="{{content.content}}"></image>
<view style="margin-top: 10rpx">{{content.description}}</view>
</block>
<block wx:if="{{content.type == 'VIDEO'}}">
<video class="media" src="{{content.content}}"></video>
<view style="margin-top: 10rpx">{{content.description}}</view>
</block>
<template is="content-footer" data="{{content}}"></template>
</template> <!-- 正文footer -->
<template name="content-footer">
<view class="footer">
<view class="left">
<image mode="aspectFit" src="../../images/icons/poi.png"></image>
<text style="margin-left:10rpx;">{{content.poi.name}}</text>
</view>
<view class="right">
<image mode="aspectFit" src="../../images/icons/comment.png"></image>
<view>{{content.commentNum}}</view>
</view>
<view class="right">
<image mode="aspectFit" src="../../images/icons/like.png"></image>
<view>{{content.likeNum}}</view>
</view>
</view>
</template> <view class="container">
<view class="header" style="#ffffff">
<!--顶部固定工具栏-->
<view class="toolbar">
<image class="item" mode="aspectFit" wx:for="{{toolbar}}" src="{{item}}"></image>
</view> <!--meta信息区-->
<view class="title">
<image class="avatar" mode="aspectFit" src="{{diary.meta.avatar}}"> </image>
<view class="desc">
<view class="item">{{diary.meta.title}}</view>
<view class="item">{{diary.meta.meta}}</view>
</view>
</view>
</view> <!--正文-->
<view wx:for="{{diary.list}}" wx:for-item="content" class="content">
<template is="content-item" data="{{content}}"></template>
</view> <view id="footer">
<view class="container">
<view class="item" style="font-size:50rpx;">
<view style="display:inline-block">游记</view>
<view style="display:inline-block;margin-left:10rpx;color:#2EA1CA;">分享</view>
</view>
<view class="item" style="font-size:24rpx;color:gray">分享旅程,分享心情</view>
</view>
</view>
</view> <!-- 预览模式 -->
<swiper class="swiper-container" duration="400" current="{{previewIndex}}" bindtap="leavePreviewMode" style="display:{{previewMode ? 'block' : 'none'}};">
<block wx:for="{{mediaList}}" wx:for-item="media">
<swiper-item>
<image src="{{media.content}}" mode="aspectFit"></image>
</swiper-item>
</block>
</swiper>

Js文件

// entry.js

const toolbar = [
'../../images/nav/download.png', '../../images/nav/fav.png',
'../../images/nav/share.png', '../../images/nav/comment.png',
];
const app = getApp(); Page({
data: {
// 当前日志
diary: undefined, // 右上角工具栏
toolbar: toolbar, // 图片预览
previewMode: false, // 当前预览
previewIndex: 0, // 内容列表
mediaList: [],
}, // 加载日记
getDiary(params) {
console.log("Loading diary data...", params); var id = params["id"], diary;
app.getDiaryList(list => {
if (typeof id === 'undefined') {
diary = list[0];
} else {
diary = list[id];
}
}); this.setData({
diary: diary,
});
}, // 过滤出预览图片列表
getMediaList() {
if (typeof this.data.diary !== 'undefined' &&
this.data.diary.list.length) {
this.setData({
mediaList: this.data.diary.list.filter(
content => content.type === 'IMAGE'),
})
}
}, // 进入预览
enterPreviewMode(event) {
let url = event.target.dataset.src;
let urls = this.data.mediaList.map(media => media.content);
let previewIndex = urls.indexOf(url); this.setData({previewMode: true, previewIndex});
}, // 退出预览
leavePreviewMode() {
this.setData({previewMode: false, previewIndex: 0});
}, onLoad: function(params) {
this.getDiary(params);
this.getMediaList();
}, onHide: function() {
},
})

我的页面

Wxml文件

<!--mine.wxml-->

<template name="tab1">
<view>
</view>
</template> <template name="tab2">
<view>
</view>
</template> <template name="tab3">
<view>
</view>
</template> <template name="tab4">
<view>
</view>
</template> <view>
<!--全屏对话框-->
<view class="modal" style="{{modalShowStyle}}">
<view class="dialog">
<view class="modal-item" style="display:flex;justify-content:center;align-items:center;">
输入日记标题
</view>
<view class="modal-item" style="margin:0 auto;width:90%;">
<input type="text" bindinput="titleInput" style="background-color:white;border-radius:2px;" value="{{diaryTitle}}" placeholder="请输入日记标题"></input>
</view>
<view class="modal-button" style="width:100%">
<view style="color:green;border-right:1px solid #E5E7ED;" bindtap="touchAddNew">确定</view>
<view bindtap="touchCancel">取消</view>
</view>
</view>
</view> <view class="header">
<view class="profile">
<image class="avatar" mode="aspectFit" src="{{userInfo.avatar}}"></image>
<view class="description">
<view class="item">
<view style="margin-right:5px">{{userInfo.nickname}}</view>
<view>{{userInfo.sex}}</view>
</view>
<view class="item">{{userInfo.meta}}</view>
</view>
<image class="add" mode="aspectFill" src="../../images/icons/add.png" bindtap="touchAdd"></image>
</view> <view class="tablist">
<view wx:for="{{tabs}}" wx:for-index="idx" class="tab" bindtap="touchTab" style="{{item.extraStyle}}" id="{{idx}}">
<view class="content" style="color:{{highLightIndex == idx ? '#54BFE2' : ''}};">
<image class="image" mode="aspectFit" src="{{highLightIndex == idx ? item.iconActive : item.icon}}"></image>
<view style="margin-top:2px;">{{item.title}}</view>
</view>
</view>
</view>
</view> <template is="{{currentTab}}"></template>
</view>

Js

// mine.js

var iconPath = "../../images/icons/"
var tabs = [
{
"icon": iconPath + "mark.png",
"iconActive": iconPath + "markHL.png",
"title": "日记",
"extraStyle": "",
},
{
"icon": iconPath + "collect.png",
"iconActive": iconPath + "collectHL.png",
"title": "收藏",
"extraStyle": "",
},
{
"icon": iconPath + "like.png",
"iconActive": iconPath + "likeHL.png",
"title": "喜欢",
"extraStyle": "",
},
{
"icon": iconPath + "more.png",
"iconActive": iconPath + "moreHL.png",
"title": "更多",
"extraStyle": "border:none;",
},
]
var userInfo = {
avatar: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3049066004,1582117064&fm=26&gp=0.jpg",
nickname: "wfs",
sex: "♂", // 0, male; 1, female
meta: '10篇日记',
} Page({ // data
data: {
// 展示的tab标签
tabs: tabs, // 当前选中的标签
currentTab: "tab1", // 高亮的标签索引
highLightIndex: "0", // 模态对话框样式
modalShowStyle: "", // 待新建的日记标题
diaryTitle: "", // TODO 用户信息
userInfo: userInfo,
}, // 隐藏模态框
hideModal() {
this.setData({modalShowStyle: ""});
}, // 清除日记标题
clearTitle() {
this.setData({diaryTitle: ""});
}, onShow: function() {
this.hideModal();
this.clearTitle();
}, // 点击tab项事件
touchTab: function(event){
var tabIndex = parseInt(event.currentTarget.id);
var template = "tab" + (tabIndex + 1).toString(); this.setData({
currentTab: template,
highLightIndex: tabIndex.toString()
}
);
}, // 新建日记事件
touchAdd: function (event) {
this.setData({
modalShowStyle: "opacity:1;pointer-events:auto;"
})
}, // 新建日记
touchAddNew: function(event) {
this.hideModal(); wx.navigateTo({
url: "../new/new?title=" + this.data.diaryTitle,
});
}, // 取消标题输入
touchCancel: function(event) {
this.hideModal();
this.clearTitle();
}, // 标题输入事件
titleInput: function(event) {
this.setData({
diaryTitle: event.detail.value,
})
}
})

新建日记页面

<!--new.wxml-->

<template name="common">
<scroll-view class="container" scroll-y="true">
<view class="common-container">
<view class="item-group" wx:for="{{layoutList}}" wx:for-item="group">
<block wx:for="{{group}}" wx:for-item="item">
<block wx:if="{{item.type == 'TEXT'}}">
<view class="album-item content-text">
<view>{{item.content}}</view>
</view>
</block>
<block wx:elif="{{item.type == 'IMAGE'}}">
<image src="{{item.content}}" class="album-item" mode="aspectFill"></image>
</block>
<block wx:elif="{{item.type == 'VIDEO'}}">
<video class="album-item" src="{{item.content}}"></video>
</block>
</block>
</view>
</view>
</scroll-view> <view class="tabbar" style="display:{{showTab ? 'flex' : 'none'}};">
<view class="item" bindtap="inputTouch">
<image class="icon" mode="aspectFit" src="../../images/tabbar/text.png"></image>
</view>
<view class="item" bindtap="mediaTouch">
<image class="icon" mode="aspectFit" src="../../images/tabbar/image.png"></image>
</view>
<view class="item">
<image class="icon" mode="aspectFit" src="../../images/tabbar/more.png"></image>
</view>
</view> <action-sheet hidden="{{mediaActionSheetHidden}}" bindchange="mediaActionSheetChange">
<block wx:for-items="{{mediaActionSheetItems}}" wx:for-index="id">
<action-sheet-item class="action-item" bindtap="{{mediaActionSheetBinds[id]}}">
{{item}}
</action-sheet-item>
</block>
<action-sheet-cancel class='action-cacel'>取消</action-sheet-cancel>
</action-sheet>
</template> <template name="inputText">
<view class="input-container">
<view style="height:47rpx" wx:for="{{inputStatus.lines}}" wx:for-index="idx">
<input type="text" data-index="{{idx}}" placeholder="" bindinput="textInput" bindchange="textInputChange" value="{{item}}" auto-focus="{{idx == inputStatus.row ? true : false}}" bindfocus="focusInput"/>
</view>
</view>
<view class="tabbar">
<view class="item" style="width:50%" bindtap="inputCancel">
<image class="icon" mode="aspectFit" src="../../images/tabbar/cancel.png"></image>
</view>
<view class="item" style="width:50%" bindtap="inputDone">
<image class="icon" mode="aspectFit" src="../../images/tabbar/ok.png"></image>
</view>
</view>
</template> <view style="width:100%;height:100%">
<block wx:if="{{showMode == 'common'}}">
<template is="{{showMode}}" data="{{showTab: showTab, mediaActionSheetHidden: mediaActionSheetHidden, mediaActionSheetItems: mediaActionSheetItems, mediaActionSheetBinds: mediaActionSheetBinds, layoutList: layoutList}}"></template>
</block>
<block wx:if="{{showMode == 'inputText'}}">
<template is="{{showMode}}" data="{{inputStatus}}"></template>
</block>
<loading hidden="{{!showLoading}}" bindchange="hideLoading">
{{loadingMessage}}
</loading>
</view>

Js

// new.js
// TODO 并不是所有非中文字符宽度都为中文字符宽度一半,需特殊处理
// TODO 由于文本框聚焦存在bug,故编辑模式待实现 const input = require('../../utils/input');
const config = require('../../config');
const geo = require('../../services/geo');
const util = require('../../utils/util'); const RESOLUTION = 750; // 微信规定屏幕宽度为750rpx
const MARGIN = 10; // 写字面板左右margin
const ROW_CHARS = Math.floor((RESOLUTION - 2 * MARGIN) / config.input.charWidth);
const MAX_CHAR = 1000; // 最多输1000字符 // 内容布局
const layoutColumnSize = 3; // 日记内容类型
const TEXT = 'TEXT';
const IMAGE = 'IMAGE';
const VIDEO = 'VIDEO'; const mediaActionSheetItems = ['拍照', '选择照片', '选择视频'];
const mediaActionSheetBinds = ['chooseImage', 'chooseImage', 'chooseVideo']; var app = getApp(); Page({ data: {
// 日记对象
diary: {
meta: {},
list: [],
}, // 日记内容布局列表(2x2矩阵)
layoutList: [], // 是否显示loading
showLoading: false, // loading提示语
loadingMessage: '', // 页面所处模式
showMode: 'common', // 输入框状态对象
inputStatus: {
row: 0,
column: 0,
lines: [''],
mode: 'INPUT',
auto: false, // 是否有自动换行
}, // 当前位置信息
poi: null, // 点击`图片`tab的action-sheet
mediaActionSheetHidden: true, // 多媒体文件插入action-sheet
mediaActionSheetItems: mediaActionSheetItems, // 多媒体文件插入项点击事件
mediaActionSheetBinds: mediaActionSheetBinds, // 是否显示底部tab栏
showTab: true,
}, // 显示底部tab
showTab() {
this.setData({showTab: true});
}, // 隐藏底部tab
hideTab() {
this.setData({showTab: false});
}, // 显示loading提示
showLoading(loadingMessage) {
this.setData({showLoading: true, loadingMessage});
}, // 隐藏loading提示
hideLoading() {
this.setData({showLoading: false, loadingMessage: ''});
}, // 数据初始化
init() {
this.getPoi();
this.setMeta();
}, // 设置日记数据
setDiary(diary) {
let layout = util.listToMatrix(diary.list, layoutColumnSize);
this.setData({diary: diary, layoutList: layout});
this.saveDiary(diary);
}, // 保存日记
// TODO sync to server
saveDiary(diary) {
const key = config.storage.diaryListKey; app.getLocalDiaries(diaries => {
diaries[diary.meta.title] = diary;
wx.setStorage({key: key, data: diaries});
})
}, // 页面初始化
onLoad: function(options) {
if (options) {
let title = options.title;
if (title) {this.setData({
'diary.meta.title': title,
'diary.meta.create_time': util.formatTime(new Date()),
'diary.meta.cover': ''
});}
} this.init();
}, // 页面渲染完成
onReady: function(){
wx.setNavigationBarTitle({title: '编辑日记'});
}, onShow:function(){
// 页面显示
}, onHide:function(){
// 页面隐藏
}, onUnload:function(){
// 页面关闭
console.log('页面跳转中...');
}, // 清除正在输入文本
clearInput() {
this.setData({inputStatus: {
row: 0,
common: 0,
lines: [''],
mode: 'INPUT',
auto: false,
}});
}, // 结束文本输入
inputDone() {
let text = this.data.inputStatus.lines.join('\n');
let diary = this.data.diary; if (text) {
diary.list.push(this.makeContent(TEXT, text, ''));
this.setDiary(diary);
} this.inputCancel();
}, // 进入文本编辑模式
inputTouch(event) {
this.setData({showMode: 'inputText'});
}, // 取消文本编辑
inputCancel() {
this.setData({showMode: 'common'});
this.clearInput();
}, // 文本输入
textInput(event) {
console.log(event);
let context = event.detail; // 输入模式
if (this.data.inputStatus.mode === 'INPUT') {
if (context.value.length != context.cursor) {
console.log('用户输入中...');
} else {
let text = context.value;
let len = input.strlen(text);
let lines = this.data.inputStatus.lines;
let row = this.data.inputStatus.row;
let [extra, extra_index] = [[['']], 0];
let hasNewLine = false;
console.log('当前文本长度: ' + len); // 当前输入长度超过规定长度
if (len >= ROW_CHARS) {
// TODO 此处方案不完善
// 一次输入最好不超过两行
hasNewLine = true;
while (input.strlen(text) > ROW_CHARS) {
let last = text[text.length - 1]; if (input.strlen(extra[extra_index] + last) > ROW_CHARS) {
extra_index += 1;
extra[extra_index] = [''];
} extra[extra_index].unshift(last);
text = text.slice(0, -1);
}
} lines[lines.length - 1] = text;
if (hasNewLine) {
extra.reverse().forEach((element, index, array) => {
lines.push(element.join(''));
row += 1;
});
} let inputStatus = {
lines: lines,
row: row,
mode: 'INPUT',
auto: true, // // 自动换行的则处于输入模式
};
列表
wxml <scroll-view scroll-y="true">
<view wx:for="{{diaries}}" wx:for-index="idx" class="item-container" bindtap="showDetail" id="{{idx}}">
<image mode="aspectFit" src="{{item.meta.cover}}" class="cover"></image>
<view class="desc">
<view class="left">
<view style="font-size:32rpx;margin:10rpx 0;">{{item.meta.title}}</view>
<view style="font-size:24rpx;color:darkgray">{{item.meta.meta}}</view>
</view>
<view class="right">
<image mode="aspectFit" src="{{item.meta.avatar}}"></image>
<text style="font-size:24rpx;margin-top:10rpx;color:darkgray">{{item.meta.nickName}}</text>
</view>
</view>
</view>
</scroll-view>

JS

const config = require("../../config");

var app = getApp();

Page({

  data: {
// 日记列表
// TODO 从server端拉取
diaries: null, // 是否显示loading
showLoading: false, // loading提示语
loadingMessage: '',
}, /**
* 生命周期函数--监听页面加载
*/
onLoad() {
this.getDiaries();
}, /**
* 获取日记列表
*/
getDiaries() {
var that = this;
app.getDiaryList(list => {
that.setData({diaries: list});
})
}, // 查看详情
showDetail(event) {
wx.navigateTo({
url: '../entry/entry?id=' + event.currentTarget.id,
});
}
})
总结

这是第一次编写小程序,刚刚听到作业的时候很震惊一周要做一个小程序。


从头开始学习html,css知识的同时,去参考完整的demo。


一句一句的理解,调试。


几天下来对小程序的结构有了了解。


在做小程序的时候,也遇到了一些困难,在搜素引擎和同学们的帮助下也都解决了。


虽然最后做的很粗糙,但是在这个过程中,基本上完成了小程序的入门,也知道了怎么去解决遇到的问题。


这次的作业也让我明白,在开发方面还有很多需要学习的知识。


需要更加努力

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/586496.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存