Commit a195524c authored by ZhangKai's avatar ZhangKai

汽车安全测试知识库-前端代码初步提交

parent 26fb3919
// https://d3js.org/d3-hierarchy/ v2.0.0 Copyright 2020 Mike Bostock
!function (n, r) {
"object" == typeof exports && "undefined" != typeof module ? r(exports) : "function" == typeof define && define.amd ? define(["exports"], r) : r((n = n || self).d3 = n.d3 || {})
}(this, function (n) {
"use strict";
function r(n, r) {
return n.parent === r.parent ? 1 : 2
}
function t(n, r) {
return n + r.x
}
function e(n, r) {
return Math.max(n, r.y)
}
function i(n) {
var r = 0, t = n.children, e = t && t.length;
if (e) for (; --e >= 0;) r += t[e].value; else r = 1;
n.value = r
}
function u(n, r) {
n instanceof Map ? (n = [void 0, n], void 0 === r && (r = a)) : void 0 === r && (r = o);
for (var t, e, i, u, f, h = new Node(n), l = [h]; t = l.pop();) if ((i = r(t.data)) && (f = (i = Array.from(i)).length)) for (t.children = i, u = f - 1; u >= 0; --u) l.push(e = i[u] = new Node(i[u])), e.parent = t, e.depth = t.depth + 1;
return h.eachBefore(c)
}
function o(n) {
return n.children
}
function a(n) {
return Array.isArray(n) ? n[1] : null
}
function f(n) {
void 0 !== n.data.value && (n.value = n.data.value), n.data = n.data.data
}
function c(n) {
var r = 0;
do {
n.height = r
} while ((n = n.parent) && n.height < ++r)
}
function Node(n) {
this.data = n, this.depth = this.height = 0, this.parent = null
}
function h(n) {
for (var r, t, e = 0, i = (n = function (n) {
for (var r, t, e = n.length; e;) t = Math.random() * e-- | 0, r = n[e], n[e] = n[t], n[t] = r;
return n
}(Array.from(n))).length, u = []; e < i;) r = n[e], t && d(t, r) ? ++e : (t = v(u = l(u, r)), e = 0);
return t
}
function l(n, r) {
var t, e;
if (s(r, n)) return [r];
for (t = 0; t < n.length; ++t) if (p(r, n[t]) && s(x(n[t], r), n)) return [n[t], r];
for (t = 0; t < n.length - 1; ++t) for (e = t + 1; e < n.length; ++e) if (p(x(n[t], n[e]), r) && p(x(n[t], r), n[e]) && p(x(n[e], r), n[t]) && s(y(n[t], n[e], r), n)) return [n[t], n[e], r];
throw new Error
}
function p(n, r) {
var t = n.r - r.r, e = r.x - n.x, i = r.y - n.y;
return t < 0 || t * t < e * e + i * i
}
function d(n, r) {
var t = n.r - r.r + 1e-9 * Math.max(n.r, r.r, 1), e = r.x - n.x, i = r.y - n.y;
return t > 0 && t * t > e * e + i * i
}
function s(n, r) {
for (var t = 0; t < r.length; ++t) if (!d(n, r[t])) return !1;
return !0
}
function v(n) {
switch (n.length) {
case 1:
return {x: (r = n[0]).x, y: r.y, r: r.r};
case 2:
return x(n[0], n[1]);
case 3:
return y(n[0], n[1], n[2])
}
var r
}
function x(n, r) {
var t = n.x, e = n.y, i = n.r, u = r.x, o = r.y, a = r.r, f = u - t, c = o - e, h = a - i,
l = Math.sqrt(f * f + c * c);
return {x: (t + u + f / l * h) / 2, y: (e + o + c / l * h) / 2, r: (l + i + a) / 2}
}
function y(n, r, t) {
var e = n.x, i = n.y, u = n.r, o = r.x, a = r.y, f = r.r, c = t.x, h = t.y, l = t.r, p = e - o, d = e - c,
s = i - a, v = i - h, x = f - u, y = l - u, g = e * e + i * i - u * u, m = g - o * o - a * a + f * f,
w = g - c * c - h * h + l * l, _ = d * s - p * v, M = (s * w - v * m) / (2 * _) - e, z = (v * x - s * y) / _,
B = (d * m - p * w) / (2 * _) - i, A = (p * y - d * x) / _, q = z * z + A * A - 1, b = 2 * (u + M * z + B * A),
E = M * M + B * B - u * u, S = -(q ? (b + Math.sqrt(b * b - 4 * q * E)) / (2 * q) : E / b);
return {x: e + M + z * S, y: i + B + A * S, r: S}
}
function g(n, r, t) {
var e, i, u, o, a = n.x - r.x, f = n.y - r.y, c = a * a + f * f;
c ? (i = r.r + t.r, i *= i, o = n.r + t.r, i > (o *= o) ? (e = (c + o - i) / (2 * c), u = Math.sqrt(Math.max(0, o / c - e * e)), t.x = n.x - e * a - u * f, t.y = n.y - e * f + u * a) : (e = (c + i - o) / (2 * c), u = Math.sqrt(Math.max(0, i / c - e * e)), t.x = r.x + e * a - u * f, t.y = r.y + e * f + u * a)) : (t.x = r.x + t.r, t.y = r.y)
}
function m(n, r) {
var t = n.r + r.r - 1e-6, e = r.x - n.x, i = r.y - n.y;
return t > 0 && t * t > e * e + i * i
}
function w(n) {
var r = n._, t = n.next._, e = r.r + t.r, i = (r.x * t.r + t.x * r.r) / e, u = (r.y * t.r + t.y * r.r) / e;
return i * i + u * u
}
function _(n) {
this._ = n, this.next = null, this.previous = null
}
function M(n) {
if (!(u = (r = n, n = "object" == typeof r && "length" in r ? r : Array.from(r)).length)) return 0;
var r, t, e, i, u, o, a, f, c, l, p, d;
if ((t = n[0]).x = 0, t.y = 0, !(u > 1)) return t.r;
if (e = n[1], t.x = -e.r, e.x = t.r, e.y = 0, !(u > 2)) return t.r + e.r;
g(e, t, i = n[2]), t = new _(t), e = new _(e), i = new _(i), t.next = i.previous = e, e.next = t.previous = i, i.next = e.previous = t;
n:for (f = 3; f < u; ++f) {
g(t._, e._, i = n[f]), i = new _(i), c = e.next, l = t.previous, p = e._.r, d = t._.r;
do {
if (p <= d) {
if (m(c._, i._)) {
e = c, t.next = e, e.previous = t, --f;
continue n
}
p += c._.r, c = c.next
} else {
if (m(l._, i._)) {
(t = l).next = e, e.previous = t, --f;
continue n
}
d += l._.r, l = l.previous
}
} while (c !== l.next);
for (i.previous = t, i.next = e, t.next = e.previous = e = i, o = w(t); (i = i.next) !== e;) (a = w(i)) < o && (t = i, o = a);
e = t.next
}
for (t = [e._], i = e; (i = i.next) !== e;) t.push(i._);
for (i = h(t), f = 0; f < u; ++f) (t = n[f]).x -= i.x, t.y -= i.y;
return i.r
}
function z(n) {
return null == n ? null : B(n)
}
function B(n) {
if ("function" != typeof n) throw new Error;
return n
}
function A() {
return 0
}
function q(n) {
return function () {
return n
}
}
function b(n) {
return Math.sqrt(n.value)
}
function E(n) {
return function (r) {
r.children || (r.r = Math.max(0, +n(r) || 0))
}
}
function S(n, r) {
return function (t) {
if (e = t.children) {
var e, i, u, o = e.length, a = n(t) * r || 0;
if (a) for (i = 0; i < o; ++i) e[i].r += a;
if (u = M(e), a) for (i = 0; i < o; ++i) e[i].r -= a;
t.r = u + a
}
}
}
function k(n) {
return function (r) {
var t = r.parent;
r.r *= n, t && (r.x = t.x + n * r.x, r.y = t.y + n * r.y)
}
}
function I(n) {
n.x0 = Math.round(n.x0), n.y0 = Math.round(n.y0), n.x1 = Math.round(n.x1), n.y1 = Math.round(n.y1)
}
function j(n, r, t, e, i) {
for (var u, o = n.children, a = -1, f = o.length, c = n.value && (e - r) / n.value; ++a < f;) (u = o[a]).y0 = t, u.y1 = i, u.x0 = r, u.x1 = r += u.value * c
}
Node.prototype = u.prototype = {
constructor: Node, count: function () {
return this.eachAfter(i)
}, each: function (n, r) {
let t = -1;
for (const e of this) n.call(r, e, ++t, this);
return this
}, eachAfter: function (n, r) {
for (var t, e, i, u = this, o = [u], a = [], f = -1; u = o.pop();) if (a.push(u), t = u.children) for (e = 0, i = t.length; e < i; ++e) o.push(t[e]);
for (; u = a.pop();) n.call(r, u, ++f, this);
return this
}, eachBefore: function (n, r) {
for (var t, e, i = this, u = [i], o = -1; i = u.pop();) if (n.call(r, i, ++o, this), t = i.children) for (e = t.length - 1; e >= 0; --e) u.push(t[e]);
return this
}, find: function (n, r) {
let t = -1;
for (const e of this) if (n.call(r, e, ++t, this)) return e
}, sum: function (n) {
return this.eachAfter(function (r) {
for (var t = +n(r.data) || 0, e = r.children, i = e && e.length; --i >= 0;) t += e[i].value;
r.value = t
})
}, sort: function (n) {
return this.eachBefore(function (r) {
r.children && r.children.sort(n)
})
}, path: function (n) {
for (var r = this, t = function (n, r) {
if (n === r) return n;
var t = n.ancestors(), e = r.ancestors(), i = null;
for (n = t.pop(), r = e.pop(); n === r;) i = n, n = t.pop(), r = e.pop();
return i
}(r, n), e = [r]; r !== t;) r = r.parent, e.push(r);
for (var i = e.length; n !== t;) e.splice(i, 0, n), n = n.parent;
return e
}, ancestors: function () {
for (var n = this, r = [n]; n = n.parent;) r.push(n);
return r
}, descendants: function () {
return Array.from(this)
}, leaves: function () {
var n = [];
return this.eachBefore(function (r) {
r.children || n.push(r)
}), n
}, links: function () {
var n = this, r = [];
return n.each(function (t) {
t !== n && r.push({source: t.parent, target: t})
}), r
}, copy: function () {
return u(this).eachBefore(f)
}, [Symbol.iterator]: function* () {
var n, r, t, e, i = this, u = [i];
do {
for (n = u.reverse(), u = []; i = n.pop();) if (yield i, r = i.children) for (t = 0, e = r.length; t < e; ++t) u.push(r[t])
} while (u.length)
}
};
var O = {depth: -1}, R = {};
function T(n) {
return n.id
}
function D(n) {
return n.parentId
}
function L(n, r) {
return n.parent === r.parent ? 1 : 2
}
function P(n) {
var r = n.children;
return r ? r[0] : n.t
}
function C(n) {
var r = n.children;
return r ? r[r.length - 1] : n.t
}
function F(n, r, t) {
var e = t / (r.i - n.i);
r.c -= e, r.s += t, n.c += e, r.z += t, r.m += t
}
function G(n, r, t) {
return n.a.parent === r.parent ? n.a : t
}
function H(n, r) {
this._ = n, this.parent = null, this.children = null, this.A = null, this.a = this, this.z = 0, this.m = 0, this.c = 0, this.s = 0, this.t = null, this.i = r
}
function J(n, r, t, e, i) {
for (var u, o = n.children, a = -1, f = o.length, c = n.value && (i - t) / n.value; ++a < f;) (u = o[a]).x0 = r, u.x1 = e, u.y0 = t, u.y1 = t += u.value * c
}
H.prototype = Object.create(Node.prototype);
var K = (1 + Math.sqrt(5)) / 2;
function N(n, r, t, e, i, u) {
for (var o, a, f, c, h, l, p, d, s, v, x, y = [], g = r.children, m = 0, w = 0, _ = g.length, M = r.value; m < _;) {
f = i - t, c = u - e;
do {
h = g[w++].value
} while (!h && w < _);
for (l = p = h, x = h * h * (v = Math.max(c / f, f / c) / (M * n)), s = Math.max(p / x, x / l); w < _; ++w) {
if (h += a = g[w].value, a < l && (l = a), a > p && (p = a), x = h * h * v, (d = Math.max(p / x, x / l)) > s) {
h -= a;
break
}
s = d
}
y.push(o = {
value: h,
dice: f < c,
children: g.slice(m, w)
}), o.dice ? j(o, t, e, i, M ? e += c * h / M : u) : J(o, t, e, M ? t += f * h / M : i, u), M -= h, m = w
}
return y
}
var Q = function n(r) {
function t(n, t, e, i, u) {
N(r, n, t, e, i, u)
}
return t.ratio = function (r) {
return n((r = +r) > 1 ? r : 1)
}, t
}(K);
var U = function n(r) {
function t(n, t, e, i, u) {
if ((o = n._squarify) && o.ratio === r) for (var o, a, f, c, h, l = -1, p = o.length, d = n.value; ++l < p;) {
for (f = (a = o[l]).children, c = a.value = 0, h = f.length; c < h; ++c) a.value += f[c].value;
a.dice ? j(a, t, e, i, d ? e += (u - e) * a.value / d : u) : J(a, t, e, d ? t += (i - t) * a.value / d : i, u), d -= a.value
} else n._squarify = o = N(r, n, t, e, i, u), o.ratio = r
}
return t.ratio = function (r) {
return n((r = +r) > 1 ? r : 1)
}, t
}(K);
n.cluster = function () {
var n = r, i = 1, u = 1, o = !1;
function a(r) {
var a, f = 0;
r.eachAfter(function (r) {
var i = r.children;
i ? (r.x = function (n) {
return n.reduce(t, 0) / n.length
}(i), r.y = function (n) {
return 1 + n.reduce(e, 0)
}(i)) : (r.x = a ? f += n(r, a) : 0, r.y = 0, a = r)
});
var c = function (n) {
for (var r; r = n.children;) n = r[0];
return n
}(r), h = function (n) {
for (var r; r = n.children;) n = r[r.length - 1];
return n
}(r), l = c.x - n(c, h) / 2, p = h.x + n(h, c) / 2;
return r.eachAfter(o ? function (n) {
n.x = (n.x - r.x) * i, n.y = (r.y - n.y) * u
} : function (n) {
n.x = (n.x - l) / (p - l) * i, n.y = (1 - (r.y ? n.y / r.y : 1)) * u
})
}
return a.separation = function (r) {
return arguments.length ? (n = r, a) : n
}, a.size = function (n) {
return arguments.length ? (o = !1, i = +n[0], u = +n[1], a) : o ? null : [i, u]
}, a.nodeSize = function (n) {
return arguments.length ? (o = !0, i = +n[0], u = +n[1], a) : o ? [i, u] : null
}, a
}, n.hierarchy = u, n.pack = function () {
var n = null, r = 1, t = 1, e = A;
function i(i) {
return i.x = r / 2, i.y = t / 2, n ? i.eachBefore(E(n)).eachAfter(S(e, .5)).eachBefore(k(1)) : i.eachBefore(E(b)).eachAfter(S(A, 1)).eachAfter(S(e, i.r / Math.min(r, t))).eachBefore(k(Math.min(r, t) / (2 * i.r))), i
}
return i.radius = function (r) {
return arguments.length ? (n = z(r), i) : n
}, i.size = function (n) {
return arguments.length ? (r = +n[0], t = +n[1], i) : [r, t]
}, i.padding = function (n) {
return arguments.length ? (e = "function" == typeof n ? n : q(+n), i) : e
}, i
}, n.packEnclose = h, n.packSiblings = function (n) {
return M(n), n
}, n.partition = function () {
var n = 1, r = 1, t = 0, e = !1;
function i(i) {
var u = i.height + 1;
return i.x0 = i.y0 = t, i.x1 = n, i.y1 = r / u, i.eachBefore(function (n, r) {
return function (e) {
e.children && j(e, e.x0, n * (e.depth + 1) / r, e.x1, n * (e.depth + 2) / r);
var i = e.x0, u = e.y0, o = e.x1 - t, a = e.y1 - t;
o < i && (i = o = (i + o) / 2), a < u && (u = a = (u + a) / 2), e.x0 = i, e.y0 = u, e.x1 = o, e.y1 = a
}
}(r, u)), e && i.eachBefore(I), i
}
return i.round = function (n) {
return arguments.length ? (e = !!n, i) : e
}, i.size = function (t) {
return arguments.length ? (n = +t[0], r = +t[1], i) : [n, r]
}, i.padding = function (n) {
return arguments.length ? (t = +n, i) : t
}, i
}, n.stratify = function () {
var n = T, r = D;
function t(t) {
var e, i, u, o, a, f, h, l = Array.from(t), p = l.length, d = new Map;
for (i = 0; i < p; ++i) e = l[i], a = l[i] = new Node(e), null != (f = n(e, i, t)) && (f += "") && (h = a.id = f, d.set(h, d.has(h) ? R : a)), null != (f = r(e, i, t)) && (f += "") && (a.parent = f);
for (i = 0; i < p; ++i) if (f = (a = l[i]).parent) {
if (!(o = d.get(f))) throw new Error("missing: " + f);
if (o === R) throw new Error("ambiguous: " + f);
o.children ? o.children.push(a) : o.children = [a], a.parent = o
} else {
if (u) throw new Error("multiple roots");
u = a
}
if (!u) throw new Error("no root");
if (u.parent = O, u.eachBefore(function (n) {
n.depth = n.parent.depth + 1, --p
}).eachBefore(c), u.parent = null, p > 0) throw new Error("cycle");
return u
}
return t.id = function (r) {
return arguments.length ? (n = B(r), t) : n
}, t.parentId = function (n) {
return arguments.length ? (r = B(n), t) : r
}, t
}, n.tree = function () {
var n = L, r = 1, t = 1, e = null;
function i(i) {
var f = function (n) {
for (var r, t, e, i, u, o = new H(n, 0), a = [o]; r = a.pop();) if (e = r._.children) for (r.children = new Array(u = e.length), i = u - 1; i >= 0; --i) a.push(t = r.children[i] = new H(e[i], i)), t.parent = r;
return (o.parent = new H(null, 0)).children = [o], o
}(i);
if (f.eachAfter(u), f.parent.m = -f.z, f.eachBefore(o), e) i.eachBefore(a); else {
var c = i, h = i, l = i;
i.eachBefore(function (n) {
n.x < c.x && (c = n), n.x > h.x && (h = n), n.depth > l.depth && (l = n)
});
var p = c === h ? 1 : n(c, h) / 2, d = p - c.x, s = r / (h.x + p + d), v = t / (l.depth || 1);
i.eachBefore(function (n) {
n.x = (n.x + d) * s, n.y = n.depth * v
})
}
return i
}
function u(r) {
var t = r.children, e = r.parent.children, i = r.i ? e[r.i - 1] : null;
if (t) {
!function (n) {
for (var r, t = 0, e = 0, i = n.children, u = i.length; --u >= 0;) (r = i[u]).z += t, r.m += t, t += r.s + (e += r.c)
}(r);
var u = (t[0].z + t[t.length - 1].z) / 2;
i ? (r.z = i.z + n(r._, i._), r.m = r.z - u) : r.z = u
} else i && (r.z = i.z + n(r._, i._));
r.parent.A = function (r, t, e) {
if (t) {
for (var i, u = r, o = r, a = t, f = u.parent.children[0], c = u.m, h = o.m, l = a.m, p = f.m; a = C(a), u = P(u), a && u;) f = P(f), (o = C(o)).a = r, (i = a.z + l - u.z - c + n(a._, u._)) > 0 && (F(G(a, r, e), r, i), c += i, h += i), l += a.m, c += u.m, p += f.m, h += o.m;
a && !C(o) && (o.t = a, o.m += l - h), u && !P(f) && (f.t = u, f.m += c - p, e = r)
}
return e
}(r, i, r.parent.A || e[0])
}
function o(n) {
n._.x = n.z + n.parent.m, n.m += n.parent.m
}
function a(n) {
n.x *= r, n.y = n.depth * t
}
return i.separation = function (r) {
return arguments.length ? (n = r, i) : n
}, i.size = function (n) {
return arguments.length ? (e = !1, r = +n[0], t = +n[1], i) : e ? null : [r, t]
}, i.nodeSize = function (n) {
return arguments.length ? (e = !0, r = +n[0], t = +n[1], i) : e ? [r, t] : null
}, i
}, n.treemap = function () {
var n = Q, r = !1, t = 1, e = 1, i = [0], u = A, o = A, a = A, f = A, c = A;
function h(n) {
return n.x0 = n.y0 = 0, n.x1 = t, n.y1 = e, n.eachBefore(l), i = [0], r && n.eachBefore(I), n
}
function l(r) {
var t = i[r.depth], e = r.x0 + t, h = r.y0 + t, l = r.x1 - t, p = r.y1 - t;
l < e && (e = l = (e + l) / 2), p < h && (h = p = (h + p) / 2), r.x0 = e, r.y0 = h, r.x1 = l, r.y1 = p, r.children && (t = i[r.depth + 1] = u(r) / 2, e += c(r) - t, h += o(r) - t, (l -= a(r) - t) < e && (e = l = (e + l) / 2), (p -= f(r) - t) < h && (h = p = (h + p) / 2), n(r, e, h, l, p))
}
return h.round = function (n) {
return arguments.length ? (r = !!n, h) : r
}, h.size = function (n) {
return arguments.length ? (t = +n[0], e = +n[1], h) : [t, e]
}, h.tile = function (r) {
return arguments.length ? (n = B(r), h) : n
}, h.padding = function (n) {
return arguments.length ? h.paddingInner(n).paddingOuter(n) : h.paddingInner()
}, h.paddingInner = function (n) {
return arguments.length ? (u = "function" == typeof n ? n : q(+n), h) : u
}, h.paddingOuter = function (n) {
return arguments.length ? h.paddingTop(n).paddingRight(n).paddingBottom(n).paddingLeft(n) : h.paddingTop()
}, h.paddingTop = function (n) {
return arguments.length ? (o = "function" == typeof n ? n : q(+n), h) : o
}, h.paddingRight = function (n) {
return arguments.length ? (a = "function" == typeof n ? n : q(+n), h) : a
}, h.paddingBottom = function (n) {
return arguments.length ? (f = "function" == typeof n ? n : q(+n), h) : f
}, h.paddingLeft = function (n) {
return arguments.length ? (c = "function" == typeof n ? n : q(+n), h) : c
}, h
}, n.treemapBinary = function (n, r, t, e, i) {
var u, o, a = n.children, f = a.length, c = new Array(f + 1);
for (c[0] = o = u = 0; u < f; ++u) c[u + 1] = o += a[u].value;
!function n(r, t, e, i, u, o, f) {
if (r >= t - 1) {
var h = a[r];
return h.x0 = i, h.y0 = u, h.x1 = o, void (h.y1 = f)
}
for (var l = c[r], p = e / 2 + l, d = r + 1, s = t - 1; d < s;) {
var v = d + s >>> 1;
c[v] < p ? d = v + 1 : s = v
}
p - c[d - 1] < c[d] - p && r + 1 < d && --d;
var x = c[d] - l, y = e - x;
if (o - i > f - u) {
var g = e ? (i * y + o * x) / e : o;
n(r, d, x, i, u, g, f), n(d, t, y, g, u, o, f)
} else {
var m = e ? (u * y + f * x) / e : f;
n(r, d, x, i, u, o, m), n(d, t, y, i, m, o, f)
}
}(0, f, n.value, r, t, e, i)
}, n.treemapDice = j, n.treemapResquarify = U, n.treemapSlice = J, n.treemapSliceDice = function (n, r, t, e, i) {
(1 & n.depth ? J : j)(n, r, t, e, i)
}, n.treemapSquarify = Q, Object.defineProperty(n, "__esModule", {value: !0})
});
{
"硬件层": {
"$count": 5,
"内部有线接口": {
"$count": 1,
"JTAG": {
"$count": 1
},
"SPI": {
"$count": 1
},
"UART": {
"$count": 1
},
"SWD": {
"$count": 1
}
},
"外部有线接口": {
"$count": 1,
"有线以太网": {
"$count": 1
},
"CAN": {
"$count": 1
},
"LIN": {
"$count": 1
},
"FlexRay": {
"$count": 1
},
"USB": {
"$count": 1
},
"充电接口": {
"$count": 1
},
"SD卡": {
"$count": 1
},
"HDMI": {
"$count": 1
}
},
"无线协议": {
"$count": 1,
"Bluetooth": {
"$count": 1
},
"BLE": {
"$count": 1
},
"Wi-Fi": {
"$count": 1
},
"蜂窝网络": {
"$count": 1
},
"GNSS": {
"$count": 1
},
"UWB": {
"$count": 1
},
"NFC": {
"$count": 1
},
"RF": {
"$count": 1
},
"DSRC": {
"$count": 1
}
},
"芯片": {
"$count": 1,
"存储": {
"$count": 1
},
"计算": {
"$count": 1
},
"通信": {
"$count": 1
},
"能源": {
"$count": 1
},
"接口": {
"$count": 1
}
},
"硬件": {
"$count": 1,
"PCB": {
"$count": 1
},
"雷达": {
"$count": 1
},
"摄像头": {
"$count": 1
},
"显示屏": {
"$count": 1
},
"麦克风": {
"$count": 1
},
"扬声器": {
"$count": 1
}
}
},
"硬件抽象层": {
"$count": 3,
"安全": {
"$count": 1,
"安全启动": {
"$count": 1
},
"安全存储": {
"$count": 1
},
"安全加解密": {
"$count": 1
}
},
"驱动": {
"$count": 1,
"微控制器": {
"$count": 1
},
"存储器": {
"$count": 1
},
"通信": {
"$count": 1
},
"I/O": {
"$count": 1
},
"文件系统": {
"$count": 1
}
},
"协议栈": {
"$count": 1,
"USB": {
"$count": 1
},
"Bluetooth": {
"$count": 1
},
"Wi-Fi": {
"$count": 1
},
"BLE": {
"$count": 1
},
"蜂窝网络": {
"$count": 1
},
"GNSS": {
"$count": 1
},
"NearLink": {
"$count": 1
},
"NFC": {
"$count": 1
},
"UWB": {
"$count": 1
},
"CAN": {
"$count": 1
},
"有线以太网": {
"$count": 1
}
}
},
"服务层": {
"$count": 3,
"存储": {
"$count": 1,
"日志存储": {
"$count": 1
},
"数据存储": {
"$count": 1
},
"文件访问": {
"$count": 1
},
"GPU访问": {
"$count": 1
}
},
"通讯": {
"$count": 1,
"Bluetooth配置": {
"$count": 1
},
"WLAN配置": {
"$count": 1
},
"以太网通讯": {
"$count": 1
},
"CAN通讯": {
"$count": 1
},
"系统内通讯": {
"$count": 1
},
"Bluetooth通讯": {
"$count": 1
},
"其他": {
"$count": 1
}
},
"运行时": {
"$count": 1,
"复杂操作系统": {
"$count": 1
},
"实时操作系统": {
"$count": 1
}
}
},
"应用层": {
"$count": 2,
"其他": {
"$count": 1,
"浏览器": {
"$count": 1
},
"语音服务": {
"$count": 1
},
"远程更新": {
"$count": 1
},
"胎压监测": {
"$count": 1
},
"工程模式": {
"$count": 1
},
"车辆控制": {
"$count": 1
},
"投屏": {
"$count": 1
},
"远程车辆控制": {
"$count": 1
},
"多媒体服务": {
"$count": 1
},
"其他": {
"$count": 1
}
},
"系统": {
"$count": 1,
"调试服务": {
"$count": 1
},
"应用安装服务": {
"$count": 1
},
"SSH服务": {
"$count": 1
},
"FTP服务": {
"$count": 1
},
"诊断服务": {
"$count": 1
},
"OTA服务": {
"$count": 1
},
"ADB服务": {
"$count": 1
},
"其他": {
"$count": 1
},
"Telnet服务": {
"$count": 1
}
}
}
}
import request from '@/utils/request'
// 汽车安全测试知识库 首页接口
export function getIndexMapData() {
return request({
url: '',
method: 'get'
})
}
import request from '@/utils/request'
// 查询汽车安全测试对象列表
export function listObjects(query) {
return request({
url: '/cstobjects/list',
method: 'get',
params: query
})
}
// 查询汽车安全测试对象详细
export function getObjects(id) {
return request({
url: '/cstobjects/' + id,
method: 'get'
})
}
// 新增汽车安全测试对象
export function addObjects(data) {
return request({
url: '/cstobjects',
method: 'post',
data: data
})
}
// 修改汽车安全测试对象
export function updateObjects(data) {
return request({
url: '/cstobjects',
method: 'put',
data: data
})
}
// 删除汽车安全测试对象
export function delObjects(id) {
return request({
url: '/cstobjects/' + id,
method: 'delete'
})
}
import request from '@/utils/request'
// 查询汽车安全测试属性测试工具列表
export function listTools(query) {
return request({
url: '/cst/tools/list',
method: 'get',
params: query
})
}
// 查询汽车安全测试属性测试工具详细
export function getTools(id) {
return request({
url: '/cst/tools/' + id,
method: 'get'
})
}
// 新增汽车安全测试属性测试工具
export function addTools(data) {
return request({
url: '/cst/tools',
method: 'post',
data: data
})
}
// 修改汽车安全测试属性测试工具
export function updateTools(data) {
return request({
url: '/cst/tools',
method: 'put',
data: data
})
}
// 删除汽车安全测试属性测试工具
export function delTools(id) {
return request({
url: '/cst/tools/' + id,
method: 'delete'
})
}
<template>
<!-- 方法库管理 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 对象属性管理 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 舆情分析 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 舆情库拆解管理 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 舆情库管理 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 场景分析 -->
</template>
<script>
export default {
name: "index",
components: {},
data() {
return {
}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 场景库管理 -->
<div class="app-container">
<el-row :gutter="20">
<!-- 左侧树 -->
<el-col :span="4" :xs="24">
<div class="head-container">
<span>对象层级</span>
<i class="el-icon-s-tools"></i>
</div>
<div class="head-container">
<el-input
v-model="scenarioName"
placeholder="请输入场景名称"
clearable
size="small"
prefix-icon="el-icon-search"
/>
</div>
<div class="head-container">
<el-tree
ref="tree"
:data="scenarioTreeOptions"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:current-node-key="this.subScenario.id"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
>
<span slot-scope="{ node, data }" class="span-ellipsis"
:style="{ color: node.data.active ? '#409EFF' : '' }">
<el-tooltip
class="item"
effect="light"
:content="node.label || ''"
placement="top-start"
>
<span style="font-size: 14px">{{ node.label }}</span>
</el-tooltip>
</span>
</el-tree>
</div>
</el-col>
<!-- 左侧对象表格数据 -->
<el-col :span="20" :xs="24">
<el-form
v-show="showSearch"
ref="queryForm"
:model="queryParams"
size="small"
:inline="true"
>
<el-form-item label="工具类别:" prop="toolType">
<el-select
v-model="queryParams.toolType"
placeholder="请选择工具类别"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.cst_tool_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="工具名称:" prop="toolName">
<el-input
v-model="queryParams.toolName"
placeholder="请输入工具名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>查询
</el-button>
<el-button
icon="el-icon-refresh"
size="mini"
@click="resetQuery"
>重置
</el-button>
<el-button
size="mini"
@click="test"
>测试
</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="22">
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>{{ this.mainScenario.label }}</el-breadcrumb-item>
<el-breadcrumb-item>{{ this.subScenario.label }}</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
<el-col :span="2">
<el-button
v-hasPermi="['cst:tools:add']"
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增
</el-button
>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="objList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55px" align="center"/>
<el-table-column type="index" width="55px" label="序号" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
label="工具类别"
align="left"
prop="toolType"
:show-overflow-tooltip="true"
min-width="120px"
>
<template slot-scope="scope">
<dict-tag :options="dict.type.cst_tool_type" :value="scope.row.toolType"/>
</template>
</el-table-column>
<el-table-column
label="工具名称"
align="left"
prop="toolName"
min-width="150px"
/>
<el-table-column
label="工具地址"
align="left"
prop="toolAddress"
min-width="150px"
/>
<el-table-column
label="参考链接"
align="left"
prop="referenceLink"
min-width="150px"
/>
<el-table-column
label="附件"
align="left"
prop="attachmentName"
min-width="150px"
/>
<el-table-column
label="操作"
align="center"
min-width="150px"
class-name="small-padding fixed-width"
>
<template v-if="scope.row.roleId !== 1" slot-scope="scope">
<el-button
v-hasPermi="['cst:tools:edit']"
size="mini"
type="text"
style="color: #409eff"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>编辑
</el-button
>
<el-button
v-hasPermi="['cst:tools:remove']"
size="mini"
type="text"
style="color: #f56c6c"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除
</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:background="false"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
<!-- 添加或修改测试工具对话框 -->
<el-dialog
:title="title"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="open"
width="500px"
append-to-body
>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="工具类别:" prop="toolType">
<el-select
v-model="form.toolType"
v-if="isEdit"
style="width: 100%"
placeholder="请选择工具类别"
clearable>
<el-option
v-for="dict in dict.type.cst_tool_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="工具名称:" prop="toolName">
<el-input v-model="form.toolName" placeholder="请输入工具名称"/>
</el-form-item>
<el-form-item label="工具地址:" prop="toolAddress">
<el-input v-model="form.toolAddress" placeholder="请输入工具地址"/>
</el-form-item>
<el-form-item label="参考链接:" prop="referenceLink">
<el-input v-model="form.referenceLink" placeholder="请输入参考链接"/>
</el-form-item>
<el-form-item label="附件:">
<el-input
v-model="form.attachmentName"
type="textarea"
placeholder="上传文件"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {addTools, delTools, getTools, listTools, updateTools} from "@/views/cst-knowledge-base/api/tools";
export default {
name: "index",
dicts: ['cst_tool_type'],
components: {},
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 对象列表 表格数据
objList: [],
// 场景名称搜索值
scenarioName: null,
// 场景树选项
scenarioTreeOptions: [],
// 场景树选项原始数据
scenarioTreeOptionsOrigin: [],
// 主场景
mainScenario: {
id: null,
label: null,
children: []
},
// 子场景
subScenario: {
id: null,
label: null
},
// 默认树结构节点数据
defaultProps: {
children: 'children',
label: 'label'
},
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 弹出层对话框内容是否可编辑
isEdit: true,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
// 工具名称
toolName: null,
// 工具类别
toolType: null
},
// 表单参数
form: {
// 工具id
id: null,
// 工具名称
toolName: null,
// 工具类别
toolType: null,
// 工具地址
toolAddress: null,
// 参考链接
referenceLink: null,
// 附件名称
attachmentName: null,
// 附件文件类型
attachmentFileType: null,
// 附件存储路径
attachmentStoragePath: null,
// 工具说明
toolDeclaration: null,
// 备注
remark: null
},
// 表单校验
rules: {
toolName: [
{required: true, message: '工具名称不能为空', trigger: 'blur'}
],
toolType: [
{required: true, message: '工具类别不能为空', trigger: 'blur'}
],
toolAddress: [
{required: true, message: '工具地址不能为空', trigger: 'blur'}
],
referenceLink: [
{required: true, message: '参考链接不能为空', trigger: 'blur'}
],
attachmentName: [
{required: true, message: '附件不能为空', trigger: 'blur'}
]
}
}
},
watch: {
// 根据名称筛选场景
scenarioName(val) {
this.$refs.tree.filter(val)
}
},
created() {
// 获取左侧场景树数据
this.getScenarioTree()
// 获取表格数据
this.getList()
},
computed: {},
methods: {
/** 获取左侧场景树数据 */
getScenarioTree() {
this.scenarioTreeOptionsOrigin = [
{
id: 1,
label: '硬件层',
children: [
{
id: 5,
label: '无线协议'
}, {
id: 6,
label: '外部有线接口'
}, {
id: 7,
label: '内部有线接口'
}, {
id: 8,
label: '芯片'
}, {
id: 9,
label: '硬件'
}
]
}, {
id: 2,
label: '硬件抽象层',
children: [
{
id: 10,
label: '协议栈'
}, {
id: 11,
label: '驱动'
}, {
id: 12,
label: '安全'
}
]
}, {
id: 3,
label: '服务层',
children: [
{
id: 13,
label: '运行时'
}, {
id: 14,
label: '通讯'
}, {
id: 15,
label: '存储'
}
]
}, {
id: 4,
label: '应用层',
children: [
{
id: 16,
label: '系统'
}, {
id: 17,
label: '其他'
}
]
}
]
this.scenarioTreeOptions = _.cloneDeep(this.scenarioTreeOptionsOrigin);
this.setScenarioNode()
},
// 筛选节点
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
// 节点单击事件
handleNodeClick(data) {
// 重置节点数据
this.scenarioTreeOptions = _.cloneDeep(this.scenarioTreeOptionsOrigin);
// TODO: please clear this log
console.log(`this.scenarioTreeOptions`, this.scenarioTreeOptions)
// TODO: please clear this log
console.log(`this.scenarioTreeOptionsOrigin`, this.scenarioTreeOptionsOrigin)
// this.queryParams.deptId = data.id
// this.handleQuery()
},
// 赋值主场景子场景节点数据
setScenarioNode() {
let activeMainScenario = this.scenarioTreeOptions.find(option => option.active)
if (activeMainScenario) {
// 主场景中存在被选中的项,即 active: true
this.mainScenario = activeMainScenario
let activeSubScenario = activeMainScenario.children.find(option => option.active)
if (activeSubScenario) {
// 子场景存在被选中的项
this.subScenario = activeSubScenario
} else {
this.scenarioTreeOptions[0].children[0].active = true
this.subScenario = this.scenarioTreeOptions[0].children[0]
}
} else {
// 如果主场景均未被选中,即主场景均无 active: true 属性,默认选择第一个主场景的第一个子场景
this.scenarioTreeOptions[0].active = true
this.scenarioTreeOptions[0].children[0].active = true
this.mainScenario = this.scenarioTreeOptions[0]
this.subScenario = this.scenarioTreeOptions[0].children[0]
}
},
/** 查询汽车安全测试属性测试工具列表 */
getList() {
this.loading = true;
listTools(this.queryParams).then(response => {
console.log(response.rows)
this.objList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
// 表单参数
this.form = {
// 工具id
id: null,
// 工具名称
toolName: null,
// 工具类别
toolType: null,
// 工具地址
toolAddress: null,
// 参考链接
referenceLink: null,
// 附件名称
attachmentName: null,
// 附件文件类型
attachmentFileType: null,
// 附件存储路径
attachmentStoragePath: null,
// 工具说明
toolDeclaration: null,
// 备注
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.isEdit = true;
this.title = "新增测试工具";
},
/** 查看按钮操作 */
handleView(row) {
this.reset();
this.isEdit = false;
getTools(row.id).then(response => {
this.form = response.data;
this.open = true;
this.title = "查看测试工具";
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.isEdit = true;
getTools(row.id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改测试工具";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateTools(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addTools(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除当前选中测试工具数据项').then(function () {
if (ids) {
delTools(ids).then(response => {
if (response.code === 200) {
this.$message.success('删除成功')
} else {
this.$message.error('删除失败')
}
})
} else {
this.$message.warning('请选择要删除的数据')
}
}).then(() => {
this.getList();
}).catch(() => {
});
},
/** 导出按钮操作 */
handleExport() {
this.download('cst/tools/export', {
...this.queryParams
}, `测试工具_${new Date().getTime()}.xlsx`)
},
// 测试方法
test() {
// TODO: please clear this log
console.log(`this.mainScenario`, this.mainScenario)
// TODO: please clear this log
console.log(`this.subScenario`, this.subScenario)
}
}
}
</script>
<style scoped>
.head-container {
padding: 10px;
box-sizing: border-box;
box-shadow: none;
text-align: left;
border: rgb(233, 233, 233) solid 1px;
}
.head-container:nth-child(1) {
display: flex;
justify-content: space-between;
align-items: center;
.el-icon-s-tools {
color: #5cb6ff;
cursor: pointer;
}
}
.head-container:nth-child(2) {
border-top: none;
border-bottom: none;
padding-bottom: 0;
}
.head-container:nth-child(3) {
border-top: none;
}
</style>
<template>
<!-- 测试工具管理 -->
<div class="app-container">
<el-form
v-show="showSearch"
ref="queryForm"
:model="queryParams"
size="small"
:inline="true"
>
<el-form-item label="工具类别:" prop="toolType">
<el-select
v-model="queryParams.toolType"
placeholder="请选择工具类别"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.cst_tool_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="工具名称:" prop="toolName">
<el-input
v-model="queryParams.toolName"
placeholder="请输入工具名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>查询
</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置
</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['cst:tools:add']"
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增
</el-button
>
</el-col>
<right-toolbar
:show-search.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="cstToolsList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55px" align="center"/>
<el-table-column type="index" width="55px" label="序号" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
label="工具类别"
align="left"
prop="toolType"
:show-overflow-tooltip="true"
min-width="120px"
>
<template slot-scope="scope">
<dict-tag :options="dict.type.cst_tool_type" :value="scope.row.toolType"/>
</template>
</el-table-column>
<el-table-column
label="工具名称"
align="left"
prop="toolName"
min-width="150px"
/>
<el-table-column
label="工具地址"
align="left"
prop="toolAddress"
min-width="150px"
/>
<el-table-column
label="参考链接"
align="left"
prop="referenceLink"
min-width="150px"
/>
<el-table-column
label="附件"
align="left"
prop="attachmentName"
min-width="150px"
/>
<el-table-column
label="操作"
align="center"
min-width="150px"
class-name="small-padding fixed-width"
>
<template v-if="scope.row.roleId !== 1" slot-scope="scope">
<el-button
v-hasPermi="['cst:tools:edit']"
size="mini"
type="text"
style="color: #409eff"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>编辑
</el-button
>
<el-button
v-hasPermi="['cst:tools:remove']"
size="mini"
type="text"
style="color: #f56c6c"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除
</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:background="false"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改测试工具对话框 -->
<el-dialog
:title="title"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="open"
width="500px"
append-to-body
>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="工具类别:" prop="toolType">
<el-select
v-model="form.toolType"
v-if="isEdit"
style="width: 100%"
placeholder="请选择工具类别"
clearable>
<el-option
v-for="dict in dict.type.cst_tool_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="工具名称:" prop="toolName">
<el-input v-model="form.toolName" placeholder="请输入工具名称"/>
</el-form-item>
<el-form-item label="工具地址:" prop="toolAddress">
<el-input v-model="form.toolAddress" placeholder="请输入工具地址"/>
</el-form-item>
<el-form-item label="参考链接:" prop="referenceLink">
<el-input v-model="form.referenceLink" placeholder="请输入参考链接"/>
</el-form-item>
<el-form-item label="附件:">
<el-input
v-model="form.attachmentName"
type="textarea"
placeholder="上传文件"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listTools,
getTools,
addTools,
updateTools,
delTools
} from "@/views/cst-knowledge-base/api/tools";
export default {
name: 'index',
dicts: ['cst_tool_type'],
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 测试工具列表 表格数据
cstToolsList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 弹出层对话框内容是否可编辑
isEdit: true,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
// 工具名称
toolName: null,
// 工具类别
toolType: null
},
// 表单参数
form: {
// 工具id
id: null,
// 工具名称
toolName: null,
// 工具类别
toolType: null,
// 工具地址
toolAddress: null,
// 参考链接
referenceLink: null,
// 附件名称
attachmentName: null,
// 附件文件类型
attachmentFileType: null,
// 附件存储路径
attachmentStoragePath: null,
// 工具说明
toolDeclaration: null,
// 备注
remark: null
},
// 表单校验
rules: {
toolName: [
{required: true, message: '工具名称不能为空', trigger: 'blur'}
],
toolType: [
{required: true, message: '工具类别不能为空', trigger: 'blur'}
],
toolAddress: [
{required: true, message: '工具地址不能为空', trigger: 'blur'}
],
referenceLink: [
{required: true, message: '参考链接不能为空', trigger: 'blur'}
],
attachmentName: [
{required: true, message: '附件不能为空', trigger: 'blur'}
]
}
}
},
created() {
this.getList()
},
methods: {
/** 查询汽车安全测试属性测试工具列表 */
getList() {
this.loading = true;
listTools(this.queryParams).then(response => {
console.log(response.rows)
this.cstToolsList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
// 表单参数
this.form = {
// 工具id
id: null,
// 工具名称
toolName: null,
// 工具类别
toolType: null,
// 工具地址
toolAddress: null,
// 参考链接
referenceLink: null,
// 附件名称
attachmentName: null,
// 附件文件类型
attachmentFileType: null,
// 附件存储路径
attachmentStoragePath: null,
// 工具说明
toolDeclaration: null,
// 备注
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.isEdit = true;
this.title = "新增测试工具";
},
/** 查看按钮操作 */
handleView(row) {
this.reset();
this.isEdit = false;
getTools(row.id).then(response => {
this.form = response.data;
this.open = true;
this.title = "查看测试工具";
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.isEdit = true;
getTools(row.id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改测试工具";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateTools(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addTools(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除当前选中测试工具数据项').then(function () {
if (ids) {
delTools(ids).then(response => {
if (response.code === 200) {
this.$message.success('删除成功')
} else {
this.$message.error('删除失败')
}
})
} else {
this.$message.warning('请选择要删除的数据')
}
}).then(() => {
this.getList();
}).catch(() => {
});
},
/** 导出按钮操作 */
handleExport() {
this.download('cst/tools/export', {
...this.queryParams
}, `测试工具_${new Date().getTime()}.xlsx`)
}
}
}
</script>
<template>
<!-- 首页圆形堆积图 -->
<div>首页圆形堆积图</div>
</template>
<script>
export default {
name: "CircularStackingDiagram",
components: {},
data() {
return {}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 力导图 -->
</template>
<script>
export default {
name: "ForceMap",
components: {},
data() {
return {}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 关系图 -->
</template>
<script>
export default {
name: "RelationalGraph",
components: {},
data() {
return {}
},
watch: {},
mounted() {
},
computed: {},
methods: {}
}
</script>
<style scoped>
</style>
<template>
<!-- 测试 -->
<div class="parent_container">
<div
ref="chartContainer"
class="chart_container"
></div>
</div>
</template>
<script>
import * as d3 from 'd3-hierarchy';
import * as echarts from 'echarts';
export default {
name: "Test",
components: {},
data() {
return {
// Echarts 元素对象
myChart: null,
// Echarts 配置
option: null,
// 系列数据
seriesData: [],
// 最大层级深度
maxDepth: 0,
// D3 数据
displayRoot: null,
// 最外层 D3 数据
displayRootData: null,
// 测试用的本地 json 文件
optionView: require('/src/charts/json/option-view.json')
}
},
watch: {},
mounted() {
// 初始化 Echarts
this.initChart();
// 加载数据
this.loadData();
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
if (this.myChart) {
this.myChart.dispose();
}
},
computed: {},
methods: {
/**
* 初始化 Echarts
*/
initChart() {
this.myChart = echarts.init(this.$refs.chartContainer, null, {
renderer: 'canvas',
useDirtyRect: false
});
},
/**
* 加载数据
*/
async loadData() {
// 接口请求数据
// const [rawData] = await Promise.all([
// getIndexMapData().then(response => response.data),
// import('d3-hierarchy').then(module => module.default)
// ]);
// 使用测试数据
const [rawData] = await Promise.all([
import('/src/charts/json/option-view.json').then(module => module.default),
import('d3-hierarchy').then(module => module.default)
]);
this.prepareData(rawData);
this.initChartOptions();
},
/**
* json 数据处理
*
* @param rawData
* @returns {{maxDepth: number, seriesData: *[]}}
*/
prepareData(rawData) {
const seriesData = [];
let maxDepth = 0;
const convert = (source, basePath, depth) => {
if (!source || maxDepth > 5) return;
maxDepth = Math.max(depth, maxDepth);
seriesData.push({
id: basePath,
value: source.$count,
depth: depth,
index: seriesData.length
});
for (const key in source) {
if (source.hasOwnProperty(key) && !key.match(/^\$/)) {
convert(source[key], `${basePath}.${key}`, depth + 1);
}
}
};
convert(rawData, '汽车安全测试知识库', 0);
this.seriesData = seriesData;
this.maxDepth = maxDepth;
},
/**
* 初始化Echarts配置
*
* @param seriesData
* @param maxDepth
*/
initChartOptions() {
this.displayRoot = this.stratify();
const option = {
dataset: {
source: this.seriesData
},
tooltip: {},
visualMap: [
{
show: false,
min: 0,
max: this.maxDepth,
dimension: 'depth',
inRange: {
color: ['#006edd', '#e0ffff']
}
}
],
series: {
type: 'custom',
renderItem: this.renderItem,
progressive: 0,
coordinateSystem: 'none',
encode: {
tooltip: 'value',
itemName: 'id'
}
}
};
this.myChart.setOption(option);
this.myChart.on('click', {seriesIndex: 0}, this.handleChartClick);
this.myChart.getZr().on('click', this.handleBackgroundClick);
},
/**
* 层级数据 转化为 D3的层级结构
*
* @param seriesData
* @returns {*}
*/
stratify() {
return d3
.stratify()
.parentId(d => d.id.substring(0, d.id.lastIndexOf('.')))(this.seriesData)
.sum(d => d.value || 0)
.sort((a, b) => b.value - a.value);
},
/**
* Echarts 图表 节点位置大小布局计算
*
* @param params
* @param api
* @param displayRoot
*/
overallLayout(params, api) {
const context = params.context;
d3.pack()
.size([api.getWidth() - 2, api.getHeight() - 2])
.padding(3)(this.displayRoot);
context.nodes = {};
this.displayRoot.descendants().forEach(node => {
context.nodes[node.id] = node;
});
},
/**
* Echarts 图表 数据项渲染
*
* @param displayRoot
* @param params
* @param api
* @returns {{shape: {r, cx, cy}, textConfig: {position: string}, z2: number, emphasis: {style: {shadowOffsetX: number, shadowOffsetY: number, fontFamily: string, shadowBlur: number, fontSize: number, shadowColor: string}}, focus: Uint32Array, textContent: {emphasis: {style: {overflow: null, fontSize: number}}, style: {fontFamily: string, overflow: string, width: number, fontSize: number, text: (*|string)}, type: string}, style: {fill: *}, type: string, transition: string[]}}
*/
renderItem(params, api) {
const context = params.context || (params.context = {});
if (!context.layout) {
this.overallLayout(params, api);
context.layout = true;
}
const nodePath = api.value('id');
const node = context.nodes[nodePath];
if (!node) return;
const isLeaf = !node.children || !node.children.length;
const focus = new Uint32Array(node.descendants().map(node => node.data.index));
const nodeName = isLeaf
? nodePath.slice(nodePath.lastIndexOf('.') + 1).split(/(?=[A-Z][^A-Z])/g).join('\n')
: '';
const z2 = api.value('depth') * 2;
return {
type: 'circle',
focus: focus,
shape: {
cx: node.x,
cy: node.y,
r: node.r
},
transition: ['shape'],
z2: z2,
textContent: {
type: 'text',
style: {
text: nodeName,
fontFamily: 'Arial',
width: node.r * 1.3,
overflow: 'truncate',
fontSize: node.r / 3
},
emphasis: {
style: {
overflow: null,
fontSize: Math.max(node.r / 3, 12)
}
}
},
textConfig: {
position: 'inside'
},
style: {
fill: api.visual('color')
},
emphasis: {
style: {
fontFamily: 'Arial',
fontSize: 12,
shadowBlur: 20,
shadowOffsetX: 3,
shadowOffsetY: 5,
shadowColor: 'rgba(0,0,0,0.3)'
}
}
};
},
handleChartClick(params) {
this.drillDown(params.data.id);
},
handleBackgroundClick(event) {
if (!event.target) {
this.drillDown();
}
},
/**
* Echarts 图表 数据钻取
*
* @param targetNodeId
* @param displayRoot
*/
drillDown(targetNodeId) {
if (targetNodeId) {
this.displayRoot = this.displayRoot.descendants().find(node => node.data.id === targetNodeId);
} else {
this.displayRoot = this.stratify();
}
this.displayRoot.parent = null;
this.myChart.setOption({
dataset: {source: this.seriesData}
});
},
/**
* 根据浏览器窗口大小调整Echarts图表尺寸
*/
handleResize() {
if (this.myChart) {
this.myChart.resize();
}
}
}
}
</script>
<style scoped>
.parent_container {
}
.chart_container {
width: 100%;
height: 50rem;
display: flex;
margin-top: 2rem;
margin-bottom: 2rem;
justify-content: center;
}
</style>
...@@ -672,6 +672,8 @@ export default { ...@@ -672,6 +672,8 @@ export default {
getDeptTree() { getDeptTree() {
deptTreeSelect().then(response => { deptTreeSelect().then(response => {
this.deptOptions = response.data this.deptOptions = response.data
// TODO: please clear this log
console.log(`this.deptOptions`, this.deptOptions)
}) })
}, },
// 筛选节点 // 筛选节点
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment