dev-QQq
qinzhenpen 2 years ago
parent df48a96bf0
commit c86d105a86

@ -2,7 +2,7 @@
* @Author: qinzhenpen qzp1807@126.com * @Author: qinzhenpen qzp1807@126.com
* @Date: 2024-08-16 10:14:59 * @Date: 2024-08-16 10:14:59
* @LastEditors: qinzhenpen qzp1807@126.com * @LastEditors: qinzhenpen qzp1807@126.com
* @LastEditTime: 2024-08-16 16:38:09 * @LastEditTime: 2024-08-17 16:57:01
* @FilePath: \vue3\src\api\marketing-algorithm.js * @FilePath: \vue3\src\api\marketing-algorithm.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
@ -31,3 +31,27 @@ export function getMarketingAlgorithmPreprocessing(data) {
data, data,
}); });
} }
// 自建表导入
export function getMarketingAlgorithmImport(data) {
return request({
url: "/api/userprofile/uploadExcel",
method: "POST",
data,
});
}
// 查询自建表
export function getMarketingAlgorithmTable(params) {
return request({
url: "/api/userprofile/selfExcelBaseInfo",
method: "GET",
params,
});
}
// 算法知识导入
export function getMarketingAlgorithmKnowledgeImport(data) {
return request({
url: "/api/model/batchImport",
method: "POST",
data,
});
}

@ -1,28 +1,14 @@
<template> <template>
<div <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
:class="classObj" <div class="title" style="height: 58px; background-color: #072048 !important; z-index: 900 !important; position: relative">
class="app-wrapper"
:style="{ '--current-color': theme }"
>
<div class="title" style="height: 58px;background-color: #072048 !important;">
<div class="navTitle"> <div class="navTitle">
<span class="nacber-name"> </span> <span class="nacber-name"> </span>
</div> </div>
</div> </div>
<div <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
v-if="device === 'mobile' && sidebar.opened"
class="drawer-bg"
@click="handleClickOutside"
/>
<sidebar v-if="!sidebar.hide" class="sidebar-container" /> <sidebar v-if="!sidebar.hide" class="sidebar-container" />
<div <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
:class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" <div :class="{ 'fixed-header': fixedHeader }"></div>
class="main-container"
>
<div :class="{ 'fixed-header': fixedHeader }">
<!-- <navbar @setLayout="setLayout" />
<tags-view v-if="needTagsView" /> -->
</div>
<app-main /> <app-main />
<settings ref="settingRef" /> <settings ref="settingRef" />
</div> </div>

@ -1,4 +1,4 @@
import { parseTime } from './ruoyi' import { parseTime } from "./ruoyi";
export function getAssetsFile(url) { export function getAssetsFile(url) {
return new URL(`../assets/images/${url}`, import.meta.url).href; return new URL(`../assets/images/${url}`, import.meta.url).href;
} }
@ -6,15 +6,22 @@ export function getAssetsFile(url){
* 表格时间格式化 * 表格时间格式化
*/ */
export function formatDate(cellValue) { export function formatDate(cellValue) {
if (cellValue == null || cellValue == "") return ""; // 判断是不是时间戳不是就返回
var date = new Date(cellValue) let time;
var year = date.getFullYear() if (typeof cellValue === new Date()) {
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() var date = new Date(cellValue);
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() var year = date.getFullYear();
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
time = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
} else {
time = cellValue;
}
return time;
} }
/** /**
@ -23,40 +30,30 @@ export function formatDate(cellValue) {
* @returns {string} * @returns {string}
*/ */
export function formatTime(time, option) { export function formatTime(time, option) {
if (('' + time).length === 10) { if (("" + time).length === 10) {
time = parseInt(time) * 1000 time = parseInt(time) * 1000;
} else { } else {
time = +time time = +time;
} }
const d = new Date(time) const d = new Date(time);
const now = Date.now() const now = Date.now();
const diff = (now - d) / 1000 const diff = (now - d) / 1000;
if (diff < 30) { if (diff < 30) {
return '刚刚' return "刚刚";
} else if (diff < 3600) { } else if (diff < 3600) {
// less 1 hour // less 1 hour
return Math.ceil(diff / 60) + '分钟前' return Math.ceil(diff / 60) + "分钟前";
} else if (diff < 3600 * 24) { } else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前' return Math.ceil(diff / 3600) + "小时前";
} else if (diff < 3600 * 24 * 2) { } else if (diff < 3600 * 24 * 2) {
return '1天前' return "1天前";
} }
if (option) { if (option) {
return parseTime(time, option) return parseTime(time, option);
} else { } else {
return ( return d.getMonth() + 1 + "月" + d.getDate() + "日" + d.getHours() + "时" + d.getMinutes() + "分";
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
} }
} }
@ -65,18 +62,18 @@ export function formatTime(time, option) {
* @returns {Object} * @returns {Object}
*/ */
export function getQueryObject(url) { export function getQueryObject(url) {
url = url == null ? window.location.href : url url = url == null ? window.location.href : url;
const search = url.substring(url.lastIndexOf('?') + 1) const search = url.substring(url.lastIndexOf("?") + 1);
const obj = {} const obj = {};
const reg = /([^?&=]+)=([^?&=]*)/g const reg = /([^?&=]+)=([^?&=]*)/g;
search.replace(reg, (rs, $1, $2) => { search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1) const name = decodeURIComponent($1);
let val = decodeURIComponent($2) let val = decodeURIComponent($2);
val = String(val) val = String(val);
obj[name] = val obj[name] = val;
return rs return rs;
}) });
return obj return obj;
} }
/** /**
@ -85,14 +82,14 @@ export function getQueryObject(url) {
*/ */
export function byteLength(str) { export function byteLength(str) {
// returns the byte length of an utf8 string // returns the byte length of an utf8 string
let s = str.length let s = str.length;
for (var i = str.length - 1; i >= 0; i--) { for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i) const code = str.charCodeAt(i);
if (code > 0x7f && code <= 0x7ff) s++ if (code > 0x7f && code <= 0x7ff) s++;
else if (code > 0x7ff && code <= 0xffff) s += 2 else if (code > 0x7ff && code <= 0xffff) s += 2;
if (code >= 0xDC00 && code <= 0xDFFF) i-- if (code >= 0xdc00 && code <= 0xdfff) i--;
} }
return s return s;
} }
/** /**
@ -100,13 +97,13 @@ export function byteLength(str) {
* @returns {Array} * @returns {Array}
*/ */
export function cleanArray(actual) { export function cleanArray(actual) {
const newArray = [] const newArray = [];
for (let i = 0; i < actual.length; i++) { for (let i = 0; i < actual.length; i++) {
if (actual[i]) { if (actual[i]) {
newArray.push(actual[i]) newArray.push(actual[i]);
} }
} }
return newArray return newArray;
} }
/** /**
@ -114,13 +111,13 @@ export function cleanArray(actual) {
* @returns {Array} * @returns {Array}
*/ */
export function param(json) { export function param(json) {
if (!json) return '' if (!json) return "";
return cleanArray( return cleanArray(
Object.keys(json).map(key => { Object.keys(json).map((key) => {
if (json[key] === undefined) return '' if (json[key] === undefined) return "";
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) return encodeURIComponent(key) + "=" + encodeURIComponent(json[key]);
}) })
).join('&') ).join("&");
} }
/** /**
@ -128,21 +125,21 @@ export function param(json) {
* @returns {Object} * @returns {Object}
*/ */
export function param2Obj(url) { export function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') const search = decodeURIComponent(url.split("?")[1]).replace(/\+/g, " ");
if (!search) { if (!search) {
return {} return {};
} }
const obj = {} const obj = {};
const searchArr = search.split('&') const searchArr = search.split("&");
searchArr.forEach(v => { searchArr.forEach((v) => {
const index = v.indexOf('=') const index = v.indexOf("=");
if (index !== -1) { if (index !== -1) {
const name = v.substring(0, index) const name = v.substring(0, index);
const val = v.substring(index + 1, v.length) const val = v.substring(index + 1, v.length);
obj[name] = val obj[name] = val;
} }
}) });
return obj return obj;
} }
/** /**
@ -150,9 +147,9 @@ export function param2Obj(url) {
* @returns {string} * @returns {string}
*/ */
export function html2Text(val) { export function html2Text(val) {
const div = document.createElement('div') const div = document.createElement("div");
div.innerHTML = val div.innerHTML = val;
return div.textContent || div.innerText return div.textContent || div.innerText;
} }
/** /**
@ -162,21 +159,21 @@ export function html2Text(val) {
* @returns {Object} * @returns {Object}
*/ */
export function objectMerge(target, source) { export function objectMerge(target, source) {
if (typeof target !== 'object') { if (typeof target !== "object") {
target = {} target = {};
} }
if (Array.isArray(source)) { if (Array.isArray(source)) {
return source.slice() return source.slice();
} }
Object.keys(source).forEach(property => { Object.keys(source).forEach((property) => {
const sourceProperty = source[property] const sourceProperty = source[property];
if (typeof sourceProperty === 'object') { if (typeof sourceProperty === "object") {
target[property] = objectMerge(target[property], sourceProperty) target[property] = objectMerge(target[property], sourceProperty);
} else { } else {
target[property] = sourceProperty target[property] = sourceProperty;
} }
}) });
return target return target;
} }
/** /**
@ -185,18 +182,16 @@ export function objectMerge(target, source) {
*/ */
export function toggleClass(element, className) { export function toggleClass(element, className) {
if (!element || !className) { if (!element || !className) {
return return;
} }
let classString = element.className let classString = element.className;
const nameIndex = classString.indexOf(className) const nameIndex = classString.indexOf(className);
if (nameIndex === -1) { if (nameIndex === -1) {
classString += '' + className classString += "" + className;
} else { } else {
classString = classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length);
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
} }
element.className = classString element.className = classString;
} }
/** /**
@ -204,10 +199,10 @@ export function toggleClass(element, className) {
* @returns {Date} * @returns {Date}
*/ */
export function getTime(type) { export function getTime(type) {
if (type === 'start') { if (type === "start") {
return new Date().getTime() - 3600 * 1000 * 24 * 90 return new Date().getTime() - 3600 * 1000 * 24 * 90;
} else { } else {
return new Date(new Date().toDateString()) return new Date(new Date().toDateString());
} }
} }
@ -218,38 +213,38 @@ export function getTime(type) {
* @return {*} * @return {*}
*/ */
export function debounce(func, wait, immediate) { export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result let timeout, args, context, timestamp, result;
const later = function () { const later = function () {
// 据上一次触发时间间隔 // 据上一次触发时间间隔
const last = +new Date() - timestamp const last = +new Date() - timestamp;
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) { if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last) timeout = setTimeout(later, wait - last);
} else { } else {
timeout = null timeout = null;
// 如果设定为immediate===true因为开始边界已经调用过了此处无需调用 // 如果设定为immediate===true因为开始边界已经调用过了此处无需调用
if (!immediate) { if (!immediate) {
result = func.apply(context, args) result = func.apply(context, args);
if (!timeout) context = args = null if (!timeout) context = args = null;
}
} }
} }
};
return function (...args) { return function (...args) {
context = this context = this;
timestamp = +new Date() timestamp = +new Date();
const callNow = immediate && !timeout const callNow = immediate && !timeout;
// 如果延时不存在,重新设定延时 // 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait) if (!timeout) timeout = setTimeout(later, wait);
if (callNow) { if (callNow) {
result = func.apply(context, args) result = func.apply(context, args);
context = args = null context = args = null;
} }
return result return result;
} };
} }
/** /**
@ -260,18 +255,18 @@ export function debounce(func, wait, immediate) {
* @returns {Object} * @returns {Object}
*/ */
export function deepClone(source) { export function deepClone(source) {
if (!source && typeof source !== 'object') { if (!source && typeof source !== "object") {
throw new Error('error arguments', 'deepClone') throw new Error("error arguments", "deepClone");
} }
const targetObj = source.constructor === Array ? [] : {} const targetObj = source.constructor === Array ? [] : {};
Object.keys(source).forEach(keys => { Object.keys(source).forEach((keys) => {
if (source[keys] && typeof source[keys] === 'object') { if (source[keys] && typeof source[keys] === "object") {
targetObj[keys] = deepClone(source[keys]) targetObj[keys] = deepClone(source[keys]);
} else { } else {
targetObj[keys] = source[keys] targetObj[keys] = source[keys];
} }
}) });
return targetObj return targetObj;
} }
/** /**
@ -279,16 +274,16 @@ export function deepClone(source) {
* @returns {Array} * @returns {Array}
*/ */
export function uniqueArr(arr) { export function uniqueArr(arr) {
return Array.from(new Set(arr)) return Array.from(new Set(arr));
} }
/** /**
* @returns {string} * @returns {string}
*/ */
export function createUniqueString() { export function createUniqueString() {
const timestamp = +new Date() + '' const timestamp = +new Date() + "";
const randomNum = parseInt((1 + Math.random()) * 65536) + '' const randomNum = parseInt((1 + Math.random()) * 65536) + "";
return (+(randomNum + timestamp)).toString(32) return (+(randomNum + timestamp)).toString(32);
} }
/** /**
@ -298,7 +293,7 @@ export function createUniqueString() {
* @returns {boolean} * @returns {boolean}
*/ */
export function hasClass(ele, cls) { export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
} }
/** /**
@ -307,7 +302,7 @@ export function hasClass(ele, cls) {
* @param {string} cls * @param {string} cls
*/ */
export function addClass(ele, cls) { export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls if (!hasClass(ele, cls)) ele.className += " " + cls;
} }
/** /**
@ -317,94 +312,91 @@ export function addClass(ele, cls) {
*/ */
export function removeClass(ele, cls) { export function removeClass(ele, cls) {
if (hasClass(ele, cls)) { if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
ele.className = ele.className.replace(reg, ' ') ele.className = ele.className.replace(reg, " ");
} }
} }
export function makeMap(str, expectsLowerCase) { export function makeMap(str, expectsLowerCase) {
const map = Object.create(null) const map = Object.create(null);
const list = str.split(',') const list = str.split(",");
for (let i = 0; i < list.length; i++) { for (let i = 0; i < list.length; i++) {
map[list[i]] = true map[list[i]] = true;
} }
return expectsLowerCase return expectsLowerCase ? (val) => map[val.toLowerCase()] : (val) => map[val];
? val => map[val.toLowerCase()]
: val => map[val]
} }
export const exportDefault = 'export default ' export const exportDefault = "export default ";
export const beautifierConf = { export const beautifierConf = {
html: { html: {
indent_size: '2', indent_size: "2",
indent_char: ' ', indent_char: " ",
max_preserve_newlines: '-1', max_preserve_newlines: "-1",
preserve_newlines: false, preserve_newlines: false,
keep_array_indentation: false, keep_array_indentation: false,
break_chained_methods: false, break_chained_methods: false,
indent_scripts: 'separate', indent_scripts: "separate",
brace_style: 'end-expand', brace_style: "end-expand",
space_before_conditional: true, space_before_conditional: true,
unescape_strings: false, unescape_strings: false,
jslint_happy: false, jslint_happy: false,
end_with_newline: true, end_with_newline: true,
wrap_line_length: '110', wrap_line_length: "110",
indent_inner_html: true, indent_inner_html: true,
comma_first: false, comma_first: false,
e4x: true, e4x: true,
indent_empty_lines: true indent_empty_lines: true,
}, },
js: { js: {
indent_size: '2', indent_size: "2",
indent_char: ' ', indent_char: " ",
max_preserve_newlines: '-1', max_preserve_newlines: "-1",
preserve_newlines: false, preserve_newlines: false,
keep_array_indentation: false, keep_array_indentation: false,
break_chained_methods: false, break_chained_methods: false,
indent_scripts: 'normal', indent_scripts: "normal",
brace_style: 'end-expand', brace_style: "end-expand",
space_before_conditional: true, space_before_conditional: true,
unescape_strings: false, unescape_strings: false,
jslint_happy: true, jslint_happy: true,
end_with_newline: true, end_with_newline: true,
wrap_line_length: '110', wrap_line_length: "110",
indent_inner_html: true, indent_inner_html: true,
comma_first: false, comma_first: false,
e4x: true, e4x: true,
indent_empty_lines: true indent_empty_lines: true,
} },
} };
// 首字母大小 // 首字母大小
export function titleCase(str) { export function titleCase(str) {
return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) return str.replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
} }
// 下划转驼峰 // 下划转驼峰
export function camelCase(str) { export function camelCase(str) {
return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase()) return str.replace(/_[a-z]/g, (str1) => str1.substr(-1).toUpperCase());
} }
export function isNumberStr(str) { export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
} }
//文件下载 //文件下载
export function downBlobFile(fileName, fileBlob) { export function downBlobFile(fileName, fileBlob) {
const link = document.createElement('a') const link = document.createElement("a");
try { try {
// let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'}); //如果后台返回的不是blob对象类型先定义成blob对象格式,type格式根据返回文件不同修改 // let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'}); //如果后台返回的不是blob对象类型先定义成blob对象格式,type格式根据返回文件不同修改
const blob = fileBlob const blob = fileBlob;
const _fileName = fileName // 拆解获取文件名,如果后端没返回文件格式,则需要自己拼接文件后缀 const _fileName = fileName; // 拆解获取文件名,如果后端没返回文件格式,则需要自己拼接文件后缀
link.style.display = 'none' link.style.display = "none";
// 兼容浏览器 // 兼容浏览器
const url = window.URL || window.webkitURL || window.moxURL const url = window.URL || window.webkitURL || window.moxURL;
link.href = url.createObjectURL(blob) // 如果没设置axios请求reponseType为blob的话则参数应为new Blob(文件流),否则报错 link.href = url.createObjectURL(blob); // 如果没设置axios请求reponseType为blob的话则参数应为new Blob(文件流),否则报错
link.download = _fileName // 下载的文件名称 link.download = _fileName; // 下载的文件名称
link.click() link.click();
window.URL.revokeObjectURL(url) // #URL.revokeObjectURL()方法会释放一个通过URL.createObjectURL()创建的对象URL. 当你要已经用过了这个对象URL,然后要让浏览器知道这个URL已经不再需要指向对应的文件的时候,就需要调用这个方法. window.URL.revokeObjectURL(url); // #URL.revokeObjectURL()方法会释放一个通过URL.createObjectURL()创建的对象URL. 当你要已经用过了这个对象URL,然后要让浏览器知道这个URL已经不再需要指向对应的文件的时候,就需要调用这个方法.
} catch (error) { } catch (error) {
console.error(error.message) console.error(error.message);
} }
} }

@ -16,9 +16,10 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({ const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分 // axios中请求配置有baseURL选项表示请求URL公共部分
// baseURL: import.meta.env.VITE_APP_BASE_API, // baseURL: import.meta.env.VITE_APP_BASE_API,
baseURL:'http://118.31.7.2:9868/', // baseURL:'http://118.31.7.2:9868/',
baseURL:'http://192.168.2.28:9868/',
// 超时 // 超时
timeout: 10000 timeout: 100000
}) })
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(config => {

@ -1,5 +1,5 @@
<template> <template>
<div class="app-main"> <div class="app-main" v-loading="loading">
<div class="main-left"> <div class="main-left">
<div class="left-top"> <div class="left-top">
<img style="width: 26px; height: 26px" src="../../../assets/images/图标1.png" alt="" /> <img style="width: 26px; height: 26px" src="../../../assets/images/图标1.png" alt="" />
@ -15,14 +15,24 @@
<span>自建表</span> <span>自建表</span>
</div> </div>
<div class="left-item"> <div class="left-item">
<div v-for="(item, index) in zjData" :key="index" class="item" :class="{ 'is-active': zjIndex === index }" @click="goZJ(index)"> <div class="metrics">
<span>{{ item }}</span> <el-select v-model="n_dataTableQuery.selfTableName" placeholder="请选择数据" style="width: 180px" @change="selectType">
<el-option v-for="item in zjData" :key="item" :label="item" :value="item" />
</el-select>
</div>
</div> </div>
<div class="left-button">
<input type="file" ref="fileData" style="display: none" @change="importData" />
<el-button round type="primary" @click="$refs.fileData.click()"></el-button>
</div> </div>
</div> </div>
<div class="main-right"> <div class="main-right">
<el-table :data="tableData" style="width: 100%" :header-cell-style="headerCellStyle"> <el-table :data="tableData" style="width: 100%" :header-cell-style="headerCellStyle">
<el-table-column v-for="column in tableLabel" :key="column" :prop="column.prop" :label="column.label" align="center" /> <el-table-column v-for="column in tableLabel" :key="column" :prop="column.prop" :label="column.label" align="center">
<template #default="{ row }">
{{ formatDate(row[column.prop]) }}
</template>
</el-table-column>
</el-table> </el-table>
<pagination v-show="datatotal > 0" :total="datatotal" v-model:page="n_dataTableQuery.index" v-model:limit="n_dataTableQuery.size" @pagination="getSurface" style="margin-top: 10px" /> <pagination v-show="datatotal > 0" :total="datatotal" v-model:page="n_dataTableQuery.index" v-model:limit="n_dataTableQuery.size" @pagination="getSurface" style="margin-top: 10px" />
</div> </div>
@ -30,25 +40,30 @@
</template> </template>
<script setup> <script setup>
import * as portraitModel from "@/api/portraitModel"; import * as portraitModel from "@/api/portraitModel";
import * as marketingAlgorithmApi from "@/api/marketing-algorithm";
import { formatDate } from "@/utils/index.js";
import useUserStore from "@/store/modules/user"; import useUserStore from "@/store/modules/user";
import useAlgorithmStore from "@/store/modules/algorithm.js"; import useAlgorithmStore from "@/store/modules/algorithm.js";
import { ref } from "vue"; const { proxy } = getCurrentInstance();
import { getUserInfo } from "@/utils/auth";
const userInfo = JSON.parse(getUserInfo());
const loading = ref(false);
const fileData = ref(null);
const userStore = useUserStore(); const userStore = useUserStore();
const algorithmStore = useAlgorithmStore(); const algorithmStore = useAlgorithmStore();
// query // query
const n_dataTableQuery = ref({ const n_dataTableQuery = ref({
index: 1, index: 1,
size: 20, size: 7,
tableName: "用户属性表", tableName: "用户属性表",
userId: userStore.userInfo.userId, userId: userInfo.userId,
}); });
const datatotal = ref(0); const datatotal = ref(0);
const nzIndex = ref(0); const nzIndex = ref(0);
const nzData = ["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"]; const nzData = ["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"];
const zjIndex = ref(-1); const zjIndex = ref(-1);
const zjData = ["用户属性表", "用户登录活跃表", "用户消费能力表", "用户行为表", "用户评论表"]; const zjData = ref([]);
const tableLabel = reactive([ const tableLabel = ref([
{ prop: "id", label: "用户ID" }, { prop: "id", label: "用户ID" },
{ prop: "loginName", label: "登录名" }, { prop: "loginName", label: "登录名" },
{ prop: "userName", label: "用户姓名" }, { prop: "userName", label: "用户姓名" },
@ -62,10 +77,28 @@ const tableLabel = reactive([
{ prop: "updateTime", label: "注册时间" }, { prop: "updateTime", label: "注册时间" },
{ prop: "location", label: "所在地" }, { prop: "location", label: "所在地" },
]); ]);
const tableLabel2 = ref([]);
const arrhander = ref([]);
const arrhanderkey = ref([]);
const goNZ = (index, item) => { const goNZ = (index, item) => {
nzIndex.value = index; nzIndex.value = index;
zjIndex.value = -1; zjIndex.value = -1;
tableLabel.value = [
{ prop: "id", label: "用户ID" },
{ prop: "loginName", label: "登录名" },
{ prop: "userName", label: "用户姓名" },
{ prop: "studentId", label: "学号" },
{ prop: "stuClass", label: "班级" },
{ prop: "major", label: "专业" },
{ prop: "school", label: "学校" },
{ prop: "roleName", label: "角色名称" },
{ prop: "roleGender", label: "角色性别" },
{ prop: "roleAge", label: "角色年龄" },
{ prop: "updateTime", label: "注册时间" },
{ prop: "location", label: "所在地" },
];
n_dataTableQuery.value.tableName = item; n_dataTableQuery.value.tableName = item;
delete n_dataTableQuery.value.selfTableName;
getSurface(); getSurface();
}; };
const goZJ = (index) => { const goZJ = (index) => {
@ -73,22 +106,60 @@ const goZJ = (index) => {
nzIndex.value = -1; nzIndex.value = -1;
}; };
const tableData = ref([]); const tableData = ref([]);
const headerCellStyle = () => { const headerCellStyle = () => {
return { return {
color: "#ffffff !important", color: "#ffffff !important",
}; };
}; };
// //
const selectType = (type) => {}; const selectType = (type) => {
delete n_dataTableQuery.value.tableName;
getSurface();
nzIndex.value = -1;
};
const getSurface = () => { const getSurface = () => {
portraitModel.getUserTableData(n_dataTableQuery.value).then((res) => { portraitModel.getUserTableData(n_dataTableQuery.value).then((res) => {
tableData.value = res?.data?.list; tableData.value = res?.data?.list;
datatotal.value = res.data.total; datatotal.value = res.data.total;
tableLabel2.value = [];
if (tableData.value[0]?.stepOneA) {
arrhander.value = JSON.parse(tableData.value[0].stepOneA);
arrhanderkey.value = Object.keys(tableData.value[0]).slice(2, arrhander.value.length + 2);
arrhander.value.forEach((item, index) => {
tableLabel2.value.push({
prop: arrhanderkey.value[index],
label: item,
});
});
tableLabel.value = tableLabel2.value;
}
});
};
//
const importData = (e) => {
loading.value = true;
const files = e.target.files[0];
const formdata = new FormData();
formdata.append("file", files);
formdata.append("userId", userInfo.userId);
marketingAlgorithmApi.getMarketingAlgorithmImport(formdata).then((res) => {
loading.value = false;
proxy.$modal.msgSuccess("导入成功");
});
};
//
const selectZJ = (item) => {
marketingAlgorithmApi.getMarketingAlgorithmTable();
};
//
const getZJData = () => {
marketingAlgorithmApi.getMarketingAlgorithmTable({ userId: userInfo.userId }).then((res) => {
zjData.value = res?.data;
}); });
}; };
onMounted(() => { onMounted(() => {
getSurface(); getSurface();
getZJData();
}); });
</script> </script>
@ -135,6 +206,44 @@ onMounted(() => {
color: #ffffff; color: #ffffff;
} }
} }
.metrics {
padding: 0px 7px !important;
:deep(.el-input) {
.el-input__wrapper {
background-color: #ffffff00;
background-image: url("../../../assets/images/下拉框.png");
background-size: 100% 100%;
}
--el-input-text-color: #ffffff;
--el-input-border-color: #ffffff00;
--el-input-hover-border-color: #ffffff00;
--el-input-hover-border: #ffffff00;
--el-select-border-color-hover: #ffffff00;
--el-select-input-focus-border-color: #ffffff00;
--el-input-placeholder-color: #ffffff;
.el-input__inner {
color: #ffffff;
}
}
}
}
.left-button {
width: 195px;
height: 31px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-top: 20px !important;
:deep(.el-button) {
width: 149px;
height: 48px;
background: url("../../../assets/images/确定.png");
color: #ffffff;
border-color: #ffffff00;
background-size: 100% 100%;
margin: 15px;
}
} }
} }
.main-right { .main-right {

@ -1,11 +1,12 @@
<template> <template>
<el-scrollbar height="800px"> <el-scrollbar height="800px" v-loading="loading">
<div class="main-top"> <div class="main-top">
<span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span> <span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span>
<p style="font-weight: 400; font-size: 12px; color: #e6e6e6">给出任务清单参考做哪些数据的统计分析Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar sic tempor. Sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus pronin sapien nunc accuan eget.</p> <p style="font-weight: 400; font-size: 12px; color: #e6e6e6">给出任务清单参考做哪些数据的统计分析Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar sic tempor. Sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus pronin sapien nunc accuan eget.</p>
</div> </div>
<div class="main-but"> <div class="main-but">
<el-button> <input type="file" ref="fileknowledge" style="display: none" @change="knowledgeImport" />
<el-button @click="$refs.fileknowledge.click()">
<img src="../../../assets/images/导入.png" alt="" /> <img src="../../../assets/images/导入.png" alt="" />
算法知识导入 算法知识导入
</el-button> </el-button>
@ -26,7 +27,7 @@
</el-select> </el-select>
</div> </div>
<div class="metrics-table" style="margin-top: 10px"> <div class="metrics-table" style="margin-top: 10px">
<el-table border :data="algorithmStore.indexLibrary" style="width: 100%" :header-cell-style="headerCellStyle" @selection-change="handleSelectionChange"> <el-table border ref="multipleTableRef" :data="algorithmStore.indexLibrary" style="width: 100%" :header-cell-style="headerCellStyle" @selection-change="handleSelectionChange">
<el-table-column type="selection" prop="date" label="Date" align="center" /> <el-table-column type="selection" prop="date" label="Date" align="center" />
<el-table-column label="指标" align="center" prop="label" /> <el-table-column label="指标" align="center" prop="label" />
</el-table> </el-table>
@ -50,7 +51,7 @@
<span>模型参数设置</span> <span>模型参数设置</span>
</div> </div>
<div class="metrics-table" style="margin-top: 10px"> <div class="metrics-table" style="margin-top: 10px">
<el-table border :data="modelParams" style="width: 100%" :header-cell-style="headerCellStyle" @selection-change="handlemodelSelectionChange"> <el-table border ref="multipleTableRef" :data="modelParams" style="width: 100%" :header-cell-style="headerCellStyle" @selection-change="handlemodelSelectionChange">
<el-table-column type="selection" prop="date" label="Date" align="center" /> <el-table-column type="selection" prop="date" label="Date" align="center" />
<el-table-column prop="name" label="统计量" align="center" /> <el-table-column prop="name" label="统计量" align="center" />
</el-table> </el-table>
@ -58,7 +59,7 @@
</div> </div>
</div> </div>
<div style="margin-top: auto"> <div style="margin-top: auto">
<div class="startOver"> <div class="startOver" @click="restart">
<img src="../../../assets/images/重新开始.png" alt="" /> <img src="../../../assets/images/重新开始.png" alt="" />
<span>重新开始</span> <span>重新开始</span>
</div> </div>
@ -75,9 +76,8 @@
<div class="analysisResults" style="margin-top: 20px"> <div class="analysisResults" style="margin-top: 20px">
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span> <span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果</span>
<el-button>下载</el-button> <el-button>下载</el-button>
<el-table :data="tableData" style="width: 94%; margin-top: 10px" :header-cell-style="headerCellStyle" height="350"> <el-table :data="tableData" style="width: 100%; margin-top: 10px" :header-cell-style="headerCellStyle" height="350">
<el-table-column v-for="column in tableLabel" :key="column.label" :prop="column.label" :label="column.label" align="center"></el-table-column> <el-table-column v-for="column in tableLabel" :key="column.label" :prop="column.prop" :label="column.label" align="center"></el-table-column>
<p v-for="column in tableLabel" :key="column.label">{{ column.label }}</p>
</el-table> </el-table>
<el-pagination style="margin-top: 10px" background layout="prev, pager, next" :total="1000" /> <el-pagination style="margin-top: 10px" background layout="prev, pager, next" :total="1000" />
</div> </div>
@ -95,46 +95,46 @@
<div class="from-item"> <div class="from-item">
<el-form :inline="true" label-position="right" label-width="84px" :model="form" class="demo-form-inline"> <el-form :inline="true" label-position="right" label-width="84px" :model="form" class="demo-form-inline">
<el-form-item label="平均数:"> <el-form-item label="平均数:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.average" clearable />
</el-form-item> </el-form-item>
<el-form-item label="众数:"> <el-form-item label="众数:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.mode" clearable />
</el-form-item> </el-form-item>
<el-form-item label="中位数:"> <el-form-item label="中位数:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.median" clearable />
</el-form-item> </el-form-item>
<el-form-item label="标准差:"> <el-form-item label="标准差:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.standardDeviation" clearable />
</el-form-item> </el-form-item>
<el-form-item label="方差:"> <el-form-item label="方差:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.variance" clearable />
</el-form-item> </el-form-item>
<el-form-item label="峰度:"> <el-form-item label="峰度:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.kurtosis" clearable />
</el-form-item> </el-form-item>
<el-form-item label="标准误差:"> <el-form-item label="标准误差:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.standardError" clearable />
</el-form-item> </el-form-item>
<el-form-item label="偏度:"> <el-form-item label="偏度:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.skewness" clearable />
</el-form-item> </el-form-item>
<el-form-item label="最大值:"> <el-form-item label="最大值:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.max" clearable />
</el-form-item> </el-form-item>
<el-form-item label="最小值:"> <el-form-item label="最小值:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.min" clearable />
</el-form-item> </el-form-item>
<el-form-item label="求和:"> <el-form-item label="求和:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.summation" clearable />
</el-form-item> </el-form-item>
<el-form-item label="观测数:"> <el-form-item label="观测数:">
<el-input style="width: 120px" v-model="formInline.user" clearable /> <el-input style="width: 120px" v-model="formInline.observations" clearable />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="dialogVisible = false">确定</el-button> <el-button @click="submitTask"></el-button>
<el-button type="primary" @click="dialogVisible = false">返回</el-button> <el-button type="primary" @click="dialogVisible = false">返回</el-button>
</div> </div>
</template> </template>
@ -142,19 +142,25 @@
</template> </template>
<script setup> <script setup>
import * as API from "@/api/AI.js"; import * as portraitModel from "@/api/portraitModel";
import * as API from "@/api/AI.js";
import * as marketingAlgorithmApi from "@/api/marketing-algorithm.js"; import * as marketingAlgorithmApi from "@/api/marketing-algorithm.js";
import useAlgorithmStore from "@/store/modules/algorithm.js"; import useAlgorithmStore from "@/store/modules/algorithm.js";
import useUserStore from "@/store/modules/user"; import useUserStore from "@/store/modules/user";
import { onMounted, ref } from "vue"; import { getUserInfo } from "@/utils/auth";
const userInfo = JSON.parse(getUserInfo());
const loading = ref(false);
const { proxy } = getCurrentInstance();
const userStore = useUserStore(); const userStore = useUserStore();
const algorithmStore = useAlgorithmStore(); const algorithmStore = useAlgorithmStore();
const multipleTableRef=ref(null)
const fileknowledge = ref(null);
const n_dataTableQuery = ref({ const n_dataTableQuery = ref({
index: 1, index: 1,
size: 20, size: 20,
tableName: "用户属性表", tableName: "用户属性表",
userId: userStore.userInfo.userId, userId: userInfo.userId,
}); });
const dialogVisible = ref(false); const dialogVisible = ref(false);
// //
@ -199,20 +205,33 @@ const modelParams = reactive([
const analysisData = ref([]); const analysisData = ref([]);
const analysisHanderKry = ref([]); const analysisHanderKry = ref([]);
const tableLabel = reactive([ const tableLabel = reactive([
{ prop: "date", label: "用户ID" }, { prop: "average", label: "平均数" },
{ prop: "name", label: "登录名" }, { prop: "median", label: "中位数" },
{ prop: "name", label: "用户姓名" }, { prop: "mode", label: "众数" },
{ prop: "name", label: "学号" }, { prop: "standardDeviation", label: "标准差" },
{ prop: "name", label: "班级" }, { prop: "variance", label: "方差" },
{ prop: "name", label: "专业" }, { prop: "standardError", label: "标准误差" },
{ prop: "name", label: "学校" }, { prop: "kurtosis", label: "峰度" },
{ prop: "name", label: "角色名称" }, { prop: "skewness", label: "偏度" },
{ prop: "name", label: "角色性别" }, { prop: "max", label: "最大值" },
{ prop: "name", label: "角色年龄" }, { prop: "min", label: "最小值" },
{ prop: "name", label: "注册时间" }, { prop: "summation", label: "求和" },
{ prop: "name", label: "所在地" }, { prop: "observations", label: "观测数" },
]); ]);
const formInline = ref({}); const formInline = ref({
average: "",
median: "",
mode: "",
standardDeviation: "",
variance: "",
standardError: "",
kurtosis: "",
skewness: "",
max: "",
min: "",
summation: "",
observations: "",
});
const input = ref(); const input = ref();
const g_indicatorData = ref([]); const g_indicatorData = ref([]);
const preProcessText = ref({ const preProcessText = ref({
@ -223,6 +242,10 @@ const preProcessText = ref({
const g_modelParameter = ref([]); const g_modelParameter = ref([]);
// //
const preProcess = (tetx) => { const preProcess = (tetx) => {
if (analysisData.value.length == 0) {
proxy.$modal.msgWarning("请先选择指标进行数据分析!");
preProcessText.value.text2 = "";
}
API.dataPreprocessing({ API.dataPreprocessing({
mapList: analysisData.value, mapList: analysisData.value,
method: preProcessText.value.text2, method: preProcessText.value.text2,
@ -235,28 +258,7 @@ const preProcess = (tetx) => {
const taskSubmit = () => { const taskSubmit = () => {
dialogVisible.value = true; dialogVisible.value = true;
}; };
const tableData = [ const tableData = ref([]);
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
];
const headerCellStyle = () => { const headerCellStyle = () => {
return { return {
backgroundColor: "#1882DE !important", // backgroundColor: "#1882DE !important", //
@ -274,9 +276,11 @@ const handleSelectionChange = (type) => {
}; };
// //
const submit = () => { const submit = () => {
if (g_indicatorData.value.length == 0) return proxy.$modal.msgWarning("请选择指标");
marketingAlgorithmApi.getMarketingAlgorithm({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName, fieldList: g_indicatorData.value }).then((res) => { marketingAlgorithmApi.getMarketingAlgorithm({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName, fieldList: g_indicatorData.value }).then((res) => {
analysisData.value = res.data; analysisData.value = res.data;
analysisHanderKry.value = Object.keys(res.data[0]); analysisHanderKry.value = Object.keys(res.data[0]);
proxy.$modal.msgSuccess("分析数据成功");
}); });
}; };
// //
@ -285,8 +289,14 @@ const handlemodelSelectionChange = (type) => {
}; };
// //
const modelCalculation = () => { const modelCalculation = () => {
if (analysisData.value.length == 0 && g_modelParameter.value.length == 0) {
proxy.$modal.msgWarning("请先分析数据/未选择模型参数!");
return;
}
const processedData = processArrayData(analysisHanderKry.value, analysisData.value); const processedData = processArrayData(analysisHanderKry.value, analysisData.value);
marketingAlgorithmApi.getMarketingAlgorithmPreprocessing(JSON.stringify({ map: processedData, statistic: g_modelParameter.value, userId: n_dataTableQuery.value.userId })); marketingAlgorithmApi.getMarketingAlgorithmPreprocessing(JSON.stringify({ map: processedData, statistic: g_modelParameter.value, userId: n_dataTableQuery.value.userId })).then((res) => {
tableData.value = res.data.map((item) => item.statistics);
});
}; };
function processArrayData(keys, data) { function processArrayData(keys, data) {
// //
@ -309,6 +319,65 @@ onMounted(() => {
const getIndicator = () => { const getIndicator = () => {
algorithmStore.getUserDatabase({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName }); algorithmStore.getUserDatabase({ userId: n_dataTableQuery.value.userId, tableName: n_dataTableQuery.value.tableName });
}; };
//
const knowledgeImport = (e) => {
loading.value = true;
const files = e.target.files[0];
const formdata = new FormData();
formdata.append("file", files);
marketingAlgorithmApi.getMarketingAlgorithmKnowledgeImport(formdata).then((res) => {
proxy.$modal.msgSuccess("导入成功");
loading.value = false;
});
};
//
const submitTask = () => {
for (let key in formInline.value) {
if (formInline.value[key] == "") {
const label = tableLabel.find((item) => item.prop == key);
proxy.$modal.msgWarning(`${label.label}不能为空`);
return;
}
}
portraitModel
.submit({
userId: n_dataTableQuery.value.userId,
taskName: "描述性统计",
numberOfErrors: 0,
})
.then((res) => {
dialogVisible.value = false;
proxy.$modal.msgSuccess("提交成功");
});
};
//
const restart = () => {
//
formInline.value = {
average: "",
median: "",
mode: "",
standardDeviation: "",
variance: "",
standardError: "",
kurtosis: "",
skewness: "",
max: "",
min: "",
summation: "",
observations: "",
};
analysisData.value = [];
analysisHanderKry.value = [];
tableData.value = [];
g_indicatorData.value = [];
g_modelParameter.value = [];
preProcessText.value.text2 = "";
n_dataTableQuery.value.tableName = "用户属性表";
getIndicator();
proxy.$modal.msgSuccess("重新开始成功");
multipleTableRef.value.clearSelection();
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -323,14 +392,14 @@ const getIndicator = () => {
.main-but { .main-but {
margin: 5px 20px 0; margin: 5px 20px 0;
display: flex; display: flex;
.el-button:nth-child(1) { .el-button:nth-child(2) {
width: 180px; width: 180px;
height: 56px; height: 56px;
background: url("../../../assets/images/011.png"); background: url("../../../assets/images/011.png");
color: #ffffff; color: #ffffff;
border-color: #ffffff00; border-color: #ffffff00;
} }
.el-button:nth-child(2) { .el-button:nth-child(3) {
width: 180px; width: 180px;
height: 56px; height: 56px;
background: url("../../../assets/images/022.png"); background: url("../../../assets/images/022.png");

@ -39,6 +39,9 @@
img{ img{
margin-right: 5px; margin-right: 5px;
} }
.el-button{
padding-left: 49px !important;
}
.el-button:nth-child(1) { .el-button:nth-child(1) {
width: 170px; width: 170px;
height: 50px; height: 50px;
@ -94,9 +97,9 @@
border-color:#FFFFFF00; border-color:#FFFFFF00;
padding:8px 5px 8px 20px; padding:8px 5px 8px 20px;
} }
// .active{ .active{
// background: url('../../assets/images/.png'); background: url('../../assets/images/亮(钮).png');
// } }
} }
} }
</style> </style>

Loading…
Cancel
Save