根据table数据监听行事件请求后端返回给ajax的数据显示在layui弹出层iframe中

本文介绍了一个基于layui框架实现的表格行点击事件处理流程。通过监听表格行点击事件并发起Ajax请求获取数据,然后利用layer弹窗展示详细信息。具体包括JS事件绑定、Ajax通信、后端数据处理及前端页面展示等步骤。

实现思路

layui监听 table行事件调用ajax请求并将点击的行的数据发送给控制器,由控制器调用后端业务得到结果将结果放入session,由ajax 回调函数success open一个type为2(即iframe)的弹出层,content属性为控制器链接,弹出层请求的控制器返回一个jsp页面,在jsp页面中获取并显示之前存入session中的数据。

主页面.js

//监听行单击事件(双击事件为:rowDouble)
table.on('row(unreadMessage)', function(obj){
    var data = obj.data;
    $.ajax({
        type: 'POST',
        url: '/stu-info_manage/getTransactionDetail',//发送请求
        data: {
            messageId:data.messageId,
        },
        success: function(result) {
            layer.open({
                type: 2,//弹出框类型
                shift:1,//弹出框动画效果
                closeBtn: 0, //不显示关闭按钮
                anim: 5,
                shadeClose: true, //开启遮罩关闭
                title:'事务信息',
                area : ['60%' , '90%'],
                shift:1,
                content:'/stu-info_manage/transactionDetail'//将结果页面放入layer弹出层中

            });
        }
    });

Controller

   //事务详情弹出层
    @RequestMapping("/getTransactionDetail")
    @ResponseBody
    public String getTransactionDetail(HttpServletRequest request,
                                           @RequestParam("messageId") int messageId) {
        String content;
        try {
            //创建session对象
            HttpSession session = request.getSession();
            //把数据保存在session域对象中
            session.setAttribute("messageId", messageId);
            content=ykyService.queryMessageContent(messageId);
            session.setAttribute("messageContent", content);
            if(session==null||"".equals(messageId+"")){
                //没有登录成功,跳转到登录页面
                return "redirect:/";    //返回首页
            }
        }catch (Exception e){
            return "redirect:/";
        }
        return content;
    }
    //加载事务内容页面
    @RequestMapping("/transactionDetail")
    public String transactionDetail(HttpServletRequest request) {
        try {
            //创建session对象
            HttpSession session = request.getSession();
            //取出会话数据
            String id = (String) session.getAttribute("id");
            System.out.println("id==="+id);
            if(session==null||id==null){
                //没有登录成功,跳转到登录页面
                return "redirect:/";    //返回首页
            }
        }catch (Exception e){
            return "redirect:/";
        }
        return "TransactionDetail";
    }

弹出层iframe加载的jsp页面(部分)

<script>
    var messageContent='${sessionScope.messageContent}';
</script>
<body>
<div class="layui-bg-gray" style="padding: 30px;">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md6">
            <div class="layui-panel">
                <div style="padding: 50px 30px;" id="messageContent"></div>
            </div>
        </div>
    </div>
</div>
<script>
    $("#messageContent").text(messageContent);
</script>
</body>
<think>我们有两个问题需要解决: 1. Layui upload.render 多文件上传时,index值未变化的问题 2. 使用table.reload('listTableID')更新表格中当前数据 我们先解决第一个问题:upload多文件上传index值不变的问题。 根据引用[5]中的示例,我们使用了`multiple: true`来实现多文件上传。但是,在`done`回调函数中,我们可能会发现`index`参数始终是0或者固定值,无法正确对应每个文件。 原因分析:在Layui的upload模块中,当设置`multiple: true`时,实际上会为每个文件单独发起上传请求,但是`done`回调中的`index`参数是当前上传实例的索引(在多个上传实例的情况下),而不是每个文件的索引。对于同一个上传实例,多个文件上传时,`index`并不会按文件顺序递增。 解决方案:我们可以通过在上传前(例如在`choose`回调中)为每个文件生成一个唯一标识,并将该标识与文件对象关联。然后在`done`回调中,通过服务器返回的标识(或者使用文件的其他唯一信息)来匹配具体的文件。 具体步骤: a. 在`choose`回调中,遍历文件对象,为每个文件生成唯一标识(如时间戳+随机数),并存储在一个对象中,以文件名为键(注意:文件名可能重复,所以最好用文件对象本身,但考虑到存储,我们可以用文件名+大小+最后修改时间等生成一个唯一key)。 b. 在上传时,将唯一标识作为额外参数传到服务器(使用`data`参数)。 c. 在服务器返回结果时,将唯一标识返回(或者我们在客户端根据返回的文件名等信息匹配之前存储的标识)。 d. 在`done`回调中,通过返回的标识找到对应的文件,然后执对应操作(如更新对应文件项的状态)。 但是,由于引用[5]中并没有提到如何获取每个文件的上传索引,而且Layui的upload模块本身并没有为每个文件提供索引,因此我们需要自己管理。 另一种方法:在`before`回调中,我们可以通过参数`obj`获取到当前上传的文件对象数组,然后我们为每个文件生成一个唯一标识,并添加到文件对象上(例如`file.uid`)。然后,在`done`回调中,我们可以从`res`中获取到服务器返回数据,假设我们返回数据中包含这个唯一标识(或者我们通过文件的其他信息匹配),那么我们就可以知道是哪个文件上传完成了。 然而,服务器返回数据通常需要包含我们上传时传递的标识,这样我们才能对应起来。所以,我们可以通过`data`参数传递这个标识。 示例代码: 由于我们无法修改服务器返回数据结构,这里假设服务器可以返回我们传递的uid(或者我们通过其他方式匹配,比如文件名),但通常我们可以在上传时传递一个额外的参数,然后在服务器返回时原样返回这个参数。 修改后的上传示例: ```javascript layui.use('upload', function () { var upload = layui.upload; var fileUidMap = {}; // 用来存储文件唯一标识和文件索引的映射,如果需要索引的话 upload.render({ elem: '#uploadBtn', url: '/upload', multiple: true, accept: 'file', exts: 'xls|xlsx', // 选择文件后的回调 choose: function (obj) { // 将文件选择追加到文件队列 var files = obj.pushFile(); // 获取当前选择的文件 // 遍历文件,为每个文件生成唯一标识 layui.each(files, function (index, file) { // 生成唯一标识 var uid = 'uid_' + Date.now() + '_' + index; file.uid = uid; // 将唯一标识赋给文件对象 // 如果需要,可以在这里将文件信息显示在页面上,并记录这个uid对应的元素 }); // 预读本地文件,多文件上传需要手动提交,所以这里不自动上传 // 如果需要自动上传,则不需要在choose中处理,可以在before中处理 // 这里我们假设自动上传,所以不需要手动提交 }, // 上传前的回调 before: function (obj) { // 这里可以设置额外的参数,将每个文件的uid传递到服务器 // 但是注意,这个回调是在所有文件上传之前触发的,所以我们需要为每个文件设置不同的参数 // 但是layui的upload在multiple模式下,每个文件都会单独请求,所以我们可以动态设置data // 但是,layui的upload模块并没有提供每个文件单独设置data的方法,所以我们可以通过重写配置的方式 // 在每次发送前动态设置data // 但是这样会覆盖整个data,所以我们需要在beforeSend回调中设置(layui.upload没有提供beforeSend) // 因此,我们换一种思路:在上传时,通过formData动态添加参数 // 在before中,我们可以通过obj.config来修改配置,但是它是全局的,所以不适合每个文件不同的情况 // 所以,我们可以在每个文件上传前(即每个请求前)修改formData // 但是layui.upload没有提供每个文件的before回调,所以我们需要在before中通过拦截请求来实现 // 这个比较复杂,所以我们可以采用另一种方式:在服务器端,我们通过文件内容来识别,但这样不可靠 // 因此,我们建议在服务器返回时,返回文件的原始名称,然后我们在客户端通过文件名来匹配(但文件名可能重复) // 所以,我们可以在客户端生成一个uid,然后通过formData附加到每个文件的上传请求中 // 但是,layui.upload没有提供每个文件单独设置formData的方法 // 经过查阅文档,layui.upload的multiple:true时,每个文件都会单独发送一个请求,那么我们可以利用这个特性,在每次发送请求前,动态修改data(因为每次请求都会触发before) // 但是,注意:before会在所有文件上传前触发一次,然后每个文件上传时再触发一次?实际上,multiple模式下,before只触发一次,然后每个文件上传时,会分别发送请求,但不会再次触发before。 // 所以,我们只能换一种方式:在choose的时候,我们为每个文件设置一个uid,然后在上传时,我们无法为每个文件单独设置data,那么我们就将所有的uid作为一个数组传递过去,但是这样服务器需要解析数组,并且与文件一一对应,这也不容易。 // 因此,我们可能需要修改layui.upload的源码,或者采用其他方式。 // 但是,layui.upload在v2.5.5版本之后,支持了单个文件上传前的回调(通过给文件对象设置before方法)?查看文档,并没有这样的功能。 // 所以,我们只能放弃在服务器端通过uid标识文件,转而使用文件的其他属性(如文件名+大小)来生成唯一标识,并在客户端存储每个文件的状态。 // 在done回调中,我们可以通过res(服务器返回)得到上传成功的文件信息,比如文件名、大小等,然后我们在客户端通过文件名和大小来匹配之前生成的文件对象。 // 所以,我们可以在choose回调中,将文件对象存储在一个数组中,在done回调中,通过返回的文件名和大小(或者其他唯一信息)来匹配数组中的文件对象,从而确定是哪个文件上传完成了。 // 但是,服务器返回数据中需要包含文件名和大小等信息。 // 示例代码(在choose中存储文件信息): // 我们定义一个数组 // 在choose回调中:filesArray.push(file); // 在done回调中:遍历filesArray,找到与res.data(假设服务器返回了文件名和大小)匹配的文件,然后根据这个文件在数组中的索引来更新对应的页面元素。 // 但是注意,文件上传完成后,我们需要从数组中移除,否则数组会越来越大。 // 由于这个实现相对复杂,且需要维护一个全局数组,所以这里我们采用另一种更简单的方法:在页面上显示文件列表时,为每个文件项设置一个data-id(唯一标识),然后在done回调中,通过返回的文件名找到对应的文件项(通过遍历文件项元素,比较文件名)来更新。 // 因此,我们可以在choose回调中,将文件信息显示在页面上,并为每个文件项设置一个自定义属性(如data-name,值为文件名),然后在done回调中,通过返回的文件名找到对应的元素。 // 示例: // choose: function(obj){ // var files = this.files = obj.pushFile(); // 得到当前选中的文件 // // 显示文件列表 // layui.each(files, function(index, file){ // var tr = $('<tr class="file-item">'); // tr.attr('data-name', file.name); // tr.append('<td>'+file.name+'</td><td>等待上传</td>'); // $('#fileList').append(tr); // }); // } // done: function(res){ // // 假设res.data中包含了上传成功的文件名 // var fileName = res.data.fileName; // $('.file-item').each(function(){ // if($(this).data('name') === fileName) { // $(this).find('td:eq(1)').text('上传成功'); // } // }); // } // 但是,如果文件名重复,这种方法就会出错。所以我们可以使用文件名+文件大小来生成一个key,然后设置为data-key,这样重复的概率就很小。 // 综上所述,由于Layui upload模块在多文件上传时没有提供每个文件的索引,我们只能通过这种方式来匹配。 // 因此,我们这里采用在页面上显示文件列表,并为每个文件项设置一个唯一标识(由文件名+大小+最后修改时间生成),然后在done回调中通过这个标识来更新。 // 由于用户的问题中,已经有一个$('.file-item')的元素,并且使用eq(index)来获取,但是index是固定的,所以导致问题。那么我们可以改为通过自定义属性来获取。 // 修改用户代码: // 原代码:var $item = $('.file-item').eq(index); // 改为:var $item = $('.file-item[data-temp="'+当前文件的唯一标识+'"]'); // 那么,在choose的时候,我们就需要为每个文件项设置data-temp属性,值为我们生成的唯一标识(注意:这个唯一标识在上传前生成,并保存在文件对象上,同时我们也要在服务器返回返回这个标识,或者我们在客户端根据返回的文件信息重新生成这个标识(通过文件名和大小)) // 但是,用户代码中已经有一个data-temp属性,并且在上传前设置为空,上传后设置为服务器返回的文件名。我们可以改变思路: // 在choose的时候,我们生成一个临时唯一标识,并设置到文件项的data-temp上,然后在上传时,将这个临时标识作为参数传到服务器,服务器返回时,将这个标识返回(这样我们就可以在done回调中知道是哪个文件了)。 // 具体步骤: // 1. 在choose回调中,为每个文件生成一个临时唯一标识(比如uuid),并设置到文件项的data-temp属性上,同时保存到文件对象上(用于上传时传递到服务器)。 // 2. 在上传时,通过data参数将这个临时标识传递到服务器。 // 3. 服务器保存这个标识,并在返回数据返回。 // 4. 在done回调中,通过res.tempId(假设服务器返回了)来找到对应的文件项,然后更新。 // 示例代码: // 由于用户没有提供完整的代码,我们根据用户已有的代码进调整: // 用户代码片段: // done: function (res) { // if (res.success) { // var $item = $('.file-item').eq(index); // $item.attr('data-temp', '').attr('data-server', res.tempName); // } // } // 修改后: // 在choose回调中: // var uuid = generateUUID(); // 生成唯一标识 // $item = $(...); // 创建文件项元素 // $item.attr('data-temp', uuid); // 设置临时标识 // 同时,在before回调中,设置上传参数: // before: function(obj) { // // 注意:这个回调只触发一次,所以我们需要在每次文件上传前设置参数(但layui.upload在multiple模式下会为每个文件单独请求,但before只触发一次) // // 所以,我们无法在每个文件上传前动态设置参数,除非我们修改layui.upload的源码。 // } // 因此,我们只能将临时标识作为文件对象的一个属性,然后在上传时,通过formData追加。 // 但是,layui.upload支持在data参数中使用函数,这样每次请求都会执函数,我们可以在这里获取当前文件的临时标识。 // 然而,layui.upload的data参数如果是函数,那么函数的参数就是当前上传的文件对象,这样就可以实现了。 // 示例: // data: function(file){ // return { // tempId: file.uid // 我们在choose时给file对象添加了uid属性 // }; // } // 这样,每个文件上传时,就会带上自己的uid。 // 然后,服务器需要将这个tempId返回(在返回json中),这样我们在done回调中就可以通过res.tempId来获取。 // 然后,我们就可以在done回调中这样写: // var $item = $('.file-item[data-temp="' + res.tempId + '"]'); // $item.attr('data-server', res.tempName).attr('data-temp', ''); // 将data-temp清空,表示已经上传 // 这样,我们就解决了index不变的问题。 // 由于用户代码中已经使用了data-temp属性,我们可以按照这个思路修改。 // 总结步骤: // 1. 在choose回调中,为每个文件生成一个唯一标识(uid),并赋值给文件对象(file.uid)和文件项元素的data-temp属性。 // 2. 在upload.render配置中,设置data为一个函数,返回{ tempId: file.uid }。 // 3. 服务器处理上传,将接收到的tempId原样返回(在返回json中)。 // 4. 在done回调中,通过返回的tempId找到对应的文件项元素,然后更新属性。 // 代码示例: // 生成唯一标识的函数(简单示例) function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } // 在upload.render的配置中: upload.render({ // ...其他配置 choose: function(obj) { // 将每次选择的文件追加到文件队列 var files = obj.pushFile(); // 得到选中的文件 // 显示文件列表 layui.each(files, function(index, file) { // 生成唯一标识 var uid = generateUUID(); file.uid = uid; // 给文件对象设置uid // 创建文件项 var $item = $('<div class="file-item">').text(file.name); $item.attr('data-temp', uid); $('#fileList').append($item); }); }, data: function(file) { return { tempId: file.uid // 将当前文件的uid作为参数上传 }; }, done: function(res) { if (res.success) { // 根据服务器返回的tempId找到文件项 var $item = $('.file-item[data-temp="' + res.tempId + '"]'); $item.attr('data-temp', '').attr('data-server', res.tempName); } } }); // 注意:服务器需要返回tempId,且值等于上传时传递的tempId。 // 这样,我们就解决了多文件上传时index不变的问题。 } }); }); ``` 接下来解决第二个问题:如何使用table.reload('listTableID')更新表格中当前数据根据引用[1]和引用[2],我们使用`table.reload`来重载表格数据。但是,默认情况下,`table.reload`会重新请求数据并重新渲染整个表格,这样会导致页面跳转到第一页,并且会丢失当前操作的状态。 如果我们只想更新当前数据,而不是整个表格,我们可以采用以下步骤: 1. 在表格渲染时,设置`page: {curr: 1}`,但这样并不能解决我们的问题,因为我们需要停留在当前页,并且只更新当前。 2. 实际上,`table.reload`方法可以接受一个`where`参数,用于传递查询条件,同时它还有一个`page`参数,用于控制分页。 3. 但是,如果我们只想更新当前,我们可以采用局部更新:即获取当前数据,然后修改这一数据,并调用`table.reload`的重载完成后的回调来更新这一,但这并不高效,因为会重新加载整个表格的数据。 4. 另一种方法是:在编辑后,通过`table.cache`获取表格缓存数据,然后找到对应的,修改数据,然后重新渲染该。 具体步骤: - 首先,在表格渲染时,设置`id: 'listTableID'`(这个id需要和reload时的id一致)。 - 然后,在编辑成功的回调中,我们可以通过`table.cache['listTableID']`获取当前表格的所有数据(包括修改未提交的)。 - 通过索引(或唯一id)找到对应的数据,更新数据。 - 然后,使用`obj.update`方法更新这一(如果是工具条事件事件回调中会返回obj,通过obj.update更新)。 但是,如果我们不是在工具条事件中(比如在弹窗编辑后),我们如何获取到这一的obj呢? 我们可以在操作这一的时候,将这一的obj保存下来(比如在点击编辑按钮时,将obj赋值给一个全局变量),然后在编辑完成后,用这个obj来更新。 但是,这种方法不推荐,因为全局变量容易出错。 更好的做法:在工具条事件中,我们通常会得到当前的obj,然后我们可以在这个作用域中处理编辑操作(比如打开一个弹窗),然后在弹窗的回调中,我们仍然可以访问到这个obj,然后更新。 示例代码: ```javascript table.on('tool(table)', function(obj) { var data = obj.data; // 当前数据 if (obj.event === 'edit') { // 打开编辑弹窗 layer.open({ type: 2, title: '编辑', content: 'edit.html', area: ['500px', '400px'], success: function(layero, index) { // 将当前数据传递到弹窗 var body = layer.getChildFrame('body', index); body.find('#name').val(data.name); // ...其他字段赋值 }, end: function() { // 弹窗关闭后,可以在这里重新加载表格,但这样会重载整个表格 }, btn: ['确定', '取消'], yes: function(index, layero) { // 获取弹窗中的表单数据 var iframeWindow = window['layui-layer-iframe' + index]; var formData = iframeWindow.getFormData(); // 发送请求更新数据 $.ajax({ url: '/update', data: formData, success: function(res) { if (res.success) { // 更新当前数据 obj.update({ name: formData.name, // ...其他字段 }); layer.close(index); } } }); } }); } }); ``` 但是,如果我们不在工具条事件中(比如在表格外部操作),那么我们就需要自己记录当前的索引或数据。 另外,如果我们使用`table.reload`,并且希望保持当前页,我们可以在reload时设置`page: {curr: 当前页码}`。 如何获取当前页码?在表格渲染完成后,我们可以监听分页事件,记录当前页码。 示例: ```javascript var currentPage = 1; // 记录当前页码 table.on('toolbar(table)', function(obj) { // 工具栏事件 }); table.on('page(table)', function(obj) { currentPage = obj.curr; // 更新当前页码 }); // 在需要重载表格的地方 table.reload('listTableID', { page: { curr: currentPage // 重新加载后保持当前页 } }); ``` 同时,为了保留选择项(如复选框选中状态),我们可以设置`smartReloadModel: true`(在table.render中设置)[^1]。 所以,结合这两个问题,我们分别给出了解决方案。 由于用户的问题比较长,且涉及两个独立的问题,我们分别进了回答。 如果用户需要更详细的代码示例,请参考上述代码片段。 相关问题: 1. Layui upload 如何实现文件上传前的格式校验? 2. Layui table 如何实现内编辑? 3. Layui upload 多文件上传时如何限制最大文件数量? 4. Layui table 如何实现数据导出? 5. Layui table 重载后如何保持排序状态? 如果用户对上述问题感兴趣,可以进一步提问。</think>### 解决 Layui 多文件上传索引问题及表格更新方案 #### 一、Layui Upload 多文件上传索引问题解决 当使用 `multiple: true` 进多文件上传时,`done` 回调中的 `index` 值不会自动变化,这是因为 Layui 的 Upload 模块在处理多文件时存在闭包作用域问题[^2]。以下是三种解决方案: **方案1:使用闭包隔离作用域(推荐)** ```javascript upload.render({ elem: '#uploadBtn', multiple: true, choose: function(obj) { // 为每个文件生成唯一标识 obj.preview(function(index, file) { file.uid = Date.now() + "_" + index; // 唯一标识 const $item = $(`<div class="file-item" data-uid="${file.uid}">`); $("#fileList").append($item); }); }, done: function(res) { if (res.success) { // 通过唯一标识定位元素 const $item = $(`.file-item[data-uid="${res.uid}"]`); $item.attr('data-server', res.tempName); } }, data: function(file) { return { uid: file.uid }; // 将UID发送到服务端 } }); ``` *服务端需返回上传时接收的 `uid` 参数* **方案2:文件特征匹配** ```javascript done: function(res) { const targetItem = Array.from($('.file-item')).find(item => $(item).data('name') === res.originalName ); $(targetItem).attr('data-server', res.tempName); } ``` **方案3:自定义索引管理** ```javascript let fileCounter = 0; upload.render({ choose: function(obj) { const files = obj.pushFile(); files.forEach(file => { file.customIndex = fileCounter++; $(`<div class="file-item" data-index="${file.customIndex}">`) .appendTo("#fileList"); }); }, done: function(res) { $(`.file-item[data-index="${res.customIndex}"]`) .attr('data-server', res.tempName); } }); ``` #### 二、表格数据更新方案 使用 `table.reload()` 更新特定数据而不刷新整个表格: **步骤1:表格初始化时启用智能重载** ```javascript table.render({ id: 'listTableID', elem: '#table', smartReloadModel: true, // 关键配置[^1] cols: [[...]], page: true }); ``` **步骤2:编辑后重载当前页** ```javascript // 编辑成功后执 table.reload('listTableID', { where: { ... }, // 保持原有查询条件 page: { curr: tablePage.curr // 获取当前页码 }, done: function(res) { layer.msg('数据更新成功'); } }); ``` **步骤3:精确更新单数据(无需重载)** ```javascript // 获取表格缓存数据 const tableData = table.cache('listTableID'); // 找到需要更新的 const rowIndex = tableData.findIndex(item => item.id === updatedData.id); // 更新数据 if (rowIndex !== -1) { tableData[rowIndex] = {...tableData[rowIndex], ...updatedData}; // 重新渲染单 const ins = table.get('listTableID'); ins.data[rowIndex] = tableData[rowIndex]; ins.renderRow(ins.data[rowIndex], rowIndex); } ``` #### 三、Upload 按钮失效问题修复 当 `table.reload()` 后 Upload 按钮失效,需重新绑定事件[^4]: ```javascript function bindUpload() { upload.render({ elem: '#importExcel', done: function(res) { table.reload('listTableID'); // 表格重载 bindUpload(); // 重新绑定上传事件 } }); } // 初始化时绑定 bindUpload(); ``` ### 最佳实践总结 1. **多文件上传**:优先使用 UID 方案解决索引问题,确保服务端返回唯一标识 2. **表格更新**: - 整表更新:启用 `smartReloadModel` 保持分页状态[^1] - 单更新:通过 `table.cache()` 操作缓存数据 3. **组件联动**: - 表格重载后重新初始化 Upload - 使用 `layer.open` 关闭回调刷新表格[^2] > 更多实践细节参考 Layui 官方文档:[Fly 社区](https://fly.layui.com/jie/43423/)[^1] --- ### 相关问题 1. Layui Upload 如何实现上传前的文件格式校验? 2. 如何保持 Layui Table 排序状态在重载后不丢失? 3. Layui 多文件上传时如何限制最大文件数量? 4. 如何实现 Layui Table 内编辑后的局部刷新? 5. Layui Upload 如何显示实时上传进度条?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值