Authored by 陈峰

Merge branch 'feature/staticPreload' into 'master'

Feature/static preload



See merge request !44
const Router = require('koa-router');
const _ = require('lodash');
const md5 = require('md5');
const stream = require('stream');
const CDNCONFIG = require('../../../config/cdn_config');
let r = new Router();
const manifestPath = 'client/precache/statics/manifest.json';
const client = {
index: async(ctx, next) => {
await ctx.render('action/client-precache', {
manifestPath
});
},
save: async(ctx, next) => {
let files = ctx.request.body.files;
let lastRevision = ctx.request.body.lastRevision;
let trimFiles = [];
_.forEach(files, val => {
trimFiles.push(_.trim(val));
});
trimFiles = _.compact(_.uniq(trimFiles));
let revision = md5(trimFiles.join(','));
if (revision === lastRevision) {
return ctx.body = {
code: 400,
message: '请修改后再保存'
};
}
let ste = new Buffer.from(JSON.stringify({
files: trimFiles,
revision
}));
const bufferStream = new stream.PassThrough();
let readable = bufferStream.end(new Buffer.from(JSON.stringify({
files: trimFiles,
revision
})));
let config = _.cloneDeep(CDNCONFIG.main);
_.assign(config, {
key: manifestPath
});
let qnMain = require('../../../lib/qiniu')(config);
let upResult = await qnMain.uploadAsync(readable, {key: manifestPath});
if (upResult && upResult.url) {
return ctx.body = {
code: 200,
message: '修改成功',
data: {
url: upResult.url
}
};
} else {
return ctx.body = {
code: 400,
message: '修改失败'
};
}
}
}
r.get('/client', client.index);
r.post('/client/save', client.save);
module.exports = r;
... ...
... ... @@ -11,6 +11,7 @@ const monitor = require('./actions/monitor');
const users = require('./actions/users');
const hotfix = require('./actions/hotfix');
const operationLog = require('./actions/operation_log');
const clientPrecache = require('./actions/client-precache');
const pageCache = require('./actions/page_cache');
const cdnCache = require('./actions/cdn_cache');
const productCache = require('./actions/product_cache');
... ... @@ -57,6 +58,7 @@ module.exports = function(app) {
base.use('/monitor', monitor.routes(), monitor.allowedMethods());
base.use('/users', users.routes(), users.allowedMethods());
// base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods());
base.use('/precache', clientPrecache.routes(), clientPrecache.allowedMethods());
base.use('/operation', operationLog.routes(), operationLog.allowedMethods());
base.use('/check', checkcode.routes(), checkcode.allowedMethods());
base.use('/page_cache', pageCache.routes(), pageCache.allowedMethods());
... ...
<style type="text/css">
.panel-body-container {
position: relative;
min-height: 100px;
}
.edit-area {
width: 100%;
position: absolute;
left: 0;
top: 0;
bottom: 0;
}
.edit-area > textarea {
width: 100%;
height: 100%;
}
.pannel-option > * {
margin-left: 10px;
}
.pannel-option .save,
.pannel-option .cancle {
display: none;
}
.pannel-option.pannel-edit .edit {
display: none;
}
.pannel-option.pannel-edit .cancle,
.pannel-option.pannel-edit .save {
display: inline;
}
.edit-area {
display: none;
}
</style>
<div class="pageheader">
<div class="media">
<div class="pageicon pull-left">
<i class="fa fa-th-list"></i>
</div>
<div class="media-body">
<ul class="breadcrumb">
<li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li>
<li><a href="/servers">Projects</a></li>
</ul>
<h4>客户端预加载清单</h4>
</div>
</div>
<!-- media -->
</div>
<div class="contentpanel task-panel" style="padding-bottom:0;">
<!-- pageheader -->
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right pannel-option">
<a href="javascript:;" class="tooltips edit">编辑</a>
<a href="javascript:;" class="tooltips save">保存</a>
<a href="javascript:;" class="tooltips cancle">取消</a>
</div>
<h4 class="panel-title">预加载清单</h4>
</div>
<div class="panel-body">
<div class="panel-body-container">
<div id="edit-area" class="edit-area">
<textarea id="textarea" class="form-control" pleaceholder="支持多条换行输入"></textarea>
</div>
<div id="static-list" class="static-list"></div>
</div>
</div>
</div>
</div>
<script>
var files = [];
var revision = ''
function resetManifest(list) {
files = list || [];
var h = '';
for (var i = 0; i < files.length; i++) {
h += '<p>' + files[i] + '</p>';
}
$('#static-list').html(h);
}
function getManifest(file) {
$.get(file + '?t=' + new Date().getTime(), function(res) {
if (res && res.files) {
resetManifest(res.files);
revision = res.revision;
};
});
}
function clearCache(url) {
var cloud = ['qiniu', 'qcloud', 'aliyun'];
cloud.forEach(function(val) {
$.post('/cdn_cache/clear', {
query_uri: url,
object_type: 'File',
cloud: val
});
});
}
$('.pannel-option').on('click', '.tooltips', function() {
var $this = $(this),
$par = $this.parent(),
$edit = $('#edit-area');
$par.toggleClass('pannel-edit');
if ($this.hasClass('save')) {
var _files = $('#textarea').val().split('\n');
$.post('/precache/client/save', {
files: _files,
lastRevision: revision
}, function(res) {
if (res.code === 200) {
getManifest(res.data.url);
clearCache(res.data.url);
$edit.hide();
} else {
$par.addClass('pannel-edit');
alert(res.message || '保存失败');
}
});
} else if ($this.hasClass('edit')) {
$('#textarea').val(files.join('\n'));
$edit.show();
} else {
$edit.hide();
}
});
getManifest('//cdn.yoho.cn/{{manifestPath}}');
</script>
... ...
... ... @@ -26,6 +26,10 @@ const normalMenus = [
title: 'Memcached',
link: '/api_cache',
isClassic: true
}, {
title: '客户端预加载',
link: '/precache/client',
isClassic: true
}]
},
{
... ...