Linuxword Global
当前位置: 建站相关 > GCP連動Firebase建立網頁聊天室以及定价

基于firebase + cloud Function 实现web聊天(demo版)

 

知识点:

  • 使用Firebase SDK创建Google Cloud功能。
  • 触发云功能基于Auth,云存储和Cloud Firestore事件。
  • 为您的网络应用添加Firebase Cloud Messaging支持

 

一:准备工作:

  1: 在Firebase控制台中,单击“ 添加项目”并将其命名为FriendlyChat。

      2: 启用Google Auth 和 云存储

692485-20190814171122422-1223136703

 

二:获取代码:

    从命令行克隆GitHub存储库:  

git clone https://github.com/firebase/friendlychat

   firebase-codelabs存储库包含多个平台的示例项目。此代码库仅使用这两个存储库:

     (我们用 cloud-functions  完整的实例)

三:安装Firebase命令行界面:

     (本地shell终端 进入 cloud-functions目录中)

     1、本地shell终端中安装  :

 

npm -g install firebase-tools

 

 2、登录(用创建项目的google账户登录)
 
 firebase login
 
 3、选择项目,选择刚刚新建的项目
 
firebase use --add
四:发布代码:
firebase deploy --except functions
 
  

部署成功,在项目中就能看到部署的服务:

692485-20190814172526856-1096513354

 

五:访问:

    部署的打印信息中  Hosting URL  或者项目后台都可以找到访问链接。

     1、浏览器打开如图:

692485-20190814172917756-654208194

 

 2、登录:

 

 3、开始聊天:

  

 

4、项目中消息记录:

 

692485-20190814173543984-2143479272

p1
What You'll Be Creating

使用Firebase創建實時社交應用程序很簡單。  而且您不必編寫壹行服務器端代碼。

在本教程中,我將展示如何利用Firebase UI創建聊天應用程序,您可以與您的朋友分享。  這是壹個非常簡單的應用程序,只有壹個聊天室,對所有用戶開放。

機智如妳,該應用程序依賴於Firebase Auth來管理用戶註冊並登錄。  還使用Firebase的實時數據庫來存儲聊天消息。

準備工作

為了與本教程保持壹致,需要註意以下幾點:

  • 最新版本的Android Studio
  • 壹個Firebase帳號

如何設置Firebase帳戶並為Android Studio中的Firebase開發做好準備,請參閱Envato Tuts +上我的教程 “入門Firebase for Android”。

  • firebase
    ANDROID SDK
    開始使用Firebase for Android
    Ashraff Hathibelagal

1.創建壹個Android Studio項目

啟動Android Studio並創建壹個名為MainActivity的空activity的新項目。

p2

要將項目配置為使用Firebase平臺,請單擊“ 工具”>“Firebase”,打開“Firebase Assistant”窗口。

在使用Firebase平臺的同時,最好將Firebase Analytics添加到項目中。  因此,在Firebase Assistant窗口中,進入Google Analytics(分析)部分,然後點擊Log an Google Analytics(分析)事件。

p3

接下來,點擊“ 連接到Firebase”按鈕,確保選擇了“ 創建新的Firebase項目”選項。  建立連接後,點擊“ 添加Google Analytics(分析)”按鈕。

p4

此時,Android Studio項目不僅集成Firebase Analytics,還可以使用所有其他Firebase服務。

2.添加依賴關系

我們將在此項目中使用兩個庫:Firebase UI和Android設計支持庫。  因此,打開app模塊的build.gradle文件並添加以下compile依賴項:

1
2
compile 'com.android.support:design:23.4.0'
compile 'com.firebaseui:firebase-ui:0.6.0'

點擊“ 立即同步”按鈕更新項目。

3.定義布局

已經綁定到MainActivity的activity_main.xml文件定義了應用程序主界面的內容。  換句話說,它就是聊天室的界面。

像今天可用的其他大多數聊天應用程序壹樣,我們的應用程序具有以下UI元素:

  • 按時間順序顯示所有群組聊天消息列表
  • 用戶可以輸入新消息的輸入框
  • 可以發布消息的按鈕

因此,activity_main.xml必須有ListView、EditText和FloatingActionButton。  將它們全部放入RelativeLayout布局後,您的布局XML應如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.tutsplus.mychatapp.MainActivity">
 
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:src="@drawable/ic_send_black_24dp"
android:id="@+id/fab"
android:tint="@android:color/white"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
app:fabSize="mini" />
 
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/fab"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true">
 
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input"
android:id="@+id/input"
/>
</android.support.design.widget.TextInputLayout>
 
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_above="@id/fab"
android:dividerHeight="16dp"
android:divider="@android:color/transparent"
android:id="@+id/list_of_messages"
android:layout_marginBottom="16dp"/>
</RelativeLayout>

請註意,我把EditText控件放在TextInputLayout控件中。  這樣做會給EditText添加壹個浮動標簽,這樣可以體現MD風格。

現在主界面的布局已經準備好了,我們可以繼續創建聊天消息的布局,ListView裏面的子item單元。  首先創建壹個名為message.xml的新布局XML文件,該文件的根元素是RelativeLayout。

該布局必須有TextView框架來顯示聊天消息的文本,發送的時間及作者。  妳可以隨意放置他們的順序。  布局如下:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
 
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="@+id/message_user"
android:textStyle="normal|bold" />
 
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/message_user"
android:layout_alignParentEnd="true"
android:id="@+id/message_time" />
 
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/message_user"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:id="@+id/message_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="18sp" />
</RelativeLayout>

4.處理用戶認證

最好不要允許用戶匿名發布消息到聊天室。  這可能會導致垃圾郵件,安全問題以及不太理想的聊天體驗。  因此,讓我們現在配置我們的應用程序,只有註冊用戶才可以讀取和發送消息。

先從Firebase Console的Auth部分開始,並啟用Email / Password作為登錄提供者。

p5

免費啟用OAuth 2.0登錄提供商。  然而,FirebaseUI v0.6.0無縫地支持Google登錄和Facebook登錄。

步驟1:處理用戶登錄

壹旦應用程序啟動,它必須檢查用戶是否登錄。  登錄後,該應用程序應該繼續顯示聊天室的內容。  否則,它必須將用戶重定向到登錄界面或註冊界面。  使用FirebaseUI創建這些界面比您想像的代碼少得多。

在MainActivity的onCreate()方法中,通過檢查當前FirebaseUser對象是否為null來檢查用戶是否已經登錄。  如果FirebaseUser對象是null,您必須創建並配置Intent對象來打開登錄activity。  為此,請使用SignInIntentBuilder類。  壹旦Intent準備就緒,您必須使用startActivityForResult()方法啟動登錄activity。

請註意,登錄activity還允許新用戶註冊。  因此,您沒有寫任何額外的代碼來處理用戶註冊。

將以下代碼添加到onCreate()方法中:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
if(FirebaseAuth.getInstance().getCurrentUser() == null) {
// Start sign in/sign up activity
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.build(),
SIGN_IN_REQUEST_CODE
);
} else {
// User is already signed in. Therefore, display
// a welcome Toast
Toast.makeText(this,
"Welcome " + FirebaseAuth.getInstance()
.getCurrentUser()
.getDisplayName(),
Toast.LENGTH_LONG)
.show();
 
// Load chat room contents
displayChatMessages();
}

如上面的代碼所示,如果用戶已經登錄,我們首先顯示壹個Toast歡迎用戶,然後調用名為displayChatMessages的方法。  現在,只需創建壹個存根。  稍後我們會添加代碼。

1
2
3
private void displayChatMessages() {
 
}

壹旦用戶登錄,MainActivity將收到壹個Intent形式的結果。  必須重寫onActivityResult()方法才來處理它。

如果結果的代碼是RESULT_OK,則表示用戶已成功登錄。  如果是這樣,妳必須()再次調用displayChatMessages方法。  否則,請調用finish()方法關閉應用程序。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
 
if(requestCode == SIGN_IN_REQUEST_CODE) {
if(resultCode == RESULT_OK) {
Toast.makeText(this,
"Successfully signed in. Welcome!",
Toast.LENGTH_LONG)
.show();
displayChatMessages();
} else {
Toast.makeText(this,
"We couldn't sign you in. Please try again later.",
Toast.LENGTH_LONG)
.show();
 
// Close the app
finish();
}
}
 
}

現在,您可以運行應用程序,並查看登錄和註冊屏幕。

p7

步驟2:處理用戶註銷

默認情況下,FirebaseUI使用Smart Lock進行密碼管理。  因此,壹旦用戶登錄,即使應用重新啟動,他們也將保持登錄狀態。  為了允許用戶註銷,我們現在將在MainActivity的菜單中添加壹個退出選項。

創建壹個名為main_menu.xml的新菜單資源文件,並向其添加壹個item,其title屬性設置為註銷。  該文件的內容應如下:

1
2
3
4
5
6
7
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
 
<item android:title="Sign out" app:showAsAction="never"
android:id="@+id/menu_sign_out"/>
 
</menu>

要實例化MainActivity裏面的菜單資源,重寫onCreateOptionsMenu()方法並調用MenuInflater對象的inflate()方法。

1
2
3
4
5
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}

接下來,重寫onOptionsItemSelected()方法來處理菜單項上的點擊事件。  在該方法中,您可以調用 AuthUI類的signOut()方法來簽名用戶。  因為註銷操作是異步執行的,所以我們還會添加壹個OnCompleteListener。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.menu_sign_out) {
AuthUI.getInstance().signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(MainActivity.this,
"You have been signed out.",
Toast.LENGTH_LONG)
.show();
 
// Close activity
finish();
}
});
}
return true;
}

用戶註銷後,應用程式應自動關閉。  這就是為什麽在上面的代碼中調用finish()方法的原因。

5.創建壹個模型

為了將聊天消息存儲到Firebase實時數據庫中,您必須為它們創建壹個模型。  本教程前面創建的聊天消息的布局有三個視圖。  為了能夠填充這些視圖,模型也必須至少有三個字段。

創建壹個新的Java類ChatMessage.java並添加三個成員變量messageText、messageUser和messageTime。  還要添加壹個構造方法來初始化這些變量。

要使模型與FirebaseUI兼容,您還必須向其添加默認構造方法以及所有成員變量的getter和setter方法。

現在,ChatMessage類應該如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class ChatMessage {
 
private String messageText;
private String messageUser;
private long messageTime;
 
public ChatMessage(String messageText, String messageUser) {
this.messageText = messageText;
this.messageUser = messageUser;
 
// Initialize to current time
messageTime = new Date().getTime();
}
 
public ChatMessage(){
 
}
 
public String getMessageText() {
return messageText;
}
 
public void setMessageText(String messageText) {
this.messageText = messageText;
}
 
public String getMessageUser() {
return messageUser;
}
 
public void setMessageUser(String messageUser) {
this.messageUser = messageUser;
}
 
public long getMessageTime() {
return messageTime;
}
 
public void setMessageTime(long messageTime) {
this.messageTime = messageTime;
}
}

6.發布聊天消息

現在,該模型已經準備就緒,我們可以輕松地向Firebase實時數據庫添加新的聊天消息。

要發送新消息,用戶要點擊FloatingActionButton。因此,您必須給它添加OnClickListener點擊事件。

在監聽器中,您必須首先使用FirebaseDatabase類的getReference()方法獲取DatabaseReference對象。  然後,您可以調用push()和setValue()方法將ChatMessage類的新實例添加到實時數據庫。

這些ChatMessage實例當然必須使用EditText的內容進行初始化並且顯示當前登錄的用戶名稱。

因此,將以下代碼添加到onCreate()方法中:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
FloatingActionButton fab =
(FloatingActionButton)findViewById(R.id.fab);
 
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText input = (EditText)findViewById(R.id.input);
 
// Read the input field and push a new instance
// of ChatMessage to the Firebase database
FirebaseDatabase.getInstance()
.getReference()
.push()
.setValue(new ChatMessage(input.getText().toString(),
FirebaseAuth.getInstance()
.getCurrentUser()
.getDisplayName())
);
 
// Clear the input
input.setText("");
}
});

Firebase實時數據庫中的數據始終作為鍵值對存儲。  但是,如果您遵守上述代碼,您將看到我們調用了setValue()而沒有指定任何鍵。  這僅僅是因為先調用了push()方法,該方法自動生成壹個新的鍵。

7.顯示聊天消息

FirebaseUI有壹個非常方便的類FirebaseListAdapter,它大大降低了使用Firebase實時數據庫中存在的數據填充ListView所需的工作量。  我們現在將使用它來獲取和顯示數據庫中存在的所有ChatMessage對象。

將FirebaseListAdapter對象添加為MainActivity類的新成員變量。

1
private FirebaseListAdapter<ChatMessage> adapter;

在displayChatMessages()方法中,使用其構造方法初始化適配器,該構造方法需要以下參數:

  • Activity引用
  • 妳感興趣的class對象
  • 列表子item的布局
  • 壹個DatabaseReference對象

FirebaseListAdapter是抽象類,有populateView()抽象方法,必須被實現該方法。

顧名思義,populateView()用於填充每個列表項的子item。  如果您熟悉ArrayAdapter類,您可以將populateView()方法看作getView()方法的替代。

在該方法中,您必須首先使用findViewById()來獲取message.xml布局文件中TextView的每壹個的引用。  然後,您可以使用ChatMessage類的getter 來調用它們的setText()方法並填充它們。

此時,displayChatMessages()方法的內容應該如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
ListView listOfMessages = (ListView)findViewById(R.id.list_of_messages);
 
adapter = new FirebaseListAdapter<ChatMessage>(this, ChatMessage.class,
R.layout.message, FirebaseDatabase.getInstance().getReference()) {
@Override
protected void populateView(View v, ChatMessage model, int position) {
// Get references to the views of message.xml
TextView messageText = (TextView)v.findViewById(R.id.message_text);
TextView messageUser = (TextView)v.findViewById(R.id.message_user);
TextView messageTime = (TextView)v.findViewById(R.id.message_time);
 
// Set their text
messageText.setText(model.getMessageText());
messageUser.setText(model.getMessageUser());
 
// Format the date before showing it
messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
model.getMessageTime()));
}
};
 
listOfMessages.setAdapter(adapter);

群聊應用已準備就緒。  運行它並發送壹條新消息,看到它們立即顯示在ListView中。  如果您與朋友分享該應用程序,您也可以立即看到他們的發送過來的消息。

結論

在本教程中,您學習了如何使用Firebase和FirebaseUI創建壹個非常簡單的群聊應用程序。  您還看到使用FirebaseUI中的類可以輕松實現快速創建新界面並實現復雜功能。

 

98f6d7bc76c3569395d43752baa773ae

Firebase 是一个用于构建 web 和移动应用程序的平台。它最初由 Firebase 公司开发,并于2018年被谷歌收购。

Firebase 有两个主要的定价套餐:

  • Spark套餐(免费) 是一个基本的套餐,提供1gb 的总存储,20K 写/天,50K 读/天,20K 删除/天
  • Blaze 套餐(收费) 即付即用,数据库存储收费0.18美元/GB,应用程序存储、数据库操作、数据传输等附加费用收费0.026美元/GB

在这篇文章中,你会学到:

  • 谷歌Firebase的成本是多少?
  • Firebase永久免费服务
  • Firebase付费服务定价
  • Cloud Firestore存储数据库
  • 实时数据库
  • 托管
  • 认证
  • 云功能
  • Firebase 机器学习
  • 测试实验室
  • Firebase: 估算你的成本

Firebase 永久免费服务

Firebase 提供多种免费和付费的服务:

  • 应用程序交付——将应用程序分发给可信的测试人员
  • 应用程序索引——使谷歌和其他搜索引擎对应用程序进行索引
  • A/b 测试_为特定用户部署不同版本的应用程序
  • 分析——报告及预测应用程式的性能
  • 应用内消息——与正在积极使用应用程序的用户交互
  • 云消息——firebase Cloud Messaging (FCM) ,也被称为 Google云消息传递服务,可以在 iOS、 Android 和 web 应用程序中使用,自动发送消息和通知
  • 性能监控——监控 Firebase 应用程序的性能
  • 崩溃记录——帮助您检测应用程序中发生的崩溃并确定其原因
  • 动态链接——可用于将用户从一个平台重定向到另一个平台
  • 远程配置——远程定制应用程序的一些基本功能,例如更改颜色和隐藏或显示文本
  • 预测——firebase 机器学习工具可以帮助您更好地分析某个特定用户是否已经返回到您的应用程序

Firebase付费服务定价

让我们回顾一下剩下的 Firebase 服务,这些服务在 Blaze 定价套餐中支付费用,并且在 Spark 套餐的某个限制内可以免费提供。

Cloud Firestore存储数据库

Cloud Firestore 是 Firebase 新推荐的数据库。它总共提供1gib 的存储空间。在 Blaze 套餐中,存储空间是收费的,数据库操作是单独定价的。

Cloud Firestore Spark Blaze
存储GB数(数据库) 总共1gb 每GB 0.18美元
每天2万次 $0.18/10万次操作
每天5万次 $0.06/10万次操作
删除 每天2万次 $0.02/10万次操作

实时数据库

Firebase 实时数据库提供免费和无限制的读写操作。

实时数据库 Spark Blaze
同时连接 100 20万/数据库
存储GB数 1 GB 5美元/GB
下载 每月10gb 1美元/GB
每个项目的数据库 1 多个
储存 Spark Blaze
存储GB数 5 GB 每 GB 0.026美元
下载 每天1gb 每 GB 0.12美元
上传操作 每天2万次 $0.05/1万次
下载操作 每天5万次 $0.004/1万次
每个项目的存储 1 多个

要了解 Google Cloud 提供的全部服务,可以了解 Google Cloud Database 的其他服务。

托管 

谷歌在 Spark 套餐中免费托管你的 Firebase 应用程序,在 Blaze 套餐中,对每 GB 的应用程序数据存储和数据传输收取适当的费用。两个套餐都为每个项目提供免费的 SSL 和多个站点。

托管 Spark Blaze
存储GB数(应用程序数据) 10 GB $0.026/GB
传输GB数 每月10gb $0.15/GB

认证

Firebase 每月提供10,000次身份验证,除此之外,根据您所在的区域收取不同的费率。

托管 Spark Blaze
前10,000次认证 免费 免费
在美国,加拿大,印度,每月认证超过10000次 不适用 每次认证收费0.01元
在世界其他地方,每月认证超过10000次 不适用 每次认证收费0.01元

云功能

作为服务产品的 Google 云功能是 Firebase 套餐的一部分。

云功能 Spark Blaze
调用 每月12.5万次 每月免费200万次,之后每百万次0.4美元
Gb-秒 每月4万次 每月最多40万次*
Cpu-秒 每月4万次 每月最多20万次*
出站网络 只允许使用谷歌服务 每月免费5GB,之后每GB 0.12美元
云构建时长 不适用 每天免费120分钟,然后每分钟0.003美元
存储空间 不适用 $0.026/GB

* 超过这个免费额度后按照gb-秒和cpu-秒收费,请参考 Google 云服务定价页面。或者了解更多关于 Google Cloud 所有服务成本的信息。

Firebase ML

谷歌机器学习工具包可以在 Firebase 中为每个项目提供多达1000张图像,并且可以用于各种图像处理任务。

测试实验室

谷歌测试实验室每天对真实设备提供5次测试,对虚拟设备提供10次测试。

Firebase: 估算你的成本

在控制台中提供了用法选项卡,显示你的支付状态和各种 Firebase 服务的使用情况:

  • 存储页——显示存储在数据库中的数据量,不包括存储在其他 Firebase 产品中的数据.
  • 连接页——像 websocket 这样的实时连接的数量.
  • 加载页——以图形方式显示应用程序负载,并显示某段时间内使用的数据.
  • 下载页——显示从数据库下载的数据量.

总结

Firebase 有两个定价级别。第一个包含一个有限制的免费套餐,它是开发和小型应用程序的绝佳选择。第二层按照即用即付模式,它极为适用于产品级应用。

Firebase 是免费的吗?

Firebase 有两个定价级别。第一个包含一个有限制的免费套餐,它是开发和小型应用程序的绝佳选择。第二层按照即用即付模式,它极为适用于产品级应用。

有哪些Firebase 套餐?

– Spark套餐(免费)
– Blaze套餐(即付即用)

免费的 Firebase 服务有哪些?

– 应用程序交付
-应用程序索引
-A/B测试
-分析
-应用程序内消息
-云消息
-性能监控
-崩溃记录
-动态链接
-远程配置
-预测

「梦想一旦被付诸行动,就会变得神圣,如果觉得我的文章对您有用,请帮助本站成长」

赞(0) 打赏
一分也是爱

支付宝扫一扫打赏

微信扫一扫打赏

上一篇:

下一篇:

相关推荐

博客简介

本站CDN采用VmShell免费提供离中国大陆最近的香港CMI高速网络做支撑,ToToTel打造全球最快速的边沿网络支撑服务,具体详情请见 :https://vmshell.com/ 以及 https://tototel.com/,网站所有的文件和内容禁止大陆网站搬迁复制,谢谢,VPS营销投稿邮箱: admin@linuxxword.com,我们免费帮大家发布,不收取任何费用,请提供完整测试文稿!

精彩评论

友情链接

他们同样是一群网虫,却不是每天泡在网上游走在淘宝和网游之间、刷着本来就快要透支的信用卡。他们或许没有踏出国门一步,但同学却不局限在一国一校,而是遍及全球!申请交换友链

站点统计

  • 文章总数: 2591 篇
  • 草稿数目: 22 篇
  • 分类数目: 6 个
  • 独立页面: 0 个
  • 评论总数: 2 条
  • 链接总数: 0 个
  • 标签总数: 13021 个
  • 注册用户: 139 人
  • 访问总量: 8,651,104 次
  • 最近更新: 2024年11月21日