游记分享

博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020
作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11334
作业目标 1. 编写一个小程序,可以全新编写,也可以学习别人的小程序进行修改 2. 熟悉git代码管理流程,将源代码上传到到github 3. 在博客园班级中写一篇相应的博文
作业源代码 git@github.com: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。一句一句的理解,调试。几天下来对小程序的结构有了了解。在做小程序的时候,也遇到了一些困难,在搜素引擎和同学们的帮助下也都解决了。虽然最后做的很粗糙,但是在这个过程中,基本上完成了小程序的入门,也知道了怎么去解决遇到的问题。这次的作业也让我明白,在开发方面还有很多需要学习的知识。需要更加努力

微信小程序-游记分享(无后台)的更多相关文章

  1. mpvue开发微信小程序,分享按钮报错:`Cannot read property 'apply' of null`

    用mpvue开发微信小程序,分享按钮报错:Cannot read property 'apply' of null onShareAppMessage 是于微信小程序Pages的生命周期钩子,顾这个方 ...

  2. 微信小程序绘制分享图

    微信小程序绘制分享图例子: demo下载地址:https://gitee.com/v-Xie/wxCanvasShar 大致代码会再以下说明 实际开发项目: 基础知识点: 了解canvas基础知识 w ...

  3. (一)校园信息通微信小程序从前端到后台整和笔记

    前段时间接触了微信小程序,现在回过头来做一些笔记. 先上效果图 后台数据管理界面(PHP) 校园信息通微信小程序前端界面 下面先简单的说一下怎样部署一个微信小程序 首先是前端 微信小程序有它专门的开发 ...

  4. 微信小程序-实现分享(带参数)

    微信小程序分享功能的实现方法有两种: 第一种 在page.js中实现onShareAppMessage,便可在小程序右上角选择分享该页面 onShareAppMessage: function () ...

  5. (一)微信小程序之模拟调用后台接口踩过的坑

    如下图标记的三个点 在调试过程中出现问题,特此记录. 1. 之前在浏览器测试接口习惯省略 http:// ,是因为浏览器默认有一个检测,在你输入的网址前面加http://,如果有就不加. 然而在微信小 ...

  6. 微信小程序,请求php后台返回json数据多出隐藏字符问题

    这几天在做一个微信小程序注册登录页面的时候碰到一个问题,就是使用wx.request api的时候success中返回的JSON数据前面会多出空白字符,后面网上查了一下是说php bom头问题(详细介 ...

  7. 微信小程序商城 带java后台源码

    微信小程序商城(Java版) 演示地址 账号:admin 密码:admin 小程序体验码: 技术选型 1 后端使用技术 1.1 springframework4.3.7.RELEASE 1.2 myb ...

  8. 微信小程序全局设置分享内容

    微信小程序每个页面都可以在onShareAppMessage中设置分享内容,如果想要全局设置成一样的分享内容如何设置呢? 在app.js中新增以下方法: //重写分享方法 overShare: fun ...

  9. 微信小程序之分享功能

    说到分享 大家都会想到手机右上角点击不就分享了么?对的没错,那样是分享转发的是小程序  而不是指定的某个页面,所以自己动手丰衣足食,自己写一个转发功能被, 其实也没那么可怕,主要参考的是微信小程序AP ...

随机推荐

  1. 手把手教你ASP.NET Core:使用Entity Framework Core进行增删改查

    新建表Todo,如图 添加模型类 在"解决方案资源管理器"中,右键单击项目. 选择"添加" > "新建文件夹". 将文件夹命名为 Mo ...

  2. Solon详解(十)- 怎么用 Solon 开发基于 undertow jsp tld 的项目?

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  3. html 背景花瓣特效--1

    html背景樱花可以用js添加,将<script>标签复制到<body>标签下就可以,javascript脚本点击 <!DOCTYPE html> <html ...

  4. 读书笔记——Effective C++

    1.让自己习惯C++ 条款01:视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 条款02:尽量以const.enum.inline替换 #define 对于单纯 ...

  5. 在程序开发中,++i 与 i++的区别在哪里?

    哈哈哈! 从大学开始又忘了...蜜汁问题哈 参考来源:https://www.zhihu.com/question/19811087/answer/80210083 i++ 与 ++i 的主要区别有两 ...

  6. Arduino读取写入电压值

    读取写入方式分为数字和模拟 读取方式:(注意接地) 数字:digitalRead(pin); 模拟:analogRead(A1);float val=value*(5.0/1023.0);       ...

  7. 初学者的Android移植:在Debian上建立一个稳定的构建环境

    介绍 通过在chrooted环境中设置开发环境,避免依赖冲突和沙箱您的Android开发从您的Debian GNU/Linux系统.这是为通配符类别准备的,因为从源代码构建Android似乎没有在其他 ...

  8. Varnish 6.2.2 的介绍与安装

    一.简介 Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 Squid 相比,Varnish 具有性能更高.速度更快 ...

  9. Dockerfile常用指令及使用

    Dockerfile常用指令及使用 1. dockerfile介绍 2. Dockerfile常用指令 指令 描述 FROM 构建新镜像是基于哪个镜像 MAINTAINER 进行维护者姓名或邮箱地址 ...

  10. 2016年 实验五 Internet与网络工具的使用

    实验五 Internet与网络工具的使用 [实验目的] 本实验目的在于掌握 Telnet.FTP.Email的工作机理,并会在 Internet 上熟练使用相关工具软件. [实验条件] ⑴.个人计算机 ...