Change import and delete subscribers to multi process.
This commit is contained in:
parent
4735b107d7
commit
7fd1c7765f
|
@ -15,6 +15,10 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
@subscribers = EPaperSubscriber.order_by(sort)
|
@subscribers = EPaperSubscriber.order_by(sort)
|
||||||
|
|
||||||
@subscribers = search_data(@subscribers,[:email]).page(params[:page]).per(10)
|
@subscribers = search_data(@subscribers,[:email]).page(params[:page]).per(10)
|
||||||
|
@thread = (params[:thread_id] ? Multithread.find(params[:thread_id]) : nil rescue nil)
|
||||||
|
if @thread && @thread.status[:status] == 'finish'
|
||||||
|
@thread = nil
|
||||||
|
end
|
||||||
render :partial => "index" if request.xhr?
|
render :partial => "index" if request.xhr?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,9 +47,21 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
render :partial => 'modal_select', :layout => false
|
render :partial => 'modal_select', :layout => false
|
||||||
end
|
end
|
||||||
def import_from_excel
|
def import_from_excel
|
||||||
|
thread = Multithread.where(:key=>'import_epaper_subscribers').first
|
||||||
|
if thread.nil?
|
||||||
|
thread = Multithread.create(:key=>'import_epaper_subscribers',:status=>{:status=>'Processing'})
|
||||||
|
else
|
||||||
|
thread.update(:status=>{:status=>'Processing'})
|
||||||
|
end
|
||||||
|
Thread.new do
|
||||||
workbook = RubyXL::Parser.parse(params["import_file"].tempfile)
|
workbook = RubyXL::Parser.parse(params["import_file"].tempfile)
|
||||||
subscribe_sheet = workbook['Subscribe']
|
subscribe_sheet = workbook['Subscribe']
|
||||||
unsubscribe_sheet = workbook['Unsubscribe']
|
unsubscribe_sheet = workbook['Unsubscribe']
|
||||||
|
all_count = (subscribe_sheet ? (subscribe_sheet.count - 1) : 0) + (unsubscribe_sheet ? (unsubscribe_sheet.count - 1) : 0)
|
||||||
|
puts_every_count = all_count * 3 / 100
|
||||||
|
current_count = 0
|
||||||
|
finish_percent = 0
|
||||||
|
thread.update(:status=>{:status=>'Importing','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
subscribe_sheet.each_with_index do |row, i|
|
subscribe_sheet.each_with_index do |row, i|
|
||||||
next if i < 1
|
next if i < 1
|
||||||
c0 = row.cells[0]
|
c0 = row.cells[0]
|
||||||
|
@ -66,6 +82,11 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
subscriber.save
|
subscriber.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
current_count += 1
|
||||||
|
if current_count % puts_every_count == 0
|
||||||
|
finish_percent = (current_count * 100.0 / all_count).round(1)
|
||||||
|
thread.update(:status=>{:status=>'Importing','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
unsubscribe_sheet.each_with_index do |row, i|
|
unsubscribe_sheet.each_with_index do |row, i|
|
||||||
next if i < 1
|
next if i < 1
|
||||||
|
@ -87,8 +108,16 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
subscriber.save
|
subscriber.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
current_count += 1
|
||||||
|
if current_count % puts_every_count == 0
|
||||||
|
finish_percent = (current_count * 100.0 / all_count).round(1)
|
||||||
|
thread.update(:status=>{:status=>'Importing','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
end
|
end
|
||||||
redirect_to admin_e_paper_subscribers_path
|
end
|
||||||
|
finish_percent = 100
|
||||||
|
thread.update(:status=>{:status=>'finish','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
|
end
|
||||||
|
redirect_to admin_e_paper_subscribers_path(thread_id: thread.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_excel_format
|
def download_excel_format
|
||||||
|
@ -100,12 +129,42 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
def batch_delete_subscribers
|
||||||
|
@thread = (params[:thread_id] ? Multithread.find(params[:thread_id]) : nil rescue nil)
|
||||||
|
if @thread && @thread.status[:status] == 'finish'
|
||||||
|
@thread = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
def delete_subscribers
|
def delete_subscribers
|
||||||
subscriber_ids = params['subscriber_ids']
|
subscriber_ids = params['subscriber_ids']
|
||||||
|
thread = Multithread.where(:key=>'delete_epaper_subscribers').first
|
||||||
|
if thread.nil?
|
||||||
|
thread = Multithread.create(:key=>'delete_epaper_subscriber',:status=>{:status=>'Processing'})
|
||||||
|
else
|
||||||
|
thread.update(:status=>{:status=>'Processing'})
|
||||||
|
end
|
||||||
if subscriber_ids
|
if subscriber_ids
|
||||||
EPaperSubscriber.where(:id.in=>subscriber_ids).destroy
|
all_count = subscriber_ids.count
|
||||||
end
|
puts_every_count = all_count * 3 / 100
|
||||||
redirect_to admin_e_paper_subscribers_path
|
current_count = 0
|
||||||
|
finish_percent = 0
|
||||||
|
thread.update(:status=>{:status=>'Deleting','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
|
Thread.new do
|
||||||
|
EPaperSubscriber.where(:id.in=>subscriber_ids).to_a.each do |s|
|
||||||
|
s.destroy
|
||||||
|
current_count += 1
|
||||||
|
if current_count % puts_every_count == 0
|
||||||
|
finish_percent = (current_count * 100.0 / all_count).round(1)
|
||||||
|
thread.update(:status=>{:status=>'Deleting','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
finish_percent = 100
|
||||||
|
thread.update(:status=>{:status=>'finish','all_count'=>all_count,'current_count'=>current_count,'finish_percent'=>finish_percent})
|
||||||
|
end
|
||||||
|
thread.update(:status=>{:status=>'finish'})
|
||||||
|
else
|
||||||
|
thread.update(:status=>{:status=>'finish'})
|
||||||
|
end
|
||||||
|
redirect_to admin_e_paper_subscribers_batch_delete_subscribers_path(thread_id: thread.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,3 +1,22 @@
|
||||||
|
<% if @thread %>
|
||||||
|
<div id="threadModal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="threadModal" aria-hidden="false">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 id="threadModal"><%=t("e_paper.#{@thread.key}")%></h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="thread-status"><%= @thread.status[:status] %></div>
|
||||||
|
<div><span class="thread-current-count"><%= @thread.status[:current_count].to_i %></span>/<span class="thread-all-count"><%= @thread.status[:all_count].to_i %></span></div>
|
||||||
|
<span class="thread-finish_percent"><%= @thread.status[:finish_percent].to_i %></span> % finished
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn" id="modal-close-btn" style="width: 4em;" data-dismiss="modal" aria-hidden="true"><%=t('close')%></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<table class="table main-list">
|
<table class="table main-list">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="sort-header">
|
<tr class="sort-header">
|
||||||
|
@ -34,6 +53,9 @@
|
||||||
content_tag(:div, link_to(t("e_paper.export"), admin_e_paper_subscribers_export_excel_path + '.xlsx', :class=>"btn btn-success"), class: "pull-right")
|
content_tag(:div, link_to(t("e_paper.export"), admin_e_paper_subscribers_export_excel_path + '.xlsx', :class=>"btn btn-success"), class: "pull-right")
|
||||||
%>
|
%>
|
||||||
<div class="dropup upload-button pull-right">
|
<div class="dropup upload-button pull-right">
|
||||||
|
<% if @thread %>
|
||||||
|
<button class="show_progress btn btn-primary" type="button"><%= t("e_paper.show_progress") %></button>
|
||||||
|
<% end %>
|
||||||
<button class="btn btn-info dropdown-toggle" type="button" data-toggle="dropdown">
|
<button class="btn btn-info dropdown-toggle" type="button" data-toggle="dropdown">
|
||||||
<i class="icon-upload-alt icon-white"></i><%= t('personal_journal.upload') %>
|
<i class="icon-upload-alt icon-white"></i><%= t('personal_journal.upload') %>
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
|
@ -49,3 +71,46 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
function update_thread(){
|
||||||
|
$.post("<%=admin_threads_get_status_path%>",{"id": "<%=params[:thread_id]%>"}).done(function(data){
|
||||||
|
var finish_percent = data["finish_percent"];
|
||||||
|
var current_count = data["current_count"];
|
||||||
|
var all_count = data["all_count"];
|
||||||
|
var is_finish = (data["status"] == "finish");
|
||||||
|
if(finish_percent){
|
||||||
|
$("#threadModal .modal-body .thread-status").text(data["status"]);
|
||||||
|
if(data["status"] != 'Processing'){
|
||||||
|
$("#threadModal .modal-body .thread-current-count").text(current_count);
|
||||||
|
$("#threadModal .modal-body .thread-all-count").text(all_count);
|
||||||
|
}
|
||||||
|
$("#threadModal .modal-body .thread-finish_percent").text(finish_percent)
|
||||||
|
}
|
||||||
|
if(!is_finish){
|
||||||
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
}else{
|
||||||
|
if(window.time_out_id)
|
||||||
|
window.clearTimeout(window.time_out_id);
|
||||||
|
window.setTimeout(function(){
|
||||||
|
$("#threadModal").modal("hide");
|
||||||
|
alert(data["status"]);
|
||||||
|
}, 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if($("#threadModal").length != 0){
|
||||||
|
$("#threadModal").on('hidden.bs.modal',function(){
|
||||||
|
window.clearTimeout(window.time_out_id);
|
||||||
|
})
|
||||||
|
$("#threadModal").on('shown.bs.modal',function(){
|
||||||
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
})
|
||||||
|
$("#threadModal").modal("show");
|
||||||
|
$(".show_progress").click(function(){
|
||||||
|
$("#threadModal").modal("show");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -161,6 +161,10 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
function select_subscribers(){
|
function select_subscribers(){
|
||||||
|
if(window.still_processing){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.still_processing = true;
|
||||||
window.selected_subscriber_ids = [];
|
window.selected_subscriber_ids = [];
|
||||||
var subscriber_cards = $('#member-filter [name="subscriber_ids[]"]:checked').map(function(i, subscriber){
|
var subscriber_cards = $('#member-filter [name="subscriber_ids[]"]:checked').map(function(i, subscriber){
|
||||||
window.selected_subscriber_ids.push(subscriber.value);
|
window.selected_subscriber_ids.push(subscriber.value);
|
||||||
|
@ -177,6 +181,7 @@
|
||||||
}
|
}
|
||||||
$('#members_field').change();
|
$('#members_field').change();
|
||||||
$("#member-filter").modal('hide');
|
$("#member-filter").modal('hide');
|
||||||
|
window.still_processing = false;
|
||||||
}
|
}
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$('#subscribers_form [type="submit"]').click(select_subscribers);
|
$('#subscribers_form [type="submit"]').click(select_subscribers);
|
||||||
|
|
|
@ -40,6 +40,9 @@
|
||||||
<button class="btn" id="remove_subscribers" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.delete_from_choice') %></button>
|
<button class="btn" id="remove_subscribers" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.delete_from_choice') %></button>
|
||||||
<button class="btn btn-danger" id="remove_subscribers_forever" style="display: none;"><i class="icon-trash"></i> <%=t('e_paper.delete_subscribers') %></button>
|
<button class="btn btn-danger" id="remove_subscribers_forever" style="display: none;"><i class="icon-trash"></i> <%=t('e_paper.delete_subscribers') %></button>
|
||||||
<!-- <button class="btn" id="edit_members" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.edit_members') %></button> -->
|
<!-- <button class="btn" id="edit_members" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.edit_members') %></button> -->
|
||||||
|
<% if @thread %>
|
||||||
|
<button class="show_progress btn btn-primary" type="button"><%= t("e_paper.show_progress") %></button>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% if @thread %>
|
<% if @thread %>
|
||||||
|
@ -47,10 +50,12 @@
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h3 id="threadModal"><%=t("site.edit_members.#{@thread.key}")%></h3>
|
<h3 id="threadModal"><%=t("e_paper.#{@thread.key}")%></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<%= @thread.status[:finish_percent] %> % finished
|
<div class="thread-status"><%= @thread.status[:status] %></div>
|
||||||
|
<div><span class="thread-current-count"><%= @thread.status[:current_count].to_i %></span>/<span class="thread-all-count"><%= @thread.status[:all_count].to_i %></span></div>
|
||||||
|
<span class="thread-finish_percent"><%= @thread.status[:finish_percent].to_i %></span> % finished
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn" id="modal-close-btn" style="width: 4em;" data-dismiss="modal" aria-hidden="true"><%=t('close')%></button>
|
<button class="btn" id="modal-close-btn" style="width: 4em;" data-dismiss="modal" aria-hidden="true"><%=t('close')%></button>
|
||||||
|
@ -172,9 +177,16 @@
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
$(document).on('click',".select_member_modal",function () {
|
$(document).on('click',".select_member_modal",function () {
|
||||||
|
if(window.still_processing){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.still_processing = true;
|
||||||
$.get("<%= admin_e_paper_subscribers_get_subscribers_modal_path %>").done(function(data){
|
$.get("<%= admin_e_paper_subscribers_get_subscribers_modal_path %>").done(function(data){
|
||||||
$("#select_member_modal").html(data);
|
$("#select_member_modal").html(data);
|
||||||
$("#member-filter").modal('show');
|
$("#member-filter").modal('show');
|
||||||
|
window.still_processing = false;
|
||||||
|
}).fail(function(){
|
||||||
|
window.still_processing = false;
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -236,14 +248,28 @@
|
||||||
$(this).parent().addClass("open");
|
$(this).parent().addClass("open");
|
||||||
})
|
})
|
||||||
$('#remove_subscribers_forever').off('click').on('click',function(){
|
$('#remove_subscribers_forever').off('click').on('click',function(){
|
||||||
var member_cards = '<ul id="card-list-managers" class="checkbox-card clearfix" style="clear: left;">'+$.map($('#members_field .check-item'),function(member_card,i){
|
if(window.still_processing){
|
||||||
return member_card.outerHTML;
|
return;
|
||||||
}).join('')+'</ul>';
|
}
|
||||||
|
window.still_processing = true;
|
||||||
|
var member_cards;
|
||||||
|
var check_items = $('#members_field #card-list-managers .check-item');
|
||||||
|
if(check_items.length > 50){
|
||||||
|
member_cards = '<ul id="card-list-managers" class="checkbox-card clearfix" style="clear: left;">'+check_items.slice(0,50).map(function(i,v){ return $(v).prop('outerHTML')}).toArray().join('')+'<li style="background: transparent;color: black;">... etc</li>'+'</ul>';
|
||||||
|
}else{
|
||||||
|
member_cards = '<ul id="card-list-managers" class="checkbox-card clearfix" style="clear: left;">'+$('#members_field #card-list-managers').html()+'</ul>';
|
||||||
|
}
|
||||||
|
window.still_processing = false;
|
||||||
if(double_confirm_message('<%= t('e_paper.delete_subscribers_hint') %>')){
|
if(double_confirm_message('<%= t('e_paper.delete_subscribers_hint') %>')){
|
||||||
|
if($('#dialog-confirm').length == 0){
|
||||||
$("#members_form").before("<div id='dialog-confirm' title='"+"<%= t('site.edit_members.delete_hint1') %>'>"+
|
$("#members_form").before("<div id='dialog-confirm' title='"+"<%= t('site.edit_members.delete_hint1') %>'>"+
|
||||||
"<div style='clear:both;'></div><div><span class='ui-icon ui-icon-alert' style='float:left; margin:0 7px 20px 0;'></span>"+
|
"<div style='clear:both;'></div><div><span class='ui-icon ui-icon-alert' style='float:left; margin:0 7px 20px 0;'></span>"+
|
||||||
"<%= t('e_paper.delete_subscribers_hint2') %>"+member_cards+"</div>"+
|
"<%= t('e_paper.delete_subscribers_hint2') %>"+member_cards+"</div>"+
|
||||||
"</div>");
|
"</div>");
|
||||||
|
}else{
|
||||||
|
$('#dialog-confirm').html("<div style='clear:both;'></div><div><span class='ui-icon ui-icon-alert' style='float:left; margin:0 7px 20px 0;'></span>"+
|
||||||
|
"<%= t('e_paper.delete_subscribers_hint2') %>"+member_cards+"</div>");
|
||||||
|
}
|
||||||
$( "#dialog-confirm" ).dialog({
|
$( "#dialog-confirm" ).dialog({
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minHeight: 100,
|
minHeight: 100,
|
||||||
|
@ -267,9 +293,16 @@
|
||||||
function update_thread(){
|
function update_thread(){
|
||||||
$.post("<%=admin_threads_get_status_path%>",{"id": "<%=params[:thread_id]%>"}).done(function(data){
|
$.post("<%=admin_threads_get_status_path%>",{"id": "<%=params[:thread_id]%>"}).done(function(data){
|
||||||
var finish_percent = data["finish_percent"];
|
var finish_percent = data["finish_percent"];
|
||||||
var is_finish = (data["status"] == "finish" || data["status"] == "error");
|
var current_count = data["current_count"];
|
||||||
|
var all_count = data["all_count"];
|
||||||
|
var is_finish = (data["status"] == "finish");
|
||||||
if(finish_percent){
|
if(finish_percent){
|
||||||
$("#threadModal .modal-body").text(finish_percent + " % finished")
|
$("#threadModal .modal-body .thread-status").text(data["status"]);
|
||||||
|
if(data["status"] != 'Processing'){
|
||||||
|
$("#threadModal .modal-body .thread-current-count").text(current_count);
|
||||||
|
$("#threadModal .modal-body .thread-all-count").text(all_count);
|
||||||
|
}
|
||||||
|
$("#threadModal .modal-body .thread-finish_percent").text(finish_percent)
|
||||||
}
|
}
|
||||||
if(!is_finish){
|
if(!is_finish){
|
||||||
window.time_out_id = window.setTimeout(update_thread, 1000);
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
@ -285,8 +318,16 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if($("#threadModal").length != 0){
|
if($("#threadModal").length != 0){
|
||||||
$("#threadModal").modal("show");
|
$("#threadModal").on('hidden.bs.modal',function(){
|
||||||
|
window.clearTimeout(window.time_out_id);
|
||||||
|
})
|
||||||
|
$("#threadModal").on('shown.bs.modal',function(){
|
||||||
window.time_out_id = window.setTimeout(update_thread, 1000);
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
})
|
||||||
|
$("#threadModal").modal("show");
|
||||||
|
$(".show_progress").click(function(){
|
||||||
|
$("#threadModal").modal("show");
|
||||||
|
})
|
||||||
}
|
}
|
||||||
$(document).on('click','.modal-backdrop',function(){
|
$(document).on('click','.modal-backdrop',function(){
|
||||||
$('.modal').modal('hide');
|
$('.modal').modal('hide');
|
||||||
|
|
|
@ -4,6 +4,7 @@ en:
|
||||||
restful_actions:
|
restful_actions:
|
||||||
batch_delete_subscribers: "Batch Delete Subscribers"
|
batch_delete_subscribers: "Batch Delete Subscribers"
|
||||||
e_paper:
|
e_paper:
|
||||||
|
show_progress: "Show Progress"
|
||||||
delete_subscribers_hint2: "Delete Subscribers below forever."
|
delete_subscribers_hint2: "Delete Subscribers below forever."
|
||||||
delete_subscribers_hint1: "Do you realy want to delete Subscribers you added forever?"
|
delete_subscribers_hint1: "Do you realy want to delete Subscribers you added forever?"
|
||||||
delete_subscribers_hint: "Click 『Add』 button to select Subscribers"
|
delete_subscribers_hint: "Click 『Add』 button to select Subscribers"
|
||||||
|
|
|
@ -4,6 +4,7 @@ zh_tw:
|
||||||
restful_actions:
|
restful_actions:
|
||||||
batch_delete_subscribers: "批次刪除訂閱者"
|
batch_delete_subscribers: "批次刪除訂閱者"
|
||||||
e_paper:
|
e_paper:
|
||||||
|
show_progress: "顯示進度"
|
||||||
delete_subscribers_hint2: "永久刪除以下訂閱者"
|
delete_subscribers_hint2: "永久刪除以下訂閱者"
|
||||||
delete_subscribers_hint1: "您確定真的要永久刪除所選的訂閱者嗎?"
|
delete_subscribers_hint1: "您確定真的要永久刪除所選的訂閱者嗎?"
|
||||||
delete_subscribers_hint: "點選『新增』按鈕選擇訂閱者"
|
delete_subscribers_hint: "點選『新增』按鈕選擇訂閱者"
|
||||||
|
|
Loading…
Reference in New Issue