codeigniter使用_使用jQuery的CodeIgniter和Ajax

codeigniter使用

CodeIgniter是一个流行的,轻量级的,开源的框架,用PHP编写,并基于模型-视图-控制器(MVC)架构模式。 jQuery是一个快速,轻量级的开源JavaScript库,旨在简化对HTML页面和Ajax交互的操作。 当一起使用时,它们为快速开发可用的网站和应用程序奠定了强大的基础。

本文介绍了如何将这两个系统集成到单个框架中,以及如何使用jQuery改进现有Web应用程序的UI。 假定您同时安装了CodeIgniter版本1.7.2或更高版本以及MySQL版本4.1或更高版本,并且您对这两者都有很好的使用知识。 另外,您需要jQuery库1.4.2或更高版本。

Web 2.0:使用jQuery的Ajax

Web 2.0最重要的方面之一是用户的体验更像是桌面应用程序,而不是网站。 具体地说,与网页的交互不需要与Web服务器进行“可视通信”,例如,单击“提交”,等待Web服务器处理提交的信息,然后整个Web页面会更新内容。 取而代之的是,仅更新需要更改的内容,而页面的其余部分保持不变。

这种“无提交”过程通过使用Ajax来工作,它使Web开发人员可以在Web客户端(浏览器)和Web服务器之间传输信息,而无需刷新页面。 更好的是,无需任何直接用户干预即可触发此信息传输。

当网页使用Ajax时,它是向Web服务器异步发送数据和从Web服务器接收数据。 传输的数据是纯文本,因此可以采用多种不同的格式,例如XML,HTML,JSON或纯文本。

数据的实际传输是使用JavaScript和称为XMLHttpRequest的API执行的,这是jQuery输入图片的地方。 jQuery库大大简化了使用Ajax的过程。 而且不仅使用Ajax更容易,而且显示更新的数据也更容易。 (如果您曾经尝试过使用JavaScript遍历HTML DOM,那么您将非常感激它多么简单!)

现有的CodeIgniter应用程序

为了演示将jQuery与CodeIgniter结合使用的强大功能和简便性,本文将指导您改进现有Web应用程序的UI。 该应用程序旨在帮助教师管理课堂活动和每个家长的参与。 教师首先从董事会批准的选项列表中选择班级活动,并为每个活动安排一个日期。 然后,父母在该网站上注册并输入其子女的联系信息。 然后,他们可以查看班级活动列表并选择参与程度(购买物品,帮助准备,协助或充当活动负责人)。

注意:此系统可以轻松应用于支持儿童运动队,基督教青年会团体等。

对于本文,该应用程序的数据库已加载约100个事件,5个父母和1个老师。 父级的用户名是parent1,parent2 、。 。 。 父母5。 教师的用户名为教师,所有密码均为ibm。 您将要下载 Web应用程序和数据库,并在Web服务器上进行设置以进行后续操作。 该应用程序要求CodeIgniter框架位于服务器的根目录。

设置jQuery

要开始使用jQuery,请先下载该库。 每个版本都提供两个文件:一个未压缩的文件和一个“最小化”文件(此高度压缩的版本加载速度更快,但如果您愿意,则无​​法跟踪)。 我建议使用未压缩版本进行开发,而使用压缩版本进行生产。

接下来,将jQuery库文件放在Web服务器根目录的.assets / js文件夹中。 然后,在名为global.js的同一文件夹中创建一个新文件,如清单1所示。在这里,您将放置整个应用程序JavaScript代码。

清单1.使用jQuery的“ Hello World”
/* Global JavaScript File for working with jQuery library */

// execute when the HTML file's (document object model: DOM) has loaded
$(document).ready(function() {

  alert ('Hello World');
	
});

对于本文(以及大多数应用程序),许多jQuery代码将驻留在$(document).ready()函数中。 仅在HTML文件的DOM完成加载后,才自动触发此功能。

为了使应用程序加载这两个文件,请编辑./system/application/views/template.php文件,如清单2所示。

清单2.加载jQuery和全局JavaScript文件
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

<link href="/assets/css/screen.css" rel="stylesheet" type="text/css" />

<!--  the following two lines load the jQuery library and JavaScript files -->
<script src="/assets/js/jquery-1.4.2.js" type="text/javascript"></script>
<script src="/assets/js/global.js" type="text/javascript"></script>

<title><?php echo $title;?></title>
</head>

现在,导航到网站的索引页面。 页面加载后,JavaScript警报将显示“ Hello World”。

将jQuery和Ajax与CodeIgniter结合使用

有了jQuery库和global.js文件,您就可以开始改善应用程序的界面了。 如果尚未注册,请花几分钟时间以家长和老师的身份登录,以熟悉系统中活动的工作方式。

自动用户名验证

改进UI的第一个地方是“注册”页面。 当前,在用户提交页面之后,对是否已使用用户名进行验证。 但是,使用Ajax,您可以运行服务器端验证并返回结果,而无需提交任何页面。

为此,请将代码绑定到用户onblur()段的onblur()事件,该事件在用户的光标离开该字段时触发。 清单3显示了更新的global.js文件。

清单3.检查用户名是否已经注册
/* Global JavaScript File for working with jQuery library */

// execute when the HTML file's (document object model: DOM) has loaded
$(document).ready(function() {

  /* USERNAME VALIDATION */
  // use element id=username 
  // bind our function to the element's onblur event
  $('#username').blur(function() {

    // get the value from the username field                              
    var username = $('#username').val();
    
    // Ajax request sent to the CodeIgniter controller "ajax" method "username_taken"
    // post the username field's value
    $.post('/index.php/ajax/username_taken',
      { 'username':username },

      // when the Web server responds to the request
      function(result) {
        // clear any message that may have already been written
        $('#bad_username').replaceWith('');
        
        // if the result is TRUE write a message to the page
        if (result) {
          $('#username').after('<div id="bad_username" style="color:red;">' +
            '<p>(That Username is already taken. Please choose another.)</p></div>');
        }
      }
    );
  });  

});

此代码使用ID为username的DOM元素创建jQuery对象。 然后,它调用jQuery blur()方法,该方法将一个函数绑定到用户onblur()事件。 此函数使用Ajax将用户名字段中的值发布到名为ajax的CodeIgniter控制器及其方法username_taken 。 接下来,它清除所有现有的错误消息,并根据Ajax发布的结果显示或不显示错误消息。

接下来,在./system/application/controllers中,创建一个名为ajax.php的文件,该文件由jQuery Ajax .post()方法引用。 清单4显示了此控制器的源代码。 (请注意,命名控制器ajax并没有什么特别的。只要.post()方法中的URL指向正确的控制器,就可以调用任何东西。)

清单4.处理Ajax请求的CodeIgniter控制器
<?php

class Ajax extends Controller {

  public function Ajax() {
  
    parent::Controller(); 
  }

  public function username_taken()
  {
    $this->load->model('MUser', '', TRUE);
    $username = trim($_POST['username']);
    // if the username exists return a 1 indicating true
    if ($this->MUser->username_exists($username)) {
      echo '1';
    }
  }

}

/* End of file ajax.php */
/* Location: ./system/application/controllers/ajax.php */

请注意, username_taken()方法不会返回值。 相反,它回响了它的响应,这是重要的一点。 jQuery Ajax请求将数据发布到Web页面并使用结果页面数据。 它不是以编程方式触及方法本身。

现在,您的第一个Ajax功能已经完成。 导航到“注册”页面,并使用已经使用的任何用户名进行注册,以查看相应的错误消息。

有趣的是,编写的jQuery代码意外产生了结果。 Ajax函数绑定到ID为username的字段,其中包括Login页面上的username字段。 清单5显示了如何修改jQuery对象,使其仅绑定到registration_form表单内的username字段。

清单5.限定正确的用户名字段
/* USERNAME VALIDATION */
  // use element id=username within the element id=registration_form
  // bind our function to the element's onblur event
  $('#registration_form').find('#username').blur(function() {

无缝状态更新和存储

UI的下一个改进是在“课堂活动列表”页面上。 为了让父母表明他或她参加特定活动,父母单击适当的单选按钮,然后单击保存链接以提交页面。 为了改善用户界面,无需单击保存链接,因此根本不需要提交页面。

首先,将以下代码添加到global.js文件中。 它分为清单6,清单7和清单8,以更轻松地描述该过程。

清单6.使用jQuery获得相关的元素值
/* AUTOSAVE PARTICIPATION */
  // use input element name=participation_type_id and type=radio
  // bind our function to the element's onclick event
  $('input[name=participation_type_id]:radio').click(function() {
    
    var participation_type_id = this.value;

    // create global variables for use below
    var class_activity_id, user_id;
    
    // get the form's two hidden input elements 
    // each is a sibling of the parent of the clicked radio button
    // store their values in the global variables
    var hidden_elements = $(this).parent().siblings('input:hidden');
    $(hidden_elements).map(function() {
      if (this.name == 'class_activity_id') {
        class_activity_id = this.value;
      }
      if (this.name == 'user_id') {
        user_id = this.value;
      }
    });

此函数绑定到任何名为onclick()的单选按钮的onclick()事件。 它获取单击的单选按钮的值。 然后,它使用一组链接方法返回隐藏的表单元素。 map()方法通过其元素传递每个元素,以获取class_activity_iduser_id值。

确定了设置家长参与所需的值之后,代码将执行一个Ajax请求来保存此信息,如清单7所示。服务器对此请求的响应未回显任何数据,因此jQuery响应函数为空(并且可以实际上已被删除)。

清单7.将Ajax请求发布到CodeIgniter
// Ajax request to CodeIgniter controller "ajax" method "update_user_participation"
    // post the user_id, class_activity_id and participation_type_id fields' values
    $.post('/index.php/ajax/update_user_participation',
      { 'user_id':user_id, 
        'class_activity_id':class_activity_id, 
        'participation_type_id':participation_type_id },
      // when the Web server responds to the request
      function(result) { }
    );

最后,使用jQuery next()方法将单选按钮旁边的文本更改为适当的颜色,以每个字符串为目标。 清单8显示了此代码。

清单8.动态更改单选按钮文本的颜色
// set the text next to the clicked radio button to red
    $(this).next().css("color", "red");

    // set the text next to the remaining radio buttons to black
    var other_r_buttons = $(this).siblings('input[name=participation_type_id]:radio');
    $(other_r_buttons).map(function() {
      $(this).next().css("color", "black");
    });

  });

现在已经编写了jQuery代码,您需要在ajax控制器中创建update_user_participation()方法,如清单9所示。

清单9.处理用户在CodeIgniter中的参与
public function update_user_participation()
  {
    $this->load->model('MActivity', '', TRUE);
    $this->MActivity->set_user_participation($_POST);
  }

此方法使用MActivity模型中已经找到的set_user_participation()方法,该方法采用Ajax请求发布的变量。

最后,注释掉./system/application/controller/activity.php中的save链接,如清单10所示。

清单10.删除不必要的保存链接
'<span style="style="white-space: nowrap;">'.
          $participation_type_buttons.'&nbsp;&nbsp;'.
          /* the save link is no longer needed
            '<a href="" onclick="document.forms[\'form_'.$activity->id.'\'].submit();
return false;">save</a>'. */
          '</span>'.
          '</form>';

现在,您可以更改家长的参与,它将自动保存,而无需刷新页面。

自动建议输入字段

自动建议或自动完成功能是Ajax的最有效和广泛使用的方法之一。 以教师身份登录,然后点击管理课堂活动 。 要添加活动,用户必须向下滚动一长串可能的活动。 为了改进UI,请在./system/application/views/activity_master_listing.php文件的顶部添加一个绑定到autosuggest功能的输入字段,如清单11所示。这样做可使教师更轻松地从所有计划外活动。

清单11.添加一个自动建议的输入字段
<div id="select_anchor">
  <a href="" onclick="$('#select_anchor').hide(100); 
    $('#select_activity').show(100);
    return false;">
    Select an unscheduled Activity to add >></a>
  <br /><br />
</div>
<div id="select_activity" class="requested_activity" style="display:none;">
  <table>
    <caption>&nbsp;Select an unscheduled Activity</caption>
    <tr class="odd_row_add">
      <td>
        Begin by typing a few letters of an activity name<br />
        then select from the resulting list<br />
        <br />
        <input type="text" value="" id="class_activity" 
          onkeyup="autosuggest(this.value);" class="autosuggest_input" />
        <div class="autosuggest" id="autosuggest_list"></div>
      </td>
    </tr>
  </table>
</div>

注意绑定到JavaScript onclick()事件的两个jQuery对象和方法。 请记住,jQuery只是一个JavaScript库,并且可以在整个应用程序中与JavaScript无缝交互,而不仅仅是在$(document).ready()函数中。

接下来,在global.js文件中的$(document).ready()函数之外,实现以下JavaScript函数。 它绑定到class_activity输入字段的onkeyup()事件。 清单12中显示了源代码。

清单12.用jQuery实现autosuggest
/* AUTOSUGGEST SEARCH */
// triggered by input field onkeyup
function autosuggest(str){
  // if there's no text to search, hide the list div
  if (str.length == 0) {
    $('#autosuggest_list').fadeOut(500);
  } else {
    // first show the loading animation
    $('#class_activity').addClass('loading');
    
    // Ajax request to CodeIgniter controller "ajax" method "autosuggest"
    // post the str parameter value
    $.post('/index.php/ajax/autosuggest',
      { 'str':str },
      function(result) {
        // if there is a result, fill the list div, fade it in 
        // then remove the loading animation
        if(result) {
          $('#autosuggest_list').html(result);
          $('#autosuggest_list').fadeIn(500);
          $('#class_activity').removeClass('loading');
      }
    });
  }
}

请注意,尽管此函数不在$(document).ready()函数之内,但仍使用jQuery对象和方法。 它的jQuery .post()方法调用Ajax控制器的autosuggest()方法,该方法回显无序的autosuggest结果列表。 清单13显示了此代码。

清单13.检索和回显自动建议的结果
public function autosuggest()
  {
    // escapes single and double quotes
    $str = addslashes($_POST['str']);
    
    $this->load->model('MActivity', '', TRUE);
    $unscheduled_activities_qry = $this->MActivity->find_unscheduled_activities($str);
    
    // echo a list where each li has a set_activity function bound to its onclick() event
    echo '<ul>';
    foreach ($unscheduled_activities_qry->result() as $activity) {
      echo '<li onclick="set_activity(\''.addslashes($activity->name).'\'';
      echo ', '.$activity->id.');">'.$activity->name.'</li>'; 
    }
    echo '</ul>';
  }

接下来,添加find_unscheduled_activities()方法以从数据库返回autosuggest结果。 清单14包含来自./system/application/models/mactivity.php的代码。

清单14.查询数据库中未计划的活动
// Finds all unscheduled activities that match the passed string
  function find_unscheduled_activities($str)
  {
    $this->db->select('id, name
        FROM master_activity 
        WHERE name LIKE \''.$str.'%\'
          AND id NOT IN 
            (SELECT master_activity_id FROM class_activity)
          ORDER BY name', FALSE);
    return $this->db->get();
  }

您还需要设置autosuggest <div>和列表的样式,以使UI更加清晰,列表元素可以单击。 清单15中显示了添加到./assets/css/screen.css的样式。

清单15.使自动提示列表清晰可点击
/***************/
/* Autosuggest */

.autosuggest {
  border:1px solid #000000;
  display:none;
  overflow:hidden;
  padding:0px;
  position:absolute;
  width:200px;
  z-index:1;
}

.autosuggest ul li {
  background-color:#FFFFFF;
  cursor:pointer;
  display:block;
  list-style:none;
  padding:5px;
  white-space:nowrap;
}

.autosuggest ul li:hover {
  background-color:#316AC5;
  color:#FFFFFF;
}

.loading{
  background-image:url('../img/indicator.gif');
  background-position:right;
  background-repeat:no-repeat;
}

.autosuggest_input {
  width:200px;
}

.table_header_add {
  background-color:#FFCC66;
}

.odd_row_add {
  background-color:#FFCC66;
}

您即将完成。 您可以在字段中键入字符以检索一组匹配的活动。 现在,实现代码以选择,显示和保存该类的活动。 首先将两个函数添加到global.js文件中,以设置活动名称字段并显示包含活动信息的行。 清单16显示了两者的源代码。

清单16.获取和显示所选活动
/* AUTOSUGGEST SET ACTIVITY */
// triggered by an onclick from any of the li's in the autosuggest list
// set the class_acitity field, wait and fade the autosuggest list
// then display the activity details
function set_activity(activity_name, master_activity_id) {
  $('#class_activity').val(activity_name);
  setTimeout("$('#autosuggest_list').fadeOut(500);", 250);
  display_activity_details(master_activity_id);
}

/* AUTOSUGGEST DISPLAY ACTIVITY DETAILS */
// called by set_activity()
// get the HTML to display and display it
function display_activity_details(master_activity_id) {
  
  // Ajax request to CodeIgniter controller "ajax" method "get_activity_html"
  // post the master_class_activity parameter values
  $.post('/index.php/ajax/get_activity_html',
    { 'master_activity_id':master_activity_id },
    // when the Web server responds to the request
    // replace the innerHTML of the select_activity element
    function(result) { 
      $('#select_activity').html(result);
    }
  );
}

此代码还使用Ajax获取显示所选活动的表行。 它HTML由清单17中的代码生成。

清单17.回显显示活动HTML表
public function get_activity_html()
  {
    $this->load->model('MActivity', '', TRUE);
    $this->load->library('table');

    $requested_activity_id = $_POST['master_activity_id'];
    $requested_activity_qry = 
      $this->MActivity->get_requested_master_activity($requested_activity_id);

    // code leveraged from /controllers/activity.php manage_class_listing() method
    // generate HTML table from query results
    $tmpl = array (
      'table_open' => '<table>',
      'heading_row_start' => '<tr class="table_header_add">',
      'row_start' => '<tr class="odd_row_add">' 
    );
    $this->table->set_template($tmpl); 
    
    $this->table->set_caption('&nbsp;Add this Activity'); 

    $this->table->set_empty("&nbsp;"); 
    
    $this->table->set_heading('<span class="date_column">Date</span>',
                  '<span class="activity_name_column">Activity Name</span>',
                  '<span class="address_column">Address</span>',
                  'City', 'Details');
    
    $table_row = array();

    foreach ($requested_activity_qry->result() as $activity)
    {
      $m_id = $activity->master_activity_id;

      $table_row = NULL;

      $table_row[] = ''.
        '<form action="" name="form_'.$m_id.'" method="post">'.
        '<input type="hidden" name="master_activity_id" value="'.$m_id.'"/> '.
        '<input type="text" name="activity_date" size="12" /> '.
        '<input type="hidden" name="action" value="save" /> '.
        '</form>'.
        '<span class="help-text">format: MM-DD-YYYY</span><br/>'.
        '<a href="" onclick="document.forms[\'form_'.$m_id.'\'].submit();'.
        'return false;">save</a>';


      $table_row[] = '<input type="text" value="'.$activity->name.
        '" id="class_activity" onkeyup="autosuggest(this.value);"'.
        'class="autosuggest_input" />'.
        '<div class="autosuggest" id="autosuggest_list"></div>';
      $table_row[] = htmlspecialchars($activity->address);
      $table_row[] = htmlspecialchars($activity->city);
      $table_row[] = htmlspecialchars($activity->details);

      $this->table->add_row($table_row);
    }    
      
    $requested_activities_table = $this->table->generate();

    echo $requested_activities_table;
  }

}

只需少量修改即可从活动控制器中利用此代码,包括回显最终表而不返回它。 它要求清单18中显示SQL查询来自./system/application/models/mactivity.php。

清单18.返回所请求的主活动
// Returns a single master activity record
  public function get_requested_master_activity($id)
  {
    $this->db->select('id as master_activity_id, name, address, city, details');
    $this->db->where('id', $id);
    return $this->db->get('master_activity');
  }

最后,尽管您已经可以添加新活动,但是您想要删除未计划的活动并以升序对列表进行重新排序。 清单19显示了MActivity模型中更新SQL代码。

清单19.仅返回未计划的活动
// Retrieve all master activity records
  function list_class_activities($activity_id)
  {
    // get all records
    if (!$activity_id) {
      $this->db->select('ma.id as master_activity_id, ma.name, 
                ma.address, ma.city, 
                ma.details, ca.id as class_activity_id, ca.date
            FROM master_activity ma
            /*LEFT*/ JOIN class_activity ca ON ca.master_activity_id = ma.id
            ORDER BY ca.date /*DESC*/, ma.name', FALSE);
      return $this->db->get();
    // get all records except the one being requested
    } else {
      $this->db->select('ma.id as master_activity_id, ma.name, 
                ma.address, ma.city, 
                ma.details, ca.id as class_activity_id, ca.date
            FROM (SELECT * FROM master_activity 
              WHERE master_activity.id != '.$activity_id.') ma
            /*LEFT*/ JOIN class_activity ca ON ca.master_activity_id = ma.id
            ORDER BY ca.date /*DESC*/, ma.name', FALSE);
      return $this->db->get();
    }
  }

可视日历选择日期

UI的最终改进是用可视日历替换用于输入日期的文本输入字段。 为此,请使用jQuery UI Datepicker,它是jQuery UI库(jQuery库的开源扩展)中流行的插件。 更新./system/application/views/template.php文件,如清单20所示。

清单20.包括jQuery UI Datepicker
<!-- including the jQuery UI Datepicker and styles -->
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"
  type="text/javascript"></script>
<link href="/assets/css/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />
<style type="text/css">
  /* jQuery UI sizing override */
  .ui-widget {font-size:1em;}
</style>

请注意, <script>标记不是下载库,而是引用http://ajax.googleapis.com,它是许多库(例如jQuery UI)的免费存储库。 CSS文件和图像被配置为仅包含必要的样式(http://jqueryui.com/download)。 最后,在假定主体字体大小为62.5%的情况下构建jQuery UI库,因此您可以覆盖其默认值以适当地调整其大小。

Datepicker通过绑定到HTML中CSS类或ID来工作。 对于edit活动功能,在第210行附近的./system/application/controllers/activity.php中的date输入字段中分配一个名为date-picker的类。代码如清单21所示。

清单21.为编辑指定日期选择器类
// add the date-picker class to the date input field
          '<input type="text" name="activity_date" size="12" value="'.
            date('m/d/Y', strtotime($activity->date)).'" class="date-picker" /> '.
          '<input type="hidden" name="action" value="update" /> '.
          '</form>'.
          '<span class="help-text">format: MM/DD/YYYY</span><br/>'.

对于添加活动功能,在第83行的./system/application/controllers/ajax.php中为date输入字段分配相同的类,如清单22所示。

清单22.为添加分配日期选择器类
// add the date-picker class to the date input field
        '<input type="text" name="activity_date" size="12" class="date-picker" /> '.
        '<input type="hidden" name="action" value="save" /> '.
        '</form>'.
        '<span class="help-text">format: MM/DD/YYYY</span><br/>'.

最后,绑定Datepicker,以便在编辑或添加班级活动时显示它。 清单23显示了位于global.js文件的$(document).ready()函数内部的代码。

清单23.将Datepicker绑定到一个类
/* jQUERY UI CALENDAR PLUGIN */
  // bind the Datepicker to the date-picker class
  $(".date-picker").datepicker();

现在尝试编辑课堂活动。 将光标放在日期输入字段中时,将显示一个日历,您可以为该活动选择一个日期。 但是,请注意,尝试添加活动时,此方法不起作用。 这是因为添加活动HTML是在文档已加载后(使用Ajax)编写的,因此Datepicker不会绑定到其日期输入字段。 要解决此问题,请在Ajax函数编写HTML之后将Datepicker绑定到日期输入字段。 清单24显示了对global.js文件中的display_activity_details()函数的更改。

清单24.将Datepicker绑定到添加日期字段
function(result) { 
      $('#select_activity').html(result);

      // because the add datepicker is not loaded with the DOM
      // manually add it after the date input field is written
      $(".date-picker").datepicker();
    }

现在,您可以使用Datepicker日历添加班级活动。

结论

在工作上表现出色! 您已经学会了通过jQuery对象组合DOM操作并通过Ajax实现无缝通信,从而显着改善了该应用程序的UI。 而且在许多情况下,执行此操作的代码非常小。 现在,您可能会面临通过进一步使用Ajax在线进行类活动编辑或实现阅读本文时可能拥有的任何其他UI想法来进一步增强应用程序的挑战。


翻译自: https://www.ibm.com/developerworks/web/library/wa-aj-codeigniter/index.html

codeigniter使用

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值