流量池修改

This commit is contained in:
邓皓元 2019-04-16 16:10:15 +08:00
parent 368d0d2567
commit 1f4841bf4c
9 changed files with 149 additions and 110 deletions

View File

@ -251,7 +251,7 @@ class FlowPoolController extends Controller
$setting['cards'] = $chunk;
$news = $cards[$package_id] ?? 0 - array_sum(array_pluck($setting['cards'], 'counts'));
$news = ($cards[$package_id] ?? 0) - array_sum(array_pluck($setting['cards'], 'counts'));
$setting['news'] = $news < 0 ? 0 : $news;

View File

@ -151,9 +151,7 @@ class PropertyService extends Service
PropertySetting::upsert($data, 'name');
$this->propertySettingRepository->forgetCached();
$settings = $this->propertySettingRepository->getAll();
$settings = $this->propertySettingRepository->getAll(true);
return true;
}

View File

@ -105,7 +105,7 @@ class CreateFlowPoolTables extends Migration
});
}
DB::unprepared(File::get(__DIR__ . '/create_flow_pool_settings_view.pgsql'));
DB::unprepared(File::get(__DIR__ . '/create_flow_pool_func.pgsql'));
}
/**

View File

@ -0,0 +1,58 @@
CREATE OR REPLACE FUNCTION GET_FLOW_POOL_MONTH_STAT(INT)
RETURNS TABLE
(
pool_id INT,
members NUMERIC,
minimum_flows NUMERIC,
minimum_price NUMERIC,
excess_flows NUMERIC,
excess_price NUMERIC
)
AS
$$
DECLARE
query TEXT;
BEGIN
query := 'WITH settings AS (
SELECT pool_id,
json_array_elements(minimum_settings::json) ->> ''package_id'' AS package_id,
json_array_elements(minimum_settings::json) ->> ''flows'' AS flows,
json_array_elements(minimum_settings::json) ->> ''price'' AS price,
gradient * pow(1024, gradient_unit) as gradient,
gradient_price / pow(1024, gradient_unit) as gradient_price,
start_at,
end_at
FROM virtual_flow_pool_settings
), pool_package AS (
SELECT virtual_flow_pool_months.pool_id,
virtual_flow_pool_months.package_id,
COUNT(*) as members,
SUM(settings.flows::NUMERIC) AS minimum_flows,
SUM(settings.price::NUMERIC) AS minimum_price,
SUM(virtual_flow_pool_months.mebibyte) AS total_flows,
AVG(settings.gradient::int) AS gradient,
AVG(settings.gradient_price::NUMERIC) AS gradient_price
FROM virtual_flow_pool_months
JOIN settings ON
settings.package_id::int = virtual_flow_pool_months.package_id AND
settings.pool_id::int = virtual_flow_pool_months.pool_id AND
settings.start_at <= (overlay($1::text placing ''-'' from 5 for 0) || ''-01 00:00:00'')::TIMESTAMP AND
(settings.end_at >= (overlay($1::text placing ''-'' from 5 for 0) || ''-01 23:59:59'')::TIMESTAMP OR settings.end_at IS NULL)
WHERE virtual_flow_pool_months.month = $1
GROUP BY virtual_flow_pool_months.pool_id, virtual_flow_pool_months.package_id
)
SELECT pool_id,
SUM(members) as members,
SUM(minimum_flows) as minimum_flows,
SUM(minimum_price) as minimum_price,
CASE WHEN SUM(total_flows) - SUM(minimum_flows) < 0 THEN 0 ELSE SUM(total_flows) - SUM(minimum_flows) END as excess_flows,
CEIL((CASE WHEN SUM(total_flows) - SUM(minimum_flows) < 0 THEN 0 ELSE SUM(total_flows) - SUM(minimum_flows) END)/AVG(gradient))*AVG(gradient)*AVG(gradient_price) as excess_price
FROM pool_package AS t GROUP BY pool_id
';
RETURN QUERY EXECUTE query USING $1;
END;
$$ LANGUAGE plpgsql;

View File

@ -1,64 +0,0 @@
CREATE OR REPLACE VIEW virtual_flow_pool_settings_view AS
SELECT pool_id,
json_array_elements(minimum_settings::json) ->> 'package_id' AS package_id,
json_array_elements(minimum_settings::json) ->> 'flows' AS flows,
json_array_elements(minimum_settings::json) ->> 'price' AS price,
gradient * pow(1024, gradient_unit) as gradient,
gradient_price / pow(1024, gradient_unit) as gradient_price,
start_at,
end_at
FROM virtual_flow_pool_settings;
CREATE OR REPLACE FUNCTION GET_FLOW_POOL_MONTH_STAT(INT)
RETURNS TABLE
(
pool_id INT,
members NUMERIC,
minimum_flows NUMERIC,
minimum_price NUMERIC,
excess_flows NUMERIC,
excess_price NUMERIC
)
AS
$$
DECLARE
query TEXT;
BEGIN
query := 'SELECT virtual_flow_pool_months.pool_id,
virtual_flow_pool_months.package_id,
COUNT(*) as members,
SUM(virtual_flow_pool_settings_view.flows::NUMERIC) AS minimum_flows,
SUM(virtual_flow_pool_settings_view.price::NUMERIC) AS minimum_price,
CASE WHEN SUM(virtual_flow_pool_months.mebibyte) - SUM(virtual_flow_pool_settings_view.flows::NUMERIC) < 0 THEN 0
ELSE SUM(virtual_flow_pool_months.mebibyte) - SUM(virtual_flow_pool_settings_view.flows::NUMERIC) END AS excess_flows,
AVG(virtual_flow_pool_settings_view.gradient::int) AS gradient,
AVG(virtual_flow_pool_settings_view.gradient_price::NUMERIC) AS gradient_price
FROM virtual_flow_pool_months
JOIN virtual_flow_pool_settings_view ON
virtual_flow_pool_settings_view.package_id::int = virtual_flow_pool_months.package_id AND
virtual_flow_pool_settings_view.pool_id::int = virtual_flow_pool_months.pool_id AND
virtual_flow_pool_settings_view.start_at <=
(overlay($1::text placing ''-'' from 5 for 0) || ''-01 00:00:00'')::TIMESTAMP AND
(virtual_flow_pool_settings_view.end_at >=
(overlay($1::text placing ''-'' from 5 for 0) || ''-01 23:59:59'')::TIMESTAMP OR
virtual_flow_pool_settings_view.end_at IS NULL)
WHERE virtual_flow_pool_months.month = $1
GROUP BY virtual_flow_pool_months.pool_id, virtual_flow_pool_months.package_id
';
query := 'SELECT pool_id,
SUM(members) as members,
SUM(minimum_flows) as minimum_flows,
SUM(minimum_price) as minimum_price,
SUM(excess_flows) as excess_flows,
CEIL(SUM(excess_flows)/AVG(gradient))*AVG(gradient)*AVG(gradient_price) as excess_price
FROM (' || query || ') AS t GROUP BY pool_id';
RAISE NOTICE '%s', query;
RETURN QUERY EXECUTE query USING $1;
END;
$$ LANGUAGE plpgsql;

View File

@ -1,5 +1,5 @@
import * as API from 'api/virtual/properties';
import draggable from 'vuedraggable';
import * as API from "api/virtual/properties";
import draggable from "vuedraggable";
export default {
props: {
@ -20,7 +20,7 @@ export default {
my_show: false,
loading: false,
settings: {},
selectedTab: '',
selectedTab: "",
completePackagesFilter: [],
dragOptions: {
animation: 0,
@ -35,7 +35,7 @@ export default {
return this.settings.package ? this.settings.package : {};
},
set(value) {
console.log('packages', value);
console.log("packages", value);
}
},
products: {
@ -88,37 +88,46 @@ export default {
methods: {
ok() {
this.loading = true;
API.settingsStore({ data: this.settings }).then(res => {
this.loading = false;
if (res.code == 0) {
this.$Message.success('修改成功');
this.clear();
this.$emit('store-success', this.settings);
}
}).catch(err => {
this.loading = false;
});
API.settingsStore({ data: this.settings })
.then(res => {
this.loading = false;
if (res.code == 0) {
this.$Message.success("修改成功");
this.clear();
this.$emit("store-success", this.settings);
}
})
.catch(err => {
this.loading = false;
});
},
visibleChange(bool) {
if (!bool) {
this.$emit('update:show', false);
this.$emit("update:show", false);
}
},
clear() {
this.my_show = false;
},
handelRemove(key, value) {
console.log(key, value);
this.$Modal.confirm({
title: '提示',
content: '已设置的属性值不会因删除改变,确认是否还要删除',
title: "提示",
content: "已设置的属性值不会因删除改变,确认是否还要删除",
onOk: () => {
let node = key === 'package' ? this.settings[key][this.selectedTab] : this.settings[key];
let node =
key === "package"
? this.settings[key][this.selectedTab]
: this.settings[key];
let index = node.indexOf(value);
node.splice(index, 1);
if (key === 'package') {
if (key === "package") {
this.settings[key][this.selectedTab] = node;
this.settings.product.splice(this.settings.product.indexOf(value), 1);
this.settings.product.splice(
this.settings.product.indexOf(value),
1
);
} else {
this.settings[key] = node;
}
@ -126,32 +135,35 @@ export default {
});
},
handleAdd(key) {
let value = '';
let node = key === 'package' ? this.settings[key][this.selectedTab] : this.settings[key];
let value = "";
let node =
key === "package"
? this.settings[key][this.selectedTab]
: this.settings[key];
this.$Modal.confirm({
render: (h) => {
return h('Input', {
render: h => {
return h("Input", {
props: {
value: value,
autofocus: true,
placeholder: '请输入名称'
placeholder: "请输入名称"
},
on: {
input: (val) => {
input: val => {
value = val;
}
}
});
},
onOk: () => {
if (value === '') {
return this.$Message.error('名称不能为空');
if (value === "") {
return this.$Message.error("名称不能为空");
}
node.push(value);
if (key === 'package') {
if (key === "package") {
this.settings[key][this.selectedTab] = node;
this.settings.product.push(value);
} else {
@ -160,12 +172,30 @@ export default {
}
});
},
handleRemovePackageType(val) {
handleRemovePackageType(key) {
let value = this.settings.package_type[key];
return new Promise(resolve => {
this.$Modal.confirm({
title: '提示',
content: '删除套餐分类将同时删除分类及分类下的产品,但已设置的属性值不会因删除改变,请谨慎操作',
title: "提示",
content:
"删除套餐分类将同时删除分类及分类下的产品,但已设置的属性值不会因删除改变,请谨慎操作",
onOk: () => {
let products = this.settings.package[value];
if (products) {
for (let i = 0; i < products.length; i++) {
const element = products[i];
let index = this.settings.product.indexOf(element);
if (index !== -1) {
this.settings.product.splice(index, 1);
}
}
}
this.settings.package_type.splice(key, 1);
delete this.settings.package[value];
resolve(true);
},
onCannel: () => {
@ -175,29 +205,31 @@ export default {
});
},
handleAddPackageType() {
let value = '';
let value = "";
this.$Modal.confirm({
render: (h) => {
return h('Input', {
render: h => {
return h("Input", {
props: {
value: value,
autofocus: true,
placeholder: '请输入套餐分类名称'
placeholder: "请输入套餐分类名称"
},
on: {
input: (val) => {
input: val => {
value = val;
}
}
});
},
onOk: () => {
if (value === '') {
return this.$Message.error('名称不能为空');
if (value === "") {
return this.$Message.error("名称不能为空");
}
let package_type = this.settings.package_type ? this.settings.package_type : [];
let package_type = this.settings.package_type
? this.settings.package_type
: [];
package_type.push(value);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-2cc41ab2.bcb99373.css rel=prefetch><link href=/css/chunk-996b1e80.5cadf3d0.css rel=prefetch><link href=/js/chunk-00ae0766.d130b440.js rel=prefetch><link href=/js/chunk-07a274ec.55e1b3b0.js rel=prefetch><link href=/js/chunk-2cc41ab2.bec32fc2.js rel=prefetch><link href=/js/chunk-996b1e80.92847c4e.js rel=prefetch><link href=/css/app.8e379248.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.8955fa7e.js rel=preload as=script><link href=/js/chunk-vendors.ed6443e8.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.8e379248.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ed6443e8.js></script><script src=/js/app.8955fa7e.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-2cc41ab2.bcb99373.css rel=prefetch><link href=/css/chunk-996b1e80.5cadf3d0.css rel=prefetch><link href=/js/chunk-00ae0766.d130b440.js rel=prefetch><link href=/js/chunk-07a274ec.55e1b3b0.js rel=prefetch><link href=/js/chunk-2cc41ab2.a9a06de3.js rel=prefetch><link href=/js/chunk-996b1e80.92847c4e.js rel=prefetch><link href=/css/app.8e379248.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.d09afebb.js rel=preload as=script><link href=/js/chunk-vendors.ed6443e8.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.8e379248.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ed6443e8.js></script><script src=/js/app.d09afebb.js></script></body></html>