merge from cool-admin-vue-5.x

This commit is contained in:
tonglx 2022-05-20 10:36:51 +08:00
parent 0c1bd6a824
commit 59b6a2f73b
188 changed files with 22999 additions and 0 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
# 🎨 editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
vite.config.ts

64
.eslintrc.js Normal file
View File

@ -0,0 +1,64 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true
},
parser: "vue-eslint-parser",
parserOptions: {
parser: "@typescript-eslint/parser",
ecmaVersion: 2020,
sourceType: "module",
jsxPragma: "React",
ecmaFeatures: {
jsx: true,
tsx: true
}
},
extends: [
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended"
],
rules: {
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-empty-function": "off",
"vue/component-name-in-template-casing": ["error", "kebab-case"],
"vue/component-definition-name-casing": ["error", "kebab-case"],
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^h$",
varsIgnorePattern: "^h$"
}
],
"no-unused-vars": [
"error",
{
argsIgnorePattern: "^h$",
varsIgnorePattern: "^h$"
}
],
"space-before-function-paren": "off",
"vue/attributes-order": "off",
"vue/one-component-per-file": "off",
"vue/html-closing-bracket-newline": "off",
"vue/max-attributes-per-line": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/attribute-hyphenation": "off",
"vue/html-self-closing": "off",
"vue/require-default-prop": "off"
}
};

4
.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
*.js text eol=lf
*.json text eol=lf
*.ts text eol=lf
*.vue text eol=lf

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local

8
.prettierrc Normal file
View File

@ -0,0 +1,8 @@
{
"tabWidth": 4,
"useTabs": true,
"semi": true,
"singleQuote": false,
"printWidth": 100,
"trailingComma": "none"
}

67
.vscode/crud.code-snippets vendored Normal file
View File

@ -0,0 +1,67 @@
{
"cl-crud": {
"prefix": "cl-crud",
"body": [
"<template>",
" <cl-crud ref=\"Crud\">",
" <el-row>",
" <!-- 刷新按钮 -->",
" <cl-refresh-btn />",
" <!-- 新增按钮 -->",
" <cl-add-btn />",
" <!-- 删除按钮 -->",
" <cl-multi-delete-btn />",
" <cl-flex1 />",
" <!-- 关键字搜索 -->",
" <cl-search-key />",
" </el-row>",
"",
" <el-row>",
" <!-- 数据表格 -->",
" <cl-table ref=\"Table\" />",
" </el-row>",
"",
" <el-row>",
" <cl-flex1 />",
" <!-- 分页控件 -->",
" <cl-pagination />",
" </el-row>",
"",
" <!-- 新增、编辑 -->",
" <cl-upsert ref=\"Upsert\" />",
" </cl-crud>",
"</template>",
"",
"<script lang=\"ts\" setup>",
"import { useCrud, useTable, useUpsert } from \"@cool-vue/crud\";",
"import { useCool } from \"/@/cool\";",
"",
"const { service, named } = useCool();",
"",
"named(\"菜单名称\");",
"",
"// cl-upsert 配置",
"const Upsert = useUpsert({",
" items: []",
"});",
"",
"// cl-table 配置",
"const Table = useTable({",
" columns: []",
"});",
"",
"// cl-crud 配置",
"const Crud = useCrud(",
" {",
" service: service.demo.goods",
" },",
" (app) => {",
" app.refresh();",
" }",
");",
"</script>",
""
],
"description": "cl-crud snippets"
}
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"editor.cursorSmoothCaretAnimation": true
}

16
Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM node:lts-alpine
WORKDIR /build
# 设置Node-Sass的镜像地址
RUN npm config set sass_binary_site https://repo.huaweicloud.com/node-sass
# 设置npm镜像
RUN npm config set registry https://repo.huaweicloud.com/repository/npm/
COPY package.json /build/package.json
RUN npm install
COPY ./ /build
RUN npm run build
FROM nginx
RUN mkdir /app
COPY --from=0 /build/dist /app
COPY --from=0 /build/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 cool-team-official
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

96
README.md Normal file
View File

@ -0,0 +1,96 @@
# cool-admin [vue3 - ts - vite]
<p align="center">
<a href="https://show.cool-admin.com/" target="blank"><img src="https://admin.cool-js.com/logo.png" width="200" alt="cool-admin Logo" /></a>
</p>
<p align="center">cool-admin 一个很酷的后台权限管理系统,开源免费,模块化、插件化、极速开发 CRUD方便快速构建迭代后台管理系统<a href="https://cool-js.com" target="_blank">文档</a> 进一步了解</p>
<p align="center">
<a href="https://github.com/cool-team-official/cool-admin-vue/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="GitHub license" />
<a href=""><img src="https://img.shields.io/github/package-json/v/cool-team-official/cool-admin-vue?style=flat-square" alt="GitHub tag"></a>
<img src="https://img.shields.io/github/last-commit/cool-team-official/cool-admin-vue?style=flat-square" alt="GitHub tag"></a>
</p>
## 地址
- [⚡️ vue2.x + element-ui](https://github.com/cool-team-official/cool-admin-vue)
- [⚡️ vue3.x + element-plus + ts + webpack](https://github.com/cool-team-official/cool-admin-vue/tree/vue3-ts-webpack)
- [📌 vue3.x + element-plus + ts + vite](https://github.com/cool-team-official/cool-admin-vue/tree/vue3-ts-vite)
- [🌐 码云仓库地址](https://gitee.com/cool-team-official/cool-admin-vue)
## 演示
[https://show.cool-admin.com](https://show.cool-admin.com)
账户admin密码123456
<img src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/home-mini.png" alt="Admin Home" ></a>
## 项目后端
[https://github.com/cool-team-official/cool-admin-midway](https://github.com/cool-team-official/cool-admin-midway)
## 微信群
<img width="260" src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/wechat.jpeg" alt="Admin Wechat"></a>
## 微信公众号
<img width="260" src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/mp.jpg" alt="Admin Wechat"></a>
## 在线社区
[https://bbs.cool-js.com/](https://bbs.cool-js.com/)
## 安装项目依赖
推荐使用 `yarn`
```shell
yarn
```
解决 `node-sass` 网络慢的方法:
```shell
yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass
```
## 运行应用程序
安装过程完成后,运行以下命令启动服务。您可以在浏览器中预览网站 [http://localhost:9000](http://localhost:9000)
```shell
yarn dev
```
### 服务器
#### 腾讯云特供
不限新老用户,注册过买过都可以享受
|配置|价格|条件|备注|
|---------|-------|-------|-------|
|2核2g2M|一年240|个人企业限一台(不限新老用户)||
|2核4g2M|一年260、两年380|个人企业限一台(不限新老用户)||
|2核4g3M|一年260、三年600|企业(不限新老用户)||
|2核4g5M|一年280、三年660|企业(不限新老用户)||
|4核8g5M|一年320、三年720|企业(不限新老用户)||
|4核8g10M|一年560、三年1520|企业(不限新老用户)||
|8核16g5M|一年1800、三年3800|限企业新用户|送独立数据库|
|8核16g10M|一年2200、三年6600|限企业新用户|送独立数据库|
|16核32g5M|一年2600、三年6900|限企业新用户|送独立数据库|
|16核32g10M|一年2900、三年9600|限企业新用户|送独立数据库|
#### 购买咨询,数量有限!!!
<img width="260" src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/wechat.jpeg?v=1" alt="Admin Wechat"></a>
#### 阿里云
[点击链接购买](https://www.aliyun.com/minisite/goods?userCode=pw6cig1f)

65
build/cool/index.ts Normal file
View File

@ -0,0 +1,65 @@
import { Plugin } from "vite";
import { parseJson } from "./utils";
import { getModules } from "./lib/modules";
import { createEps, getEps } from "./lib/eps";
import { createMenu } from "./lib/menu";
export const cool = (): Plugin | null => {
return {
name: "vite-cool",
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
function done(data: any) {
res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
res.end(JSON.stringify(data));
}
// 自定义
if (req.url.includes("__cool")) {
const body = await parseJson(req);
let next: any = null;
switch (req.url) {
// 快速创建菜单
case "/__cool_createMenu":
next = createMenu(body);
break;
// 获取模块列表
case "/__cool_modules":
next = getModules();
break;
// 创建描述文件
case "/__cool_eps":
next = createEps(body);
break;
}
if (next) {
next.then((data: any) => {
done({
code: 1000,
data
});
}).catch((message: string) => {
done({
code: 1001,
message
});
});
}
} else {
next();
}
});
},
config() {
return {
define: {
__EPS__: getEps()
}
};
}
};
};

219
build/cool/lib/eps/index.ts Normal file
View File

@ -0,0 +1,219 @@
import prettier from "prettier";
import { isEmpty, last } from "lodash";
import { createDir, firstUpperCase, readFile, toCamel } from "../../utils";
import { createWriteStream } from "fs";
import { join } from "path";
// 临时目录路径
const tempPath = join(__dirname, "../../temp");
// 创建描述文件
export async function createEps({ list, service }: any) {
const t0 = [
[
`
declare interface Crud {
/**
*
* @returns Promise<any>
*/
add(data: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
delete(data: { ids?: number[] | string[]; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data: { id?: number | string; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data: { id?: number | string; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: { page?: number | string; size?: number | string; [key: string]: any }): Promise<PageResponse>;
}
`,
`
declare interface PageResponse {
list: any[];
pagination: { size: number; page: number; total: number };
[key: string]: any;
}
`,
`
declare interface RequestOptions {
params?: any;
data?: any;
url: string;
method?: "GET" | "get" | "POST" | "post" | string;
[key: string]: any;
}
`
]
];
const t1 = [`declare type Service = {`, `request(data: RequestOptions): Promise<any>;`];
// 处理数据
function deep(d: any, k?: string) {
if (!k) k = "";
for (const i in d) {
const name = k + toCamel(firstUpperCase(i.replace(/[:]/g, "")));
if (d[i].namespace) {
// 查找配置
const item = list.find((e: any) => (e.prefix || "").includes(d[i].namespace));
if (item) {
const t = [
`declare interface ${name} ${item.extendCrud ? " extends Crud" : ""} {`
];
t1.push(`${i}: ${name};`);
// 插入方法
if (item.api) {
// 权限列表
const permission: string[] = [];
item.api.forEach((a: any) => {
// 方法名
const n = toCamel(a.name || last(a.path.split("/"))).replace(
/[:\/-]/g,
""
);
if (n) {
// 参数类型
let q: string[] = [];
// 参数列表
const { parameters = [] } = a.dts || {};
parameters.forEach((p: any) => {
if (p.description) {
q.push(`\n/** ${p.description} */\n`);
}
if (p.name.includes(":")) {
return false;
}
const a = `${p.name}${p.required ? "" : "?"}`;
const b = `${p.schema.type || "string"}`;
q.push(`${a}: ${b},`);
});
if (isEmpty(q)) {
q = ["any"];
} else {
q.unshift("{");
q.push("}");
}
// 返回类型
let res = "";
switch (a.path) {
case "/page":
res = "PageResponse";
break;
default:
res = "any";
break;
}
// 描述
t.push("\n");
t.push("/**\n");
t.push(` * ${a.summary || n}\n`);
t.push(` * @returns Promise<${res}>\n`);
t.push(" */\n");
t.push(
`${n}(data${q.length == 1 ? "?" : ""}: ${q.join(
""
)}): Promise<${res}>;`
);
}
permission.push(`${n}: string;`);
});
// 添加权限
t.push("\n");
t.push("/**\n");
t.push(" * 权限\n");
t.push(" */\n");
t.push(`permission: { ${permission.join("\n")} }`);
}
t.push("}");
t0.push(t);
}
} else {
t1.push(`${i}: {`);
deep(d[i], name);
t1.push(`},`);
}
}
}
deep(service);
t1.push("}");
// 追加
t0.push(t1);
// 文本内容
const content = prettier.format(t0.map((e) => e.join("")).join("\n\n"), {
parser: "typescript",
useTabs: true,
tabWidth: 4,
endOfLine: "lf",
semi: true,
singleQuote: false,
printWidth: 100,
trailingComma: "none"
});
// 创建 temp 目录
createDir(tempPath);
// 创建 service 描述文件
createWriteStream(join(tempPath, "service.d.ts"), {
flags: "w"
}).write(content);
// 创建 eps 文件
createWriteStream(join(tempPath, "eps.json"), {
flags: "w"
}).write(
JSON.stringify(
list.map((e: any) => {
return [e.prefix, e.api.map((a: any) => [a.method || "", a.path, a.name || ""])];
})
)
);
}
// 获取描述
export function getEps() {
return JSON.stringify(readFile(join(tempPath, "eps.json")));
}

View File

@ -0,0 +1,360 @@
import { createWriteStream } from "fs";
import prettier from "prettier";
import { join } from "path";
import { createDir } from "../../utils";
import rules from "./rules";
import { isFunction, isRegExp, isString } from "lodash";
// 格式化
function format(data: any) {
return {
label: data.label,
prop: data.prop,
...data,
component: data.component
};
}
// 颜色
const colors = [
"#409EFF",
"#67C23A",
"#E6A23C",
"#F56C6C",
"#909399",
"#B0CFEB",
"#FF9B91",
"#E6A23C",
"#BFAD6F",
"#FB78F2"
];
// 组件处理器
const handler = {
// 单选
dict({ comment }) {
const [label, ...arr] = comment.split(" ");
// 选择列表
const list = arr.map((e: string, i: number) => {
const [value, label] = e.split("-");
const d: any = {
label,
value: isNaN(Number(value)) ? value : Number(value)
};
if (i > 0 && colors[i]) {
d.color = colors[i];
}
return d;
});
const d: any = {
table: {
label,
dict: list
},
form: {
label,
component: {
name: "",
options: list
}
}
};
// 默认值
if (list[0]) {
d.form.value = list[0].value;
}
// 匹配组件
d.form.component.name = arr.length > 4 ? "el-select" : "el-radio-group";
return d;
},
// 多选
dict_multiple({ comment }) {
const { table, form }: any = handler.dict({ comment });
if (!form.component.props) {
form.component.props = {};
}
if (!form.value) {
form.value = [];
}
switch (form.component.name) {
case "el-select":
form.component.props.multiple = true;
form.component.props.filterable = true;
break;
case "el-radio-group":
form.component.name = "el-checkbox-group";
break;
}
return {
table,
form
};
}
};
// 创建组件
function createComponent(item: any) {
const { propertyName: prop, comment: label } = item;
let d = null;
rules.forEach((r: any) => {
const s = r.test.find((e: any) => {
if (isRegExp(e)) {
return e.test(prop);
}
if (isFunction(e)) {
return e(prop);
}
if (isString(e)) {
const re = new RegExp(`${e}$`);
return re.test(prop.toLocaleLowerCase());
}
return false;
});
if (s) {
if (r.handler) {
const fn = isString(r.handler) ? handler[r.handler] : r.handler;
if (isFunction(fn)) {
d = fn(item);
}
} else {
d = {
...r,
test: undefined
};
}
}
});
function parse(v: any) {
if (v?.name) {
return {
prop,
label,
component: v
};
} else {
return {
prop,
label,
...v
};
}
}
return {
column: parse(d?.table),
item: parse(d?.form)
};
}
// 获取页面标识
function getPageName(router: string) {
if (router.indexOf("/") === 0) {
router = router.substr(1, router.length);
}
return router ? router.replace("/", "-") : "";
}
// 时间合并
function datetimeMerge({ columns, item }: any) {
if (["startTime", "startDate"].includes(item.prop)) {
const key = item.prop.replace("start", "");
if (columns.find((e: any) => e.propertyName == "end" + key)) {
item.prop = key.toLocaleLowerCase();
const isTime = item.prop == "time";
item.label = isTime ? "时间范围" : "日期范围";
item.hook = "datetimeRange";
item.component = {
name: "el-date-picker",
props: {
type: isTime ? "datetimerange" : "daterange",
valueFormat: isTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD 00:00:00",
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
}
};
}
}
}
// 创建文件
export async function createMenu({ router, columns, prefix, api, module, filename }: any): void {
const upsert: any = {
items: []
};
const table: any = {
columns: []
};
// 遍历
columns.forEach((e: any) => {
// 组件
const { item, column }: any = createComponent(e);
// 验证规则
if (!e.nullable) {
item.required = true;
}
// 忽略部分字段
if (!["createTime", "updateTime", "id", "endTime", "endDate"].includes(item.prop)) {
datetimeMerge({ columns, item });
if (!item.component) {
item.component = {
name: "el-input"
};
}
upsert.items.push(format(item));
}
if (!["cl-codemirror", "cl-editor-quill"].includes(column.component?.name)) {
table.columns.push(format(column));
}
});
// 服务
const service = prefix.replace("/admin", "service").replace(/\//g, ".");
// 请求路径
const paths = api.map((e: any) => e.path);
// 权限
const permission: any = {
add: paths.includes("/add"),
del: paths.includes("/delete"),
update: paths.includes("/info") && paths.includes("/update"),
page: paths.includes("/page"),
upsert: true
};
permission.upsert = permission.add || permission.update;
// 是否有操作栏
if (permission.del || permission.upsert) {
const d: any = {
type: "op",
buttons: []
};
if (permission.upsert) {
d.buttons.push("edit");
}
if (permission.del) {
d.buttons.push("delete");
}
table.columns.push(d);
}
// 是否多选、序号
if (permission.del) {
table.columns.unshift({
type: "selection"
});
} else {
table.columns.unshift({
label: "#",
type: "index"
});
}
// 代码模板
const temp = `<template>
<cl-crud ref="Crud">
<el-row>
<!-- -->
<cl-refresh-btn />
${permission.add ? "<!-- 新增按钮 -->\n<cl-add-btn />" : ""}
${permission.del ? "<!-- 删除按钮 -->\n<cl-multi-delete-btn />" : ""}
<cl-flex1 />
<!-- -->
<cl-search-key />
</el-row>
<el-row>
<!-- -->
<cl-table ref="Table" />
</el-row>
<el-row>
<cl-flex1 />
<!-- -->
<cl-pagination />
</el-row>
<!-- -->
<cl-upsert ref="Upsert" />
</cl-crud>
</template>
<script lang="ts" setup>
import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
import { useCool } from "/@/cool";
const { service, named } = useCool();
named("${getPageName(router)}");
// cl-upsert 配置
const Upsert = useUpsert(${JSON.stringify(upsert)});
// cl-table 配置
const Table = useTable(${JSON.stringify(table)});
// cl-crud 配置
const Crud = useCrud(
{
service: ${service}
},
(app) => {
app.refresh();
}
);
</script>`;
const content = prettier.format(temp, {
parser: "vue",
useTabs: true,
tabWidth: 4,
endOfLine: "lf",
semi: true,
jsxBracketSameLine: true,
singleQuote: false,
printWidth: 100,
trailingComma: "none"
});
// views 目录是否存在
const dir = join(__dirname, `../../../../src/modules/${module}/views`);
// 创建目录
createDir(dir);
// 创建文件
createWriteStream(join(dir, `${filename}.vue`), {
flags: "w"
}).write(content);
}

View File

@ -0,0 +1,214 @@
export default [
{
test: ["avatar", "img", "image", "pic", "photo", "picture", "head", "icon"],
table: {
name: "cl-image",
props: {
size: 60
}
},
form: {
name: "cl-upload"
}
},
{
test: ["avatars", "imgs", "images", "pics", "photos", "pictures", "heads", "icons"],
table: {
name: "cl-image",
props: {
size: 60
}
},
form: {
name: "cl-upload",
props: {
listType: "picture-card",
multiple: true
}
}
},
{
test: ["file", "attachment", "attach", "url", "video", "music"],
table: {
name: "cl-link"
},
form: {
name: "cl-upload",
props: {
listType: "text",
limit: 1
}
}
},
{
test: ["files", "attachments", "attachs", "urls", "videos", "musics"],
table: {
name: "cl-link"
},
form: {
name: "cl-upload",
props: {
listType: "text",
multiple: true
}
}
},
{
test: ["enable", "status"],
table: {
name: "cl-switch"
},
form: {
name: "el-switch"
}
},
{
test: ["type", "classify", "category"],
handler: "dict"
},
{
test: ["types", "classifys", "categorys"],
handler: "dict_multiple"
},
{
test: ["date"],
table: {
name: "cl-date-text",
props: {
format: "YYYY-MM-DD"
}
},
form: {
name: "el-date-picker",
props: {
type: "date",
valueFormat: "YYYY-MM-DD"
}
}
},
{
test: ["dates", "dateRange", "dateScope"],
table: {
name: "cl-date-text",
props: {
format: "YYYY-MM-DD"
}
},
form: {
component: {
name: "el-date-picker",
props: {
type: "daterange",
valueFormat: "YYYY-MM-DD"
}
}
}
},
{
test: ["time"],
form: {
name: "el-date-picker",
props: {
type: "datetime",
valueFormat: "YYYY-MM-DD HH:mm:ss"
}
}
},
{
test: ["times", "timeRange", "timeScope"],
form: {
component: {
name: "el-date-picker",
props: {
type: "datetimerange",
valueFormat: "YYYY-MM-DD HH:mm:ss",
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
}
}
}
},
{
test: ["star", "stars"],
table: {
name: "el-rate",
props: {
disabled: true
}
},
form: {
name: "el-rate"
}
},
{
test: ["progress", "rate", "ratio"],
table: {
name: "el-progress"
},
form: {
name: "el-slider",
props: {
style: {
width: "200px"
}
}
}
},
{
test: ["num", "price", "age", "amount"],
form: {
name: "el-input-number",
props: {
min: 0
}
}
},
{
test: ["remark", "desc"],
table: {
showOverflowTooltip: true
},
form: {
name: "el-input",
props: {
type: "textarea",
rows: 4
}
}
},
{
test: ["rich", "text", "html", "content", "introduce", "description", "desc"],
table: {
name: "cl-editor-quill"
},
form: {
name: "cl-editor-quill",
props: {
height: 400
}
}
},
{
test: ["code", "codes"],
table: {
name: "cl-codemirror"
},
form: {
name: "cl-codemirror",
props: {
height: 400
}
}
},
{
test: ["createTime"],
table: {
sortable: "desc"
}
},
{
test: ["updateTime"],
table: {
sortable: "custom"
}
}
];

View File

@ -0,0 +1,11 @@
import fs from "fs";
import { join } from "path";
export function getModules() {
try {
const dirs = fs.readdirSync(join(__dirname, "../../../../src/modules"));
return Promise.resolve(dirs.filter((e) => !e.includes(".")));
} catch (e) {
return Promise.reject(e);
}
}

1
build/cool/temp/eps.json Normal file
View File

@ -0,0 +1 @@
[["/admin/base/comm",[["post","/personUpdate",""],["get","/uploadMode",""],["get","/permmenu",""],["get","/person",""],["post","/upload",""],["post","/logout",""],["","/list",""],["","/page",""],["","/info",""],["","/update",""],["","/delete",""],["","/add",""]]],["/admin/base/open",[["get","/refreshToken",""],["get","/captcha",""],["post","/login",""],["get","/html",""],["get","/eps",""],["","/list",""],["","/page",""],["","/info",""],["","/update",""],["","/delete",""],["","/add",""]]],["/admin/base/sys/department",[["post","/delete",""],["post","/update",""],["post","/order",""],["post","/list",""],["post","/add",""],["","/page",""],["","/info",""]]],["/admin/base/sys/log",[["post","/setKeep",""],["get","/getKeep",""],["post","/clear",""],["post","/page",""],["","/list",""],["","/info",""],["","/update",""],["","/delete",""],["","/add",""]]],["/admin/base/sys/menu",[["post","/delete",""],["post","/update",""],["get","/info",""],["post","/list",""],["post","/page",""],["post","/add",""]]],["/admin/base/sys/param",[["post","/delete",""],["post","/update",""],["get","/html",""],["get","/info",""],["post","/page",""],["post","/add",""],["","/list",""]]],["/admin/base/sys/role",[["post","/delete",""],["post","/update",""],["get","/info",""],["post","/list",""],["post","/page",""],["post","/add",""]]],["/admin/base/sys/user",[["post","/delete",""],["post","/update",""],["post","/move",""],["get","/info",""],["post","/list",""],["post","/page",""],["post","/add",""]]],["/admin/demo/goods",[["post","/delete",""],["post","/update",""],["get","/info",""],["post","/page",""],["post","/list",""],["post","/add",""]]],["/admin/space/info",[["post","/delete",""],["post","/update",""],["get","/info",""],["post","/list",""],["post","/page",""],["post","/add",""]]],["/admin/space/type",[["post","/delete",""],["post","/update",""],["get","/info",""],["post","/list",""],["post","/page",""],["post","/add",""]]],["/admin/task/info",[["post","/delete",""],["post","/update",""],["post","/start",""],["post","/once",""],["post","/stop",""],["get","/info",""],["post","/page",""],["get","/log",""],["post","/add",""],["","/list",""]]],["/test",[["","/list",""],["","/page",""],["","/info",""],["","/update",""],["","/delete",""],["","/add",""]]]]

768
build/cool/temp/service.d.ts vendored Normal file
View File

@ -0,0 +1,768 @@
declare interface Crud {
/**
*
* @returns Promise<any>
*/
add(data: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
delete(data: { ids?: number[] | string[]; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data: { id?: number | string; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data: { id?: number | string; [key: string]: any }): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: {
page?: number | string;
size?: number | string;
[key: string]: any;
}): Promise<PageResponse>;
}
declare interface PageResponse {
list: any[];
pagination: { size: number; page: number; total: number };
[key: string]: any;
}
declare interface RequestOptions {
params?: any;
data?: any;
url: string;
method?: "GET" | "get" | "POST" | "post" | string;
[key: string]: any;
}
declare interface BaseComm {
/**
*
* @returns Promise<any>
*/
personUpdate(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
uploadMode(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
permmenu(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
person(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
upload(data?: any): Promise<any>;
/**
* 退
* @returns Promise<any>
*/
logout(data?: any): Promise<any>;
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
* page
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
* info
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
* update
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
* delete
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
* add
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
personUpdate: string;
uploadMode: string;
permmenu: string;
person: string;
upload: string;
logout: string;
list: string;
page: string;
info: string;
update: string;
delete: string;
add: string;
};
}
declare interface BaseOpen {
/**
* token
* @returns Promise<any>
*/
refreshToken(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
captcha(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
login(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
html(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
eps(data?: any): Promise<any>;
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
* page
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
* info
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
* update
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
* delete
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
* add
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
refreshToken: string;
captcha: string;
login: string;
html: string;
eps: string;
list: string;
page: string;
info: string;
update: string;
delete: string;
add: string;
};
}
declare interface BaseSysDepartment {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
order(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
* page
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
* info
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
order: string;
list: string;
add: string;
page: string;
info: string;
};
}
declare interface BaseSysLog {
/**
*
* @returns Promise<any>
*/
setKeep(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
getKeep(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
clear(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
* info
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
* update
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
* delete
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
* add
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
setKeep: string;
getKeep: string;
clear: string;
page: string;
list: string;
info: string;
update: string;
delete: string;
add: string;
};
}
declare interface BaseSysMenu {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
info: string;
list: string;
page: string;
add: string;
};
}
declare interface BaseSysParam {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
html(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
html: string;
info: string;
page: string;
add: string;
list: string;
};
}
declare interface BaseSysRole {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
info: string;
list: string;
page: string;
add: string;
};
}
declare interface BaseSysUser {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
move(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
move: string;
info: string;
list: string;
page: string;
add: string;
};
}
declare interface DemoGoods {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
info: string;
page: string;
list: string;
add: string;
};
}
declare interface SpaceInfo {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
info: string;
list: string;
page: string;
add: string;
};
}
declare interface SpaceType {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
info: string;
list: string;
page: string;
add: string;
};
}
declare interface TaskInfo {
/**
*
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
start(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
once(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
stop(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
*
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
*
* @returns Promise<any>
*/
log(data?: any): Promise<any>;
/**
*
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
*
*/
permission: {
delete: string;
update: string;
start: string;
once: string;
stop: string;
info: string;
page: string;
log: string;
add: string;
list: string;
};
}
declare interface Test {
/**
* list
* @returns Promise<any>
*/
list(data?: any): Promise<any>;
/**
* page
* @returns Promise<PageResponse>
*/
page(data?: any): Promise<PageResponse>;
/**
* info
* @returns Promise<any>
*/
info(data?: any): Promise<any>;
/**
* update
* @returns Promise<any>
*/
update(data?: any): Promise<any>;
/**
* delete
* @returns Promise<any>
*/
delete(data?: any): Promise<any>;
/**
* add
* @returns Promise<any>
*/
add(data?: any): Promise<any>;
/**
*
*/
permission: {
list: string;
page: string;
info: string;
update: string;
delete: string;
add: string;
};
}
declare type Service = {
request(data: RequestOptions): Promise<any>;
base: {
comm: BaseComm;
open: BaseOpen;
sys: {
department: BaseSysDepartment;
log: BaseSysLog;
menu: BaseSysMenu;
param: BaseSysParam;
role: BaseSysRole;
user: BaseSysUser;
};
};
demo: { goods: DemoGoods };
space: { info: SpaceInfo; type: SpaceType };
task: { info: TaskInfo };
test: Test;
};

46
build/cool/utils/index.ts Normal file
View File

@ -0,0 +1,46 @@
import fs from "fs";
// 首字母大写
export function firstUpperCase(value: string): string {
return value.replace(/\b(\w)(\w*)/g, function ($0, $1, $2) {
return $1.toUpperCase() + $2;
});
}
// 横杠转驼峰
export function toCamel(str: string): string {
return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) {
return $1 + $2.toUpperCase();
});
}
// 创建目录
export function createDir(path: string) {
if (!fs.existsSync(path)) fs.mkdirSync(path);
}
// 读取文件
export function readFile(name: string) {
try {
return fs.readFileSync(name, "utf8");
} catch (e) {}
return "";
}
// 解析body
export function parseJson(req: any) {
return new Promise((resolve) => {
let d = "";
req.on("data", function (chunk: Buffer) {
d += chunk;
});
req.on("end", function () {
try {
resolve(JSON.parse(d));
} catch {
resolve({});
}
});
});
}

71
build/svg/index.ts Normal file
View File

@ -0,0 +1,71 @@
import { Plugin } from "vite";
import { readFileSync, readdirSync } from "fs";
let idPerfix = "";
const svgTitle = /<svg([^>+].*?)>/;
const clearHeightWidth = /(width|height)="([^>+].*?)"/g;
const hasViewBox = /(viewBox="[^>+].*?")/g;
const clearReturn = /(\r)|(\n)/g;
function findSvgFile(dir: string): string[] {
const svgRes = [];
const dirents = readdirSync(dir, {
withFileTypes: true
});
for (const dirent of dirents) {
if (dirent.isDirectory()) {
svgRes.push(...findSvgFile(dir + dirent.name + "/"));
} else {
const svg = readFileSync(dir + dirent.name)
.toString()
.replace(clearReturn, "")
.replace(svgTitle, (_: any, $2: any) => {
let width = 0;
let height = 0;
let content = $2.replace(clearHeightWidth, (_: any, s2: any, s3: any) => {
if (s2 === "width") {
width = s3;
} else if (s2 === "height") {
height = s3;
}
return "";
});
if (!hasViewBox.test($2)) {
content += `viewBox="0 0 ${width} ${height}"`;
}
return `<symbol id="${idPerfix}-${dirent.name.replace(
".svg",
""
)}" ${content}>`;
})
.replace("</svg>", "</symbol>");
svgRes.push(svg);
}
}
return svgRes;
}
export const svgBuilder = (path: string, perfix = "icon"): Plugin | null => {
if (path !== "") {
idPerfix = perfix;
const res = findSvgFile(path);
return {
name: "svg-transform",
transformIndexHtml(html): string {
return html.replace(
"<body>",
`
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
${res.join("")}
</svg>
`
);
}
};
} else {
return null;
}
};

163
index.html Normal file
View File

@ -0,0 +1,163 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="referer" content="never" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
/>
<title>COOL-ADMIN</title>
<link rel="icon" href="favicon.ico" />
<style>
html,
body,
#app {
height: 100%;
}
* {
margin: 0;
padding: 0;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
.preload__wrap {
display: flex;
flex-direction: column;
height: 100%;
letter-spacing: 1px;
background-color: #2f3447;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 9999;
}
.preload__container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
user-select: none;
flex-grow: 1;
}
.preload__name {
font-size: 30px;
color: #fff;
letter-spacing: 5px;
font-weight: bold;
margin-bottom: 30px;
}
.preload__title {
color: #fff;
font-size: 14px;
margin: 30px 0 20px 0;
}
.preload__sub-title {
color: #ababab;
font-size: 12px;
}
.preload__footer {
text-align: center;
padding: 10px 0 20px 0;
}
.preload__footer a {
font-size: 12px;
color: #ababab;
text-decoration: none;
}
.preload__loading {
height: 30px;
width: 30px;
border-radius: 30px;
border: 7px solid currentColor;
border-bottom-color: #2f3447 !important;
position: relative;
animation: r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67),
bc 2s infinite ease-in;
transform: rotate(0deg);
}
@keyframes r {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.preload__loading::after,
.preload__loading::before {
content: "";
display: inline-block;
position: absolute;
bottom: -2px;
height: 7px;
width: 7px;
border-radius: 10px;
background-color: currentColor;
}
.preload__loading::after {
left: -1px;
}
.preload__loading::before {
right: -1px;
}
@keyframes bc {
0% {
color: #689cc5;
}
25% {
color: #b3b7e2;
}
50% {
color: #93dbe9;
}
75% {
color: #abbd81;
}
100% {
color: #689cc5;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload__wrap">
<div class="preload__container">
<p class="preload__name">COOL-ADMIN</p>
<div class="preload__loading"></div>
<p class="preload__title">正在加载资源...</p>
<p class="preload__sub-title">初次加载资源可能需要较多时间 请耐心等待</p>
</div>
<div class="preload__footer">
<a href="https://cool-js.com/" target="_blank"> https://cool-js.com </a>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

123
nginx.conf Normal file
View File

@ -0,0 +1,123 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
upstream backend {
server midway:7001;
}
server {
listen 80;
server_name localhost;
location / {
root /app;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/
{
proxy_pass http://backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
#缓存相关配置
#proxy_cache cache_one;
#proxy_cache_key $host$request_uri$is_args$args;
#proxy_cache_valid 200 304 301 302 1h;
#持久化连接相关配置
proxy_connect_timeout 3000s;
proxy_read_timeout 86400s;
proxy_send_timeout 3000s;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
add_header X-Cache $upstream_cache_status;
#expires 12h;
}
location /im {
proxy_pass http://backend/im;
proxy_connect_timeout 3600s; #配置点1
proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
proxy_send_timeout 3600s; #配置点3
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
#proxy_bind $remote_addr transparent;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# rewrite /socket/(.*) /$1 break;
proxy_redirect off;
}
location /socket {
proxy_pass http://backend/socket;
proxy_connect_timeout 3600s; #配置点1
proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
proxy_send_timeout 3600s; #配置点3
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
#proxy_bind $remote_addr transparent;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
rewrite /socket/(.*) /$1 break;
proxy_redirect off;
}
location /adminer/
{
proxy_pass http://adminer:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
#缓存相关配置
#proxy_cache cache_one;
#proxy_cache_key $host$request_uri$is_args$args;
#proxy_cache_valid 200 304 301 302 1h;
#持久化连接相关配置
proxy_connect_timeout 3000s;
proxy_read_timeout 86400s;
proxy_send_timeout 3000s;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
add_header X-Cache $upstream_cache_status;
#expires 12h;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}

70
package.json Normal file
View File

@ -0,0 +1,70 @@
{
"name": "front-next",
"version": "5.2.1",
"scripts": {
"dev": "vite --host",
"build": "vite build",
"serve": "vite preview",
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
},
"dependencies": {
"@cool-vue/crud": "^5.0.7",
"@element-plus/icons-vue": "^1.1.3",
"@vueuse/core": "^8.2.5",
"axios": "^0.27.2",
"codemirror": "^5.62.0",
"core-js": "^3.6.5",
"echarts": "^5.0.2",
"element-plus": "^2.2.0",
"file-saver": "^2.0.5",
"js-beautify": "^1.13.5",
"lodash": "^4.17.21",
"mitt": "^3.0.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"pinia": "^2.0.12",
"quill": "^1.3.7",
"store": "^2.0.12",
"unocss": "^0.31.0",
"vue": "^3.2.32",
"vue-echarts": "^6.0.2",
"vue-router": "^4.0.14",
"vuedraggable": "^4.1.0",
"xlsx": "^0.16.9"
},
"devDependencies": {
"@types/lodash": "^4.14.168",
"@types/node": "^16.10.2",
"@types/nprogress": "^0.2.0",
"@types/quill": "^2.0.9",
"@types/store": "^2.0.2",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"@unocss/preset-uno": "^0.31.0",
"@vitejs/plugin-vue": "^2.3.1",
"@vitejs/plugin-vue-jsx": "^1.3.9",
"@vue/cli-plugin-babel": "^5.0.1",
"@vue/cli-plugin-typescript": "^5.0.1",
"@vue/compiler-sfc": "^3.2.31",
"@vue/composition-api": "^1.4.9",
"eslint": "^7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.13.0",
"iconv-lite": "^0.6.3",
"prettier": "^2.4.1",
"sass": "^1.49.9",
"sass-loader": "^11.1.1",
"svg-sprite-loader": "^6.0.2",
"typescript": "^4.6.2",
"unplugin-vue-components": "^0.17.21",
"vite": "^2.9.8",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-dts": "^0.9.9",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-style-import": "^1.0.1",
"vite-svg-loader": "^2.1.0"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

28
src/App.vue Normal file
View File

@ -0,0 +1,28 @@
<template>
<el-config-provider :locale="zhCn">
<div class="preload__wrap" v-if="app.loading">
<div class="preload__container">
<p class="preload__name">{{ app.info.name }}</p>
<div class="preload__loading"></div>
<p class="preload__title">正在加载菜单...</p>
<p class="preload__sub-title">初次加载资源可能需要较多时间 请耐心等待</p>
</div>
<div class="preload__footer">
<a href="https://cool-js.com" target="_blank"> https://cool-js.com </a>
</div>
</div>
<router-view />
</el-config-provider>
</template>
<script lang="ts" setup>
import { ElConfigProvider } from "element-plus";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import { useBaseStore } from "/$/base";
const { app } = useBaseStore();
</script>
<style lang="scss" src="./assets/css/index.scss"></style>

44
src/assets/css/index.scss Normal file
View File

@ -0,0 +1,44 @@
* {
padding: 0;
margin: 0;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
"微软雅黑", Arial, sans-serif;
}
*::-webkit-scrollbar {
width: 10px;
height: 10px;
}
*::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
}
*::-webkit-scrollbar-track {
background: transparent;
}
#app {
height: 100vh;
width: 100vw;
overflow: hidden;
}
:root {
--view-bg-color: #f7f7f7;
}
a {
text-decoration: none;
}
input,
button {
outline: none;
}
input {
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px white inset;
}
}

BIN
src/assets/logo-text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

49
src/cool/bootstrap.ts Normal file
View File

@ -0,0 +1,49 @@
import { createPinia } from "pinia";
import { App } from "vue";
import { useModule } from "./module";
import { router, viewer } from "./router";
import { useBaseStore } from "/$/base";
import mitt from "mitt";
import VueECharts from "vue-echarts";
import ElementPlus from "element-plus";
import "element-plus/theme-chalk/src/index.scss";
import "uno.css";
export async function bootstrap(Vue: App) {
// 缓存
Vue.use(createPinia());
// ui库
Vue.use(ElementPlus);
// 事件通讯
Vue.provide("mitt", mitt());
// 可视图表
Vue.component("v-chart", VueECharts);
// 基础
const { app, user, menu } = useBaseStore();
// 加载模块
useModule(Vue);
// 取缓存视图
viewer.add(menu.routes);
// 路由
Vue.use(router);
// 开启
app.showLoading();
if (user.token) {
// 获取用户信息
user.get();
// 获取菜单权限
await menu.get();
}
app.hideLoading();
}

20
src/cool/config/dev.ts Normal file
View File

@ -0,0 +1,20 @@
import { getUrlParam, storage } from "../utils";
import { proxy } from "./proxy";
export default {
// 根地址
host: proxy["/dev"].target,
// 请求地址
get baseUrl() {
let proxy = getUrlParam("proxy");
if (proxy) {
storage.set("proxy", proxy);
} else {
proxy = storage.get("proxy") || "dev";
}
return `/${proxy}`;
}
};

61
src/cool/config/index.ts Normal file
View File

@ -0,0 +1,61 @@
import dev from "./dev";
import prod from "./prod";
// 是否开发模式
export const isDev = import.meta.env.MODE === "development";
// 配置
export const config = {
// 项目信息
app: {
name: "COOL-ADMIN",
// 菜单
menu: {
list: []
},
// 路由
router: {
// 模式
mode: "history",
// 页面
pages: [],
// 视图 / 路由下的 children
views: []
},
// 主题
theme: {
// 主色
color: "",
// 样式地址
url: "",
// 显示一级菜单
showAMenu: false
},
// 字体图标库
iconfont: []
},
// 忽略规则
ignore: {
// 不显示请求进度条
NProgress: ["/sys/info/record"],
// 页面不需要登录验证
token: ["/login", "/401", "/403", "/404", "/500", "/502"]
},
// 调试
test: {
token: "",
mock: false,
eps: true
},
// 当前环境
...(isDev ? dev : prod)
};
export * from "./proxy";

9
src/cool/config/prod.ts Normal file
View File

@ -0,0 +1,9 @@
import { proxy } from "./proxy";
export default {
// 根地址
host: proxy["/prod"].target,
// 请求地址
baseUrl: "/api"
};

13
src/cool/config/proxy.ts Normal file
View File

@ -0,0 +1,13 @@
export const proxy = {
"/dev": {
target: "http://127.0.0.1:8001",
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/dev/, "")
},
"/prod": {
target: "https://show.cool-admin.com",
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/prod/, "/api")
}
};

49
src/cool/hook/index.ts Normal file
View File

@ -0,0 +1,49 @@
import { onBeforeUpdate, ref, inject, getCurrentInstance } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useService } from "../service";
export function useRefs() {
const refs: any = ref<any[]>([]);
onBeforeUpdate(() => {
refs.value = [];
});
const setRefs = (index: string) => (el: any) => {
refs.value[index] = el;
};
return { refs, setRefs };
}
// 服务
const service = useService();
// 组件命名
function named(name: string) {
const { proxy }: any = getCurrentInstance();
proxy.$.type.name = name;
}
export function useCool() {
const { refs, setRefs } = useRefs();
// 通信
const mitt = inject<any>("mitt");
// 路由
const route = useRoute();
// 路由器
const router = useRouter();
return {
route,
router,
refs,
setRefs,
service,
mitt,
named
};
}

6
src/cool/index.ts Normal file
View File

@ -0,0 +1,6 @@
export * from "./service";
export * from "./bootstrap";
export * from "./hook";
export * from "./router";
export * from "./config";
export { storage } from "./utils";

162
src/cool/module/index.ts Normal file
View File

@ -0,0 +1,162 @@
import { App } from "vue";
import modules from "/@/modules";
import { router, viewer } from "../router";
import { filename, module } from "../utils";
import { isFunction, isObject } from "lodash";
// 扫描文件
const files = import.meta.globEager("/src/modules/**/*");
// 模块列表
const list: any[] = [...modules];
function main() {
for (const i in files) {
// 模块名
const [, , , name, action] = i.split("/");
// 文件内容
let value: any = null;
try {
value = files[i].default;
} catch (err) {
console.error(err, i);
value = files[i];
}
if (!value) {
continue;
}
// 文件名
const fname: string = filename(i);
// 配置参数
function next(d: any) {
// 配置参数入口
if (action == "config.ts") {
d.options = value || {};
}
// 模块入口
if (action == "index.ts") {
d.value = value || {};
}
// 其他功能
switch (action) {
case "service":
const s = new value();
d.service.push({
path: s.namespace,
value: s
});
break;
case "pages":
case "views":
if (value.cool) {
d[action].push({
...value.cool.route,
component: value
});
}
break;
case "components":
d.components[value.name] = value;
break;
case "directives":
d.directives[fname] = value;
break;
}
return d;
}
// 是否存在
const item: any = list.find((e) => e.name === name);
if (item) {
if (!item.isLoaded) {
next(item);
}
} else {
list.push(
next({
name,
options: {},
directives: {},
components: {},
pages: [],
views: [],
service: []
})
);
}
}
module.set(list);
}
main();
export function useModule(app: App) {
// 模块安装
list.forEach((e: any) => {
if (isObject(e.value)) {
if (isFunction(e.value.install)) {
Object.assign(e, e.value.install(app, e.options));
} else {
Object.assign(e, e.value);
}
}
try {
// 注册组件
if (e.components) {
for (const i in e.components) {
if (e.components[i]) {
if (e.components[i].cool?.global || i.indexOf("cl-") === 0) {
app.component(e.components[i].name, e.components[i]);
}
}
}
}
// 注册指令
if (e.directives) {
for (const i in e.directives) {
app.directive(i, e.directives[i]);
}
}
// 注册页面
if (e.pages) {
e.pages.forEach((e: any) => {
router.addRoute(e);
});
}
// 注册视图
if (e.views) {
e.views.forEach((e: any) => {
if (!e.meta) {
e.meta = {};
}
if (e.path) {
viewer.add([e]);
} else {
console.error(`[${name}-views]:缺少 path 参数`);
}
});
}
} catch (err) {
console.error(`模块 ${name} 异常`, err);
}
});
}

144
src/cool/router/index.ts Normal file
View File

@ -0,0 +1,144 @@
// @ts-nocheck
import { ElMessage } from "element-plus";
import {
createRouter,
createWebHashHistory,
createWebHistory,
NavigationGuardNext,
RouteRecordRaw
} from "vue-router";
import { storage, config } from "/@/cool";
import { useBaseStore } from "/$/base";
import { cloneDeep, isArray } from "lodash";
// 视图文件
const views = import.meta.globEager("/src/**/views/**/*.vue");
for (const i in views) {
views[i.slice(5)] = views[i];
delete views[i];
}
// 默认路由
const routes: RouteRecordRaw[] = [
{
path: "/",
name: "index",
component: () => import("/$/base/pages/layout/index.vue"),
children: [
{
path: "/",
name: "数据统计",
component: () => import("/@/views/home/index.vue")
},
...config.app.router.views
]
},
...config.app.router.pages,
{
path: "/:catchAll(.*)",
name: "404",
redirect: "/404"
}
];
// 创建
const router = createRouter({
history: config.app.router.mode == "history" ? createWebHistory() : createWebHashHistory(),
routes
}) as CoolRouter;
// 路由守卫
router.beforeEach((to: any, _: any, next: NavigationGuardNext) => {
const { user, process } = useBaseStore();
if (user.token) {
if (to.path.includes("/login")) {
// 登录成功且 token 未过期,回到首页
if (!storage.isExpired("token")) {
return next("/");
}
} else {
// 添加路由进程
process.add({
keepAlive: to.meta?.keepAlive,
label: to.meta?.label || to.name,
value: to.fullPath
});
}
} else {
if (!config.ignore.token.find((e: string) => to.path == e)) {
return next("/login");
}
}
next();
});
// 自定义
router.href = function (path: string) {
const url = import.meta.env.BASE_URL + path;
if (url != location.pathname) {
location.href = url;
}
};
let lock = false;
// 错误监听
router.onError((err: any) => {
if (!lock) {
lock = true;
ElMessage.error("页面不存在或者未配置!");
console.error(err);
setTimeout(() => {
lock = false;
}, 0);
}
});
// 视图
const viewer = {
add(data: any[] | any) {
// 列表
const list = isArray(data) ? data : [data];
list.forEach((e: any) => {
const d: any = cloneDeep(e);
// 命名
d.name = d.router;
if (!d.component) {
const url = d.viewPath;
if (url) {
if (
/^(http[s]?:\/\/)([0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?(\?[0-9a-z&=]+)?(#[0-9-a-z]+)?/i.test(
url
)
) {
d.meta.iframeUrl = url;
d.component = () => import(`/$/base/pages/iframe/index.vue`);
} else {
d.component = () => Promise.resolve(views[url.replace("cool/", "")]);
}
} else {
d.redirect = "/404";
}
}
// 批量添加
router.addRoute("index", d);
});
},
get() {
return router.getRoutes().find((e) => e.name == "index")?.children;
}
};
export { router, viewer };

132
src/cool/service/base.ts Normal file
View File

@ -0,0 +1,132 @@
// @ts-nocheck
import { isDev, config, proxy } from "../config";
import { isObject } from "lodash";
import request from "./request";
export function Service(
value:
| string
| {
namespace?: string;
url?: string;
mock?: boolean;
}
) {
return function (target: any) {
// 命名
if (typeof value == "string") {
target.prototype.namespace = value;
}
// 复杂项
if (isObject(value)) {
target.prototype.namespace = value.namespace;
target.prototype.mock = value.mock;
// 代理
if (value.proxy) {
target.prototype.url = proxy[value.proxy].target;
} else {
if (value.url) {
target.prototype.url = value.url;
}
}
}
};
}
export class BaseService {
constructor(
options = {} as {
namespace?: string;
}
) {
if (options?.namespace) {
this.namespace = options.namespace;
}
}
request(
options = {} as {
params?: any;
data?: any;
url: string;
method?: "GET" | "get" | "POST" | "post" | string;
[key: string]: any;
}
) {
if (!options.params) options.params = {};
let ns = "";
// 是否 mock 模式
if (this.mock || config.test.mock) {
// 测试
} else {
if (isDev) {
ns = this.proxy || config.baseUrl;
} else {
ns = this.proxy ? this.url : config.baseUrl;
}
}
// 拼接前缀
if (this.namespace) {
ns += "/" + this.namespace;
}
// 处理地址
if (options.proxy === undefined || options.proxy) {
options.url = ns + options.url;
}
return request(options);
}
list(data: any) {
return this.request({
url: "/list",
method: "POST",
data
});
}
page(data: { page?: number; size?: number; [key: string]: any }) {
return this.request({
url: "/page",
method: "POST",
data
});
}
info(params: { id?: number | string; [key: string]: any }) {
return this.request({
url: "/info",
params
});
}
update(data: { id?: number | string; [key: string]: any }) {
return this.request({
url: "/update",
method: "POST",
data
});
}
delete(data: { ids?: number[] | string[]; [key: string]: any }) {
return this.request({
url: "/delete",
method: "POST",
data
});
}
add(data: any) {
return this.request({
url: "/add",
method: "POST",
data
});
}
}

213
src/cool/service/eps.ts Normal file
View File

@ -0,0 +1,213 @@
import { isDev, config } from "../config";
import { BaseService } from "./base";
import { storage, toCamel } from "../utils";
import { isArray, isEmpty } from "lodash";
// 获取标签名
function getNames(v: any) {
return [...Object.getOwnPropertyNames(v.constructor.prototype), ...Object.keys(v)].filter(
(e) => !["namespace", "constructor", "request", "permission"].includes(e)
);
}
// 标签名
const names = getNames(new BaseService());
export function useEps(service: Service) {
// 创建描述文件
function createDts(list: any[]) {
function deep(v: any) {
for (const i in v) {
if (v[i].namespace) {
v[i].namespace = v[i].namespace;
// 模块
const item: any = list.find((e: any) => e.prefix.includes(v[i].namespace));
// 接口
const api: any[] = item ? item.api : [];
// 获取方法集合
[...names, ...getNames(v[i])].forEach((e) => {
if (!api.find((a) => a.path.includes(e))) {
api.push({
path: `/${e}`
});
}
});
if (item) {
item.api = api;
} else {
list.push({
prefix: `/${v[i].namespace}`,
api
});
}
} else {
deep(v[i]);
}
}
}
deep(service);
// 本地服务
return service.request({
url: "/__cool_eps",
method: "POST",
proxy: false,
data: {
service,
list
}
});
}
// 获取 eps
function getEps() {
if (isDev && config.test.eps) {
service
.request({
url: "/admin/base/open/eps"
})
.then(async (res) => {
if (!isEmpty(res)) {
const isLoaded: boolean = storage.get("eps");
storage.set("eps", res);
if (!isLoaded) {
location.reload();
} else {
set(res, true);
console.log("[Eps] 初始化成功。");
}
}
})
.catch((err) => {
console.error("[Eps] 获取失败!", err.message);
});
}
}
// 设置
async function set(d: any, c?: boolean) {
const list: any[] = [];
if (!d) {
return false;
}
if (isArray(d)) {
d = { d };
}
for (const i in d) {
if (isArray(d[i])) {
d[i].forEach((e: any) => {
// 分隔路径
const arr = e.prefix
.replace(/\//, "")
.replace("admin", "")
.split("/")
.filter(Boolean)
.map(toCamel);
// 遍历
function deep(d: any, i: number) {
const k = arr[i];
if (k) {
// 是否最后一个
if (arr[i + 1]) {
if (!d[k]) {
d[k] = {};
}
deep(d[k], i + 1);
} else {
// 本地不存在则创建实例
if (!d[k]) {
d[k] = new BaseService({
namespace: e.prefix.substr(1, e.prefix.length - 1)
});
}
// 创建方法
e.api.forEach((a: any) => {
// 方法名
const n = (a.name || a.path).replace("/", "");
// 过滤
if (!names.includes(n)) {
// 本地不存在则创建
if (!d[k][n]) {
if (n && !/[-:]/g.test(n)) {
d[k][n] = function (data: any) {
return this.request({
url: a.path,
method: a.method,
[a.method.toLocaleLowerCase() == "post"
? "data"
: "params"]: data
});
};
}
}
}
});
// 创建权限
if (!d[k].permission) {
d[k].permission = {};
const ks = Array.from(new Set([...names, ...getNames(d[k])]));
ks.forEach((e) => {
d[k].permission[e] = `${d[k].namespace.replace(
"admin/",
""
)}/${e}`.replace(/\//g, ":");
});
}
list.push(e);
}
}
}
deep(service, 0);
});
}
}
if (isDev && c) {
await createDts(list);
}
}
// 解析
try {
const eps =
storage.get("eps") ||
JSON.parse(__EPS__ || "[]").map(([prefix, api]: any[]) => {
return {
prefix,
api: api.map(([method, path, name]: string[]) => {
return {
method,
path,
name
};
})
};
});
set(eps);
} catch (err) {
console.error("[Eps] 解析失败!", err);
}
// 获取
getEps();
}

23
src/cool/service/index.ts Normal file
View File

@ -0,0 +1,23 @@
import { deepFiles, deepMerge, module } from "../utils";
import { BaseService } from "./base";
import { useEps } from "./eps";
// 基础服务
export const service: Service = {
request: new BaseService().request
};
export function useService() {
// 接口内容
useEps(service);
// 模块内容
module.list.forEach((e) => {
deepMerge(service, deepFiles(e.service || []));
});
return service;
}
export * from "./base";
export * from "./request";

146
src/cool/service/request.ts Normal file
View File

@ -0,0 +1,146 @@
import axios from "axios";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { ElMessage } from "element-plus";
import { isDev, config } from "/@/cool";
import { storage } from "/@/cool/utils";
import { useBaseStore } from "/$/base";
import { router } from "../router";
axios.defaults.timeout = 30000;
axios.defaults.withCredentials = false;
NProgress.configure({
showSpinner: true
});
// 请求队列
let requests: Array<Function> = [];
// Token 是否刷新中
let isRefreshing = false;
// @ts-ignore
axios.interceptors.request.eject(axios._req);
// @ts-ignore
axios._req = axios.interceptors.request.use(
(req: any) => {
const { user } = useBaseStore();
if (req.url) {
// 请求进度条
if (!config.ignore.NProgress.some((e: string) => req.url.includes(e))) {
NProgress.start();
}
}
// 请求信息
if (isDev) {
console.group(req.url);
console.log("method:", req.method);
console.table("data:", req.method == "get" ? req.params : req.data);
console.groupEnd();
}
// 验证 token
if (user.token) {
// 请求标识
req.headers["Authorization"] = user.token;
if (req.url.includes("refreshToken")) {
return req;
}
// 判断 token 是否过期
if (storage.isExpired("token")) {
// 判断 refreshToken 是否过期
if (storage.isExpired("refreshToken")) {
return user.logout();
}
// 是否在刷新中
if (!isRefreshing) {
isRefreshing = true;
user.refreshToken()
.then((token: string) => {
requests.forEach((cb) => cb(token));
requests = [];
isRefreshing = false;
})
.catch(() => {
user.clear();
});
}
return new Promise((resolve) => {
// 继续请求
requests.push((token: string) => {
// 重新设置 token
req.headers["Authorization"] = token;
resolve(req);
});
});
}
}
return req;
},
(error) => {
return Promise.reject(error);
}
);
// 响应
axios.interceptors.response.use(
(res) => {
NProgress.done();
if (!res?.data) {
return res;
}
const { code, data, message } = res.data;
switch (code) {
case 1000:
return data;
default:
return Promise.reject({ code, message });
}
},
async (error) => {
NProgress.done();
if (error.response) {
const { status, config } = error.response;
if (isDev) {
ElMessage.error(`${config.url} ${status}`);
} else {
switch (status) {
case 401:
router.href("401");
break;
case 403:
router.href("403");
break;
case 500:
router.href("500");
break;
case 502:
router.href("502");
break;
}
}
}
return Promise.reject({ message: error.message });
}
);
export default axios;

272
src/cool/utils/index.ts Normal file
View File

@ -0,0 +1,272 @@
import { isArray, orderBy } from "lodash";
import storage from "./storage";
import module from "./module";
// 首字母大写
export function firstUpperCase(value: string): string {
return value.replace(/\b(\w)(\w*)/g, function ($0, $1, $2) {
return $1.toUpperCase() + $2;
});
}
// 获取方法名
export function getNames(value: any) {
return Object.getOwnPropertyNames(value.constructor.prototype);
}
// 深度合并
export function deepMerge(a: any, b: any) {
let k;
for (k in b) {
a[k] =
a[k] && a[k].toString() === "[object Object]" ? deepMerge(a[k], b[k]) : (a[k] = b[k]);
}
return a;
}
// 获取地址栏参数
export function getUrlParam(name: string): string | null {
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
const r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURIComponent(r[2]);
return null;
}
// 文件路径转对象
export function deepFiles(list: any[]) {
const modules: any = {};
list.forEach((e) => {
const arr = e.path.split("/");
const parents = arr.slice(0, arr.length - 1);
const name = basename(e.path).replace(".ts", "");
let curr: any = modules;
let prev: any = null;
let key: any = null;
parents.forEach((k: string) => {
if (!curr[k]) {
curr[k] = {};
}
prev = curr;
curr = curr[k];
key = k;
});
if (name == "index") {
prev[key] = e.value;
} else {
curr[name] = e.value;
}
});
return modules;
}
// 文件名
export function filename(path: string): string {
return basename(path.substring(0, path.lastIndexOf(".")));
}
// 路径名称
export function basename(path: string): string {
let index = path.lastIndexOf("/");
index = index > -1 ? index : path.lastIndexOf("\\");
if (index < 0) {
return path;
}
return path.substring(index + 1);
}
// 文件扩展名
export function extname(path: string): string {
return path.substring(path.lastIndexOf(".") + 1);
}
// 横杠转驼峰
export function toCamel(str: string): string {
return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) {
return $1 + $2.toUpperCase();
});
}
// uuid
export function uuid(): string {
const s: any[] = [];
const hexDigits = "0123456789abcdef";
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
// 浏览器信息
export function getBrowser() {
const { clientHeight, clientWidth } = document.documentElement;
// 浏览器信息
const ua = navigator.userAgent.toLowerCase();
// 浏览器类型
let type = (ua.match(/firefox|chrome|safari|opera/g) || "other")[0];
if ((ua.match(/msie|trident/g) || [])[0]) {
type = "msie";
}
// 平台标签
let tag = "";
const isTocuh =
"ontouchstart" in window || ua.indexOf("touch") !== -1 || ua.indexOf("mobile") !== -1;
if (isTocuh) {
if (ua.indexOf("ipad") !== -1) {
tag = "pad";
} else if (ua.indexOf("mobile") !== -1) {
tag = "mobile";
} else if (ua.indexOf("android") !== -1) {
tag = "androidPad";
} else {
tag = "pc";
}
} else {
tag = "pc";
}
// 浏览器内核
let prefix = "";
switch (type) {
case "chrome":
case "safari":
case "mobile":
prefix = "webkit";
break;
case "msie":
prefix = "ms";
break;
case "firefox":
prefix = "Moz";
break;
case "opera":
prefix = "O";
break;
default:
prefix = "webkit";
break;
}
// 操作平台
const plat = ua.indexOf("android") > 0 ? "android" : navigator.platform.toLowerCase();
// 屏幕信息
let screen = "full";
if (clientWidth < 768) {
screen = "xs";
} else if (clientWidth < 992) {
screen = "sm";
} else if (clientWidth < 1200) {
screen = "md";
} else if (clientWidth < 1920) {
screen = "xl";
} else {
screen = "full";
}
// 是否 ios
const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
// 浏览器版本
const version = (ua.match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
// 是否 PC 端
const isPC = tag === "pc";
// 是否移动端
const isMobile = isPC ? false : true;
// 是否移动端 + 屏幕宽过小
const isMini = screen === "xs" || isMobile;
return {
height: clientHeight,
width: clientWidth,
version,
type,
plat,
tag,
prefix,
isMobile,
isIOS,
isPC,
isMini,
screen
};
}
// 列表转树形
export function deepTree(list: any[]): any[] {
const newList: Array<any> = [];
const map: any = {};
list.forEach((e) => (map[e.id] = e));
list.forEach((e) => {
const parent = map[e.parentId];
if (parent) {
(parent.children || (parent.children = [])).push(e);
} else {
newList.push(e);
}
});
const fn = (list: Array<any>) => {
list.map((e) => {
if (e.children instanceof Array) {
e.children = orderBy(e.children, "orderNum");
fn(e.children);
}
});
};
fn(newList);
return orderBy(newList, "orderNum");
}
// 树形转列表
export function revDeepTree(list: Array<any> = []) {
const d: Array<any> = [];
let id = 0;
const deep = (list: Array<any>, parentId: any) => {
list.forEach((e) => {
if (!e.id) {
e.id = id++;
}
e.parentId = parentId;
d.push(e);
if (e.children && isArray(e.children)) {
deep(e.children, e.id);
}
});
};
deep(list || [], null);
return d;
}
export { storage, module };

31
src/cool/utils/module.ts Normal file
View File

@ -0,0 +1,31 @@
// @ts-nocheck
interface Item {
name: string;
options: {
[key: string]: any;
};
value: any;
service?: any[];
pages?: any[];
views?: any[];
components?: {
[key: string]: any;
};
}
const module = {
get list(): Item[] {
return window.__modules__ || [];
},
set(list: Item[]) {
window.__modules__ = list;
},
get(name: string) {
return name ? window.__modules__.find((e) => e.name == name) : window.__modules__;
}
};
export default module;

81
src/cool/utils/storage.ts Normal file
View File

@ -0,0 +1,81 @@
import store from "store";
export default {
// 后缀标识
suffix: "_deadtime",
/**
*
* @param {string} key
*/
get(key: string) {
return store.get(key);
},
/**
*
*/
info() {
const d: any = {};
store.each(function (value: any, key: any) {
d[key] = value;
});
return d;
},
/**
*
* @param {string} key
* @param {*} value
* @param {number} expires
*/
set(key: string, value: any, expires?: any) {
store.set(key, value);
if (expires) {
store.set(`${key}${this.suffix}`, Date.parse(String(new Date())) + expires * 1000);
}
},
/**
*
* @param {string} key
*/
isExpired(key: string) {
return (this.getExpiration(key) || 0) - Date.parse(String(new Date())) <= 2000;
},
/**
*
* @param {string} key
*/
getExpiration(key: string) {
return this.get(key + this.suffix);
},
/**
*
* @param {string} key
*/
remove(key: string) {
store.remove(key);
this.removeExpiration(key);
},
/**
*
* @param {string} key
*/
removeExpiration(key: string) {
store.remove(key + this.suffix);
},
/**
*
*/
clearAll() {
store.clearAll();
}
};

4
src/env.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
/// <reference types="@cool-vue/crud" />
/// <reference types="../build/cool/temp/service" />
declare const __EPS__: string;

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441341007" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11418" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M848.896 132.192c-10.048-5.664-22.4-5.408-32.352 0.544-0.448 0.288-45.664 27.328-98.688 27.328-53.184 0-99.776-27.232-100.16-27.424a29.488 29.488 0 0 0-3.456-1.792c-3.2-1.408-79.008-34.752-149.696-34.752-70.08 0-151.936 32.96-155.36 34.368-12.032 4.896-19.936 16.64-19.936 29.632v416a32.041 32.041 0 0 0 14.24 26.624c8.928 5.984 20.192 7.04 30.08 2.912 19.68-8.224 80.992-29.536 127.68-29.536 51.52 0 115.776 24.768 126.208 28.928 11.712 6.304 68.544 35.072 133.088 35.072 72.032 0 127.776-35.616 130.08-37.152 9.088-5.92 14.592-16 14.592-26.848v-416c0.032-11.584-6.24-22.208-16.32-27.904z m-271.68 763.744H224.768V128.064c0-17.664-14.336-32-32-32s-32 14.336-32 32v768c0 0.064 0.032 0.096 0.032 0.16-16.96 0.8-30.56 14.528-30.56 31.712 0 17.696 14.336 32 32 32h414.976c17.696 0 32-14.304 32-32s-14.304-32-32-32z" p-id="11419"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441249036" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4552" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M364.8 590.62857143H182.85714286c-60.34285714 0-109.71428571-49.37142857-109.71428572-109.71428572V182.85714286c0-60.34285714 49.37142857-109.71428571 109.71428572-109.71428572h181.94285714c60.34285714 0 109.71428571 49.37142857 109.71428571 109.71428572v298.05714285c0 60.34285714-49.37142857 109.71428571-109.71428571 109.71428572zM841.14285714 358.4H659.2c-60.34285714 0-109.71428571-49.37142857-109.71428571-109.71428571V182.85714286c0-60.34285714 49.37142857-109.71428571 109.71428571-109.71428572H841.14285714c60.34285714 0 109.71428571 49.37142857 109.71428572 109.71428572v65.82857143c0 60.34285714-49.37142857 109.71428571-109.71428572 109.71428571zM364.8 950.85714286H182.85714286c-60.34285714 0-109.71428571-49.37142857-109.71428572-109.71428572v-65.82857143c0-60.34285714 49.37142857-109.71428571 109.71428572-109.71428571h181.94285714c60.34285714 0 109.71428571 49.37142857 109.71428571 109.71428571v65.82857143c0 60.34285714-49.37142857 109.71428571-109.71428571 109.71428572z m476.34285714 0H659.2c-60.34285714 0-109.71428571-49.37142857-109.71428571-109.71428572V543.08571429c0-60.34285714 49.37142857-109.71428571 109.71428571-109.71428572H841.14285714c60.34285714 0 109.71428571 49.37142857 109.71428572 109.71428572V841.14285714c0 60.34285714-49.37142857 109.71428571-109.71428572 109.71428572z" p-id="4553"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441250987" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4692" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M825.42250667 584.80298667H628.39239111l-29.53557333-99.30865778c74.05568-33.86026667 125.62545778-108.54172445 125.62545777-195.44291556 0-118.69297778-95.98862222-214.90005333-214.37553777-214.90005333-118.40170667 0-214.37553778 96.22186667-214.37553778 214.90005333 0 86.91484445 51.56977778 161.59744 125.62545778 195.44291556l-29.53557333 99.30865778h-197.02897778a70.59000889 70.59000889 0 0 0-70.59000889 70.59000888v131.0572089c0 17.31697778 14.03904 31.34122667 31.34008889 31.34122666h709.05628444a31.36967111 31.36967111 0 0 0 31.36967111-31.37080889V655.36341333a70.54563555 70.54563555 0 0 0-70.54563555-70.56042666z m48.71509333 291.24266666h-728.07537778a21.84533333 21.84533333 0 0 0-21.84533333 21.84533334v29.12711111a21.84533333 21.84533333 0 0 0 21.84533333 21.84533333h728.09016889a21.84533333 21.84533333 0 0 0 21.84533334-21.84533333v-29.12711111a21.84533333 21.84533333 0 0 0-21.86012445-21.84533334z" p-id="4693"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441301181" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8337" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M864.35351563 176.78515625c-22.93945313 3.95507813-46.40625 6.06445313-70.48828126 6.06445313-101.42578125 0-194.32617188-36.82617188-265.95703124-97.73437501-9.31640625-7.91015625-23.02734375-7.91015625-32.34375001 0-71.63085938 60.99609375-164.53125 97.734375-265.95703124 97.734375-23.73046875 0-47.02148438-2.02148438-69.60937501-5.88867187-15.1171875-2.54882813-28.91601563 9.140625-29.00390625 24.52148437-0.17578125 95.88867188-0.3515625 209.26757813-0.3515625 213.13476563 0 413.96484375 346.72851563 520.92773438 378.80859376 529.98046875 1.58203125 0.43945313 3.1640625 0.43945313 4.74609374 0C546.18945313 935.6328125 890.80859375 829.28515625 893.00585938 418.57226562l0.35156249-217.08984374c0-15.46875-13.88671875-27.33398438-29.00390625-24.69726563zM541.8828125 562.00976563v135.79101562c0 16.5234375-13.359375 29.8828125-29.8828125 29.8828125s-29.8828125-13.359375-29.8828125-29.8828125V562.00976563c-59.94140625-13.62304688-104.67773438-67.1484375-104.67773438-131.22070313 0-74.26757813 60.20507813-134.56054688 134.56054688-134.56054688S646.56054688 356.43359375 646.56054688 430.7890625c0 64.07226563-44.73632813 117.68554688-104.67773438 131.22070313z" p-id="8338"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441322440" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10017" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M509.27 62.598c-248.668 0-450.254 199.753-450.254 446.161s201.586 446.162 450.255 446.162 450.255-199.754 450.255-446.162S757.939 62.598 509.27 62.598z m0 148.72c55.666 0 107.78 15.033 152.468 41.2L250.676 659.842c-26.404-44.281-41.575-95.922-41.575-151.084 0-164.27 134.386-297.441 300.17-297.441z m0 594.883c-55.666 0-107.78-15.033-152.469-41.198l411.062-407.326C794.27 401.96 809.44 453.6 809.44 508.76c0 164.277-134.394 297.442-300.17 297.442z" p-id="10018"></path></svg>

After

Width:  |  Height:  |  Size: 853 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441302655" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8477" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M284.22599111 249.97250845c11.41782755-31.32742163 22.64147437-62.24099555 33.94279348-93.11573334 5.90309452-16.13035141 16.45317689-23.63907792 33.554432-23.65121422 106.48871822-0.05218608 212.97743645-0.05218608 319.46615466 0 17.70928355 0.0121363 28.54456889 7.85703822 34.61635793 24.69979022 10.16172089 28.2338797 20.42781392 56.42892325 30.26549571 84.76596148 1.99399348 5.76109985 4.88121837 7.46989037 10.84863526 7.43105423 45.03779555-0.25971675 90.06102755-0.1432083 135.09760948-0.1432083 46.33152475 0 84.05477452 36.93317689 84.11909689 83.25256533 0.19418075 158.4126483 0.44054755 316.81194667-0.12864474 475.22459497-0.19418075 53.15333689-45.21862637 83.49771852-83.951616 83.43339615-247.67025303-0.46603378-495.35506963-0.23301689-743.02532267-0.23301689-43.83387497 0-81.34959408-37.54241897-81.36173036-81.46610253-0.02669985-159.4612243-0.01334992-318.93458489 0-478.39580918 0-44.29990875 37.55455525-81.7767917 81.90543643-81.80227792 47.92380682-0.0121363 95.85974992 0 144.65130193 0z m395.04129897 308.73524147c0.75123675-92.05502103-75.58849422-164.60094578-163.6555283-166.58280295-93.00043852-2.09593837-171.21522725 72.74131911-171.65577481 165.14465185-0.42719763 88.27456475 69.05067141 167.64351525 167.87531851 167.43598459 100.13293985-0.21966697 167.90201837-80.54617125 167.4359846-165.99904711z" p-id="8478"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441255776" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4972" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M891.733 170.667H132.267c-38.4 0-68.267 29.866-68.267 68.266v102.4h896v-102.4c0-38.4-29.867-68.266-68.267-68.266z m0 704c38.4 0 68.267-29.867 68.267-68.267V426.667H64V806.4c0 38.4 29.867 68.267 68.267 68.267h759.466zM192 554.667h253.867c19.2 0 32 12.8 32 32s-12.8 32-32 32H187.733c-17.066-2.134-27.733-14.934-27.733-32 0-19.2 12.8-32 32-32z m0 128h128c19.2 0 32 12.8 32 32s-12.8 32-32 32H187.733c-17.066-2.134-27.733-14.934-27.733-32 0-19.2 12.8-32 32-32z" p-id="4973"></path></svg>

After

Width:  |  Height:  |  Size: 859 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441257585" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5112" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M259.2 896a64 64 0 1 0 128 0 64 64 0 1 0-128 0zM768 896a64 64 0 1 0 128 0 64 64 0 1 0-128 0zM940.8 284.8c-16-19.2-38.4-28.8-64-28.8H249.6l-22.4-112c-6.4-44.8-44.8-80-92.8-80H96c-19.2 0-32 16-32 32s12.8 32 32 32h38.4c12.8 0 25.6 9.6 28.8 25.6L192 310.4l51.2 371.2c6.4 48 44.8 86.4 89.6 86.4h486.4c44.8 0 83.2-32 89.6-73.6L960 355.2c3.2-25.6-3.2-51.2-19.2-70.4z" p-id="5113"></path></svg>

After

Width:  |  Height:  |  Size: 763 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441314533" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9317" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M478.176 454.848c-17.12 0-33.184 6.656-45.248 18.72-24.928 24.96-24.928 65.568 0 90.592 24.128 24.096 66.304 24.064 90.496-0.032 12.096-12.096 18.752-28.16 18.752-45.28s-6.656-33.184-18.752-45.28c-12.064-12.096-28.096-18.72-45.248-18.72zM512 63.968c-247.04 0-448 172.256-448 384 0 116.48 63.008 226.048 170.592 298.944l87.328 71.52c-3.904 19.328-17.408 60.096-32.64 97.536-4.928 12.096-1.984 25.984 7.36 35.072a32.049 32.049 0 0 0 22.272 8.992c4.384 0 8.8-0.896 12.992-2.752 36.416-16.224 147.488-68.96 187.584-125.376C763.104 828.448 960 657.568 960 447.968c0-211.744-200.96-384-448-384z m214.624 334.656c12.512 12.512 12.512 32.736 0 45.248-6.24 6.24-14.432 9.376-22.624 9.376s-16.384-3.136-22.624-9.376l-39.84-39.84-52.288 52.288c10.688 18.944 16.896 40.128 16.928 62.496 0.032 34.24-13.312 66.4-37.504 90.592-24.16 24.16-56.288 37.472-90.496 37.472-34.176 0-66.336-13.312-90.496-37.472-49.888-49.984-49.888-131.2 0-181.056 24.16-24.16 56.288-37.472 90.496-37.472 24.032 0 46.912 6.912 66.848 19.2l136.352-136.352c12.512-12.512 32.736-12.512 45.248 0s12.512 32.736 0 45.248l-39.84 39.84 39.84 39.808z" p-id="9318"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441297938" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8056" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 65.984C266.08 65.984 65.984 266.08 65.984 512c0 245.952 200.064 446.016 446.016 446.016 245.952 0 446.016-200.064 446.016-446.016 0-245.92-200.064-446.016-446.016-446.016zM512 672c-88.224 0-160-71.776-160-160s71.776-160 160-160 160 71.776 160 160-71.776 160-160 160z" p-id="8057"></path></svg>

After

Width:  |  Height:  |  Size: 675 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441329307" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10578" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M517.46416016 442.25V126.28583984A64.28583984 64.28583984 0 0 1 592.35839844 62.96416016a450 450 0 0 1 368.67832031 368.67832031 64.28583984 64.28583984 0 0 1-63.32167969 74.89335937H581.75a64.28583984 64.28583984 0 0 1-64.28583984-64.28583984z m-21.53583985 117.96416016h299.08916016a64.28583984 64.28583984 0 0 1 64.28583984 75.21416015A401.78583984 401.78583984 0 1 1 388.57167969 165.5a64.28583984 64.28583984 0 0 1 75.21416015 64.28583984v298.28583985a32.14248047 32.14248047 0 0 0 32.14248047 32.14248047z" p-id="10579"></path></svg>

After

Width:  |  Height:  |  Size: 917 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441339081" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11278" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M960.14 330.74c0-57.69-46.92-104.61-104.64-104.61S750.86 273.05 750.86 330.74c0 49.41 34.5 90.69 80.64 101.61-41.46 82.65-96.24 159.48-125.58 159.48-28.56 0-86.13-83.31-144.36-242.94 41.88-18.42 70.41-59.97 70.41-107.94 0-65.28-53.13-118.38-118.41-118.38-65.31 0-118.44 53.13-118.44 118.38 0 48.09 28.65 89.7 70.65 108.03C403.79 520.7 349.85 583.97 327.71 583.97c-41.13 0-98.25-79.98-135.42-151.65 46.17-10.89 80.73-52.2 80.73-101.64 0-57.69-46.95-104.61-104.64-104.61S63.74 273.05 63.74 330.74c0 39.54 22.32 73.62 54.78 91.41L139.25 839.81a29.955 29.955 0 0 0 13.86 23.82c4.35 2.79 109.41 67.65 360.45 67.65s356.1-65.1 360.45-67.86a30.1209375 30.1209375 0 0 0 13.86-24l18.48-417.81c31.92-17.88 53.79-51.69 53.79-90.87z" p-id="11279"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441317794" class="icon" viewBox="0 0 1096 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9597" xmlns:xlink="http://www.w3.org/1999/xlink" width="137" height="128"><defs><style type="text/css"></style></defs><path d="M415.24 190.419A128.774 128.774 0 1 0 544.014 62 128.774 128.774 0 0 0 415.24 190.419zM254.806 544.014h578.417a32.016 32.016 0 0 1 32.016 32.016v32.015a32.016 32.016 0 0 0 32.015 32.372 32.016 32.016 0 0 0 32.016-32.372v-96.402a32.016 32.016 0 0 0-32.016-32.016H608.046a32.016 32.016 0 0 1-32.016-32.016V415.24a32.016 32.016 0 0 0-32.016-32.016 32.371 32.371 0 0 0-32.371 32.016v32.371a32.016 32.016 0 0 1-32.016 32.016H190.42a32.016 32.016 0 0 0-32.016 32.016v96.402a32.016 32.016 0 0 0 32.016 32.372 32.371 32.371 0 0 0 32.371-32.372V576.03a32.016 32.016 0 0 1 32.016-32.016zM62 833.223A128.774 128.774 0 1 0 190.42 704.448 128.419 128.419 0 0 0 62 833.223z m706.836 0a128.419 128.419 0 1 0 128.418-128.775 128.419 128.419 0 0 0-128.418 128.775z m-353.596 0a128.774 128.774 0 1 0 128.774-128.775A128.774 128.774 0 0 0 415.24 833.223z" p-id="9598"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441331528" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10718" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M928.768 87.232c-0.032-7.456-1.216-13.696-2.848-19.328-31.328-8.288-72.128 1.248-106.624 17.984-7.072 3.424-23.84 13.632-48.672 28.736-10.272 6.272-19.328 11.776-23.328 14.048-0.384 0.224-0.608 0.64-0.96 0.864C678.56 88.256 599.296 64 514.272 64c-247.04 0-448 200.96-448 448 0 82.816 22.976 160.192 62.304 226.784C82.112 810.4 59.072 862.112 65.088 897.152c1.248 7.168 13.6 8.32 20.384 8.32 138.432 0 454.848-303.776 494.208-342.496C753.504 392 928.864 182.976 928.768 87.232zM306.272 610.688c-44.096 0-80-35.872-80-80 0-44.096 35.904-80 80-80s80 35.904 80 80c0 44.128-35.904 80-80 80z m140.8-224c-52.928 0-96-43.072-96-96s43.072-96 96-96 96 43.072 96 96-43.072 96-96 96zM895.904 278.56C828.8 378.208 723.296 497.856 618.048 601.344c-28.64 28.192-202.272 196.448-348.096 286.112 0.128-0.096 0.224-0.16 0.352-0.224C340.576 933.088 424.288 960 514.272 960c247.04 0 448-200.96 448-448-0.032-85.6-24.544-165.344-66.368-233.44zM640.032 800c-35.296 0-64-28.704-64-64s28.704-64 64-64 64 28.704 64 64-28.704 64-64 64z" p-id="10719"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441239241" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4412" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 960.00035C264.5696 960.00035 63.99965 759.4304 63.99965 512S264.5696 63.99965 512 63.99965 960.00035 264.5696 960.00035 512 759.4304 960.00035 512 960.00035z m-179.20035-403.2a179.20035 179.20035 0 1 0 358.4007 0H332.79965z m0-89.6007a67.2 67.2 0 1 0 0-134.4 67.2 67.2 0 0 0 0 134.4z m358.4007 0a67.2 67.2 0 1 0 0-134.4 67.2 67.2 0 0 0 0 134.4z" p-id="4413"></path></svg>

After

Width:  |  Height:  |  Size: 753 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441342980" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11558" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M957.216 404.32c-3.808-11.36-13.632-19.68-25.504-21.504l-270.336-41.728-120.8-258.624C535.328 71.232 524.032 64.032 511.648 64h-0.064a31.968 31.968 0 0 0-28.928 18.336L360.8 340.352l-270.72 40.8a32.014 32.014 0 0 0-25.568 21.408c-3.84 11.36-0.992 23.936 7.36 32.512l196.448 202.08-46.88 284.8a31.997 31.997 0 0 0 13.12 31.328c9.984 7.072 23.168 7.808 33.888 1.92l241.824-133.024 241.312 133.856a32.547 32.547 0 0 0 15.52 3.968h0.64c17.696 0 32-14.304 32-32 0-3.968-0.704-7.776-2.016-11.296l-44.896-278.688L949.76 436.768c8.32-8.544 11.232-21.088 7.456-32.448z" p-id="11559"></path></svg>

After

Width:  |  Height:  |  Size: 965 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441261013" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5392" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M898.133 341.333c0-10.666-10.666-21.333-21.333-21.333h-128v-8.533C746.667 185.6 646.4 85.333 520.533 85.333h-17.066c-123.734 0-226.134 100.267-226.134 226.134V320h-128C138.667 320 128 328.533 128 341.333l-17.067 518.4v2.134C115.2 917.333 162.133 960 217.6 960h595.2c55.467 0 102.4-42.667 106.667-98.133v-2.134l-21.334-518.4zM320 311.467C320 209.067 403.2 128 503.467 128h17.066C620.8 128 704 211.2 704 311.467V320H320v-8.533z m-21.333 243.2C275.2 554.667 256 535.467 256 512c0-14.933 8.533-29.867 21.333-36.267V384c0-12.8 8.534-21.333 21.334-21.333S320 371.2 320 384v91.733c12.8 6.4 21.333 21.334 21.333 36.267 0 23.467-19.2 42.667-42.666 42.667z m426.666 0c-23.466 0-42.666-19.2-42.666-42.667 0-14.933 8.533-29.867 21.333-36.267V384c0-12.8 8.533-21.333 21.333-21.333S746.667 371.2 746.667 384v91.733C759.467 482.133 768 497.067 768 512c0 23.467-19.2 42.667-42.667 42.667z" p-id="5393"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441323970" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10157" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M947.2 422.4L572.8 115.2c-32-25.6-86.4-25.6-118.4 0L76.8 425.6c-12.8 6.4-16 22.4-9.6 35.2 3.2 12.8 16 19.2 28.8 19.2h32v364.8c0 48 35.2 83.2 83.2 83.2H416c19.2 0 32-12.8 32-32V748.8c0-22.4 35.2-44.8 64-44.8 28.8 0 67.2 22.4 67.2 44.8V896c0 19.2 12.8 32 32 32h208c48 0 80-32 80-83.2V480h32c12.8 0 25.6-9.6 28.8-22.4 3.2-12.8 0-25.6-12.8-35.2z" p-id="10158"></path></svg>

After

Width:  |  Height:  |  Size: 747 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441312875" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9177" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M713 221c-12-9-27-6-36 0-9 9-15 24-9 36 6 12 9 27 12 42C599 110 464 68 458 65c-9-3-21 0-27 6-9 6-12 18-9 27 12 81-24 177-108 291-6-24-15-48-30-75-9-9-21-15-33-12-15 3-24 12-24 27-3 45-24 87-48 132C158 500 137 542 128 587c-30 141 93 309 219 357 9 3 18 6 30 9-24-18-39-48-45-90C308 680 506 632 515 464c144 99 210 315 129 474 3 0 6-3 9-3 0 0 3 0 3-3 153-84 237-195 243-324 15-198-153-366-186-387z" p-id="9178"></path></svg>

After

Width:  |  Height:  |  Size: 797 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441311089" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9037" xmlns:xlink="http://www.w3.org/1999/xlink" width="128.125" height="128"><defs><style type="text/css"></style></defs><path d="M512.26455078 82.10585938C263.58681641 82.10585938 62.52910156 258.29667969 62.52910156 475.22744141c0 11.11113281 0.52910156 22.22226562 1.58730469 33.33339843C74.6984375 619.14306641 137.66152344 716.49775391 231.3125 782.10546875v147.61933594c0 22.75136719 24.86777344 36.50800781 43.91542969 24.86777343l152.90947265-92.59277343c27.51328125 4.2328125 55.55566406 6.87832031 84.12714844 6.87832031 235.45019531 0 428.57138672-158.20048828 448.14814453-359.78818359 1.05820312-11.11113281 2.11640625-22.22226562 2.11640625-33.33339844C962 258.29667969 760.41230469 82.10585938 512.26455078 82.10585938zM286.86728516 458.29619141c0-15.34394531 12.6984375-28.04238281 28.04238281-28.04238282h41.26992187c15.34394531 0 28.04238281 12.6984375 28.04238282 28.04238282s-12.6984375 28.04238281-28.04238282 28.04238281h-41.26992187c-15.34394531 0.52910156-28.04150391-12.16933594-28.04150391-28.04238281z m365.60917968 157.67226562H371.52353516c-15.34394531 0-28.04238281-12.6984375-28.04238282-28.04238281s12.6984375-28.04238281 28.04238282-28.04238281h281.48203125c15.34394531 0 28.04238281 12.6984375 28.04238281 28.04238281-0.52910156 15.34394531-12.6984375 28.04238281-28.57148438 28.04238281z m56.61386719-129.10078125H462.52900391c-15.34394531 0-28.04238281-12.6984375-28.04238282-28.04238281s12.6984375-28.04238281 28.04238282-28.04238281h246.03222656c15.34394531 0 28.04238281 12.6984375 28.04238281 28.04238281 0.52822266 15.34394531-12.16933594 28.04238281-27.51328125 28.04238281z" p-id="9038"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441333584" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10858" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M722 136c-61.83 0-120.54 23.46-165.36 66.06-4.29 4.05-26.88 26.94-44.37 44.7L467.9 202.6C423.05 159.64 364.13 136 302 136 169.67 136 62 243.67 62 376c0 77.28 38.61 135.27 71.7 171.09l297.09 300.12C454.31 870.7 480.41 886 512 886s57.72-15.3 81.33-38.91l296.94-300 2.07-2.31C928.16 500.11 962 457.93 962 376c0-132.33-107.67-240-240-240z" p-id="10859"></path></svg>

After

Width:  |  Height:  |  Size: 740 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441325978" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10297" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M407.467 488.533a106.667 106.667 0 1 0 213.333 0 106.667 106.667 0 1 0-213.333 0z" p-id="10298"></path><path d="M512 64C264.533 64 64 264.533 64 512c0 236.8 183.467 428.8 416 445.867v-134.4c-53.333-59.734-200.533-230.4-200.533-334.934 0-130.133 104.533-234.666 234.666-234.666S748.8 358.4 748.8 488.533c0 61.867-49.067 153.6-145.067 270.934L544 827.733V960c232.533-17.067 416-211.2 416-448 0-247.467-200.533-448-448-448z" p-id="10299"></path></svg>

After

Width:  |  Height:  |  Size: 826 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441337115" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11138" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M871.616 64H152.384c-31.488 0-60.416 25.28-60.416 58.24v779.52c0 32.896 26.24 58.24 60.352 58.24h719.232c34.112 0 60.352-25.344 60.352-58.24V122.24c0.128-32.96-28.8-58.24-60.288-58.24zM286.272 512c-23.616 0-44.672-20.224-44.672-43.008 0-22.784 20.992-43.008 44.608-43.008 23.616 0 44.608 20.224 44.608 43.008A43.328 43.328 0 0 1 286.272 512z m0-202.496c-23.616 0-44.608-20.224-44.608-43.008 0-22.784 20.992-43.008 44.608-43.008 23.616 0 44.608 20.224 44.608 43.008a43.456 43.456 0 0 1-44.608 43.008zM737.728 512H435.904c-23.68 0-44.672-20.224-44.672-43.008 0-22.784 20.992-43.008 44.608-43.008h299.264c23.616 0 44.608 20.224 44.608 43.008A42.752 42.752 0 0 1 737.728 512z m0-202.496H435.904c-23.616 0-44.608-20.224-44.608-43.008 0-22.784 20.992-43.008 44.608-43.008h299.264c23.616 0 44.608 20.224 44.608 43.008a42.88 42.88 0 0 1-42.048 43.008z" p-id="11139"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441316068" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9457" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M910.93333334 214.1088H116.55786667a37.23733333 37.23733333 0 0 1 0-74.47253333H910.93333334a37.23733333 37.23733333 0 0 1 0 74.47253333z m0 695.07946667H116.55786667a37.23733333 37.23733333 0 0 1 0-74.4736H910.93333334a37.23733333 37.23733333 0 0 1 0 74.4736zM712.33920001 561.648H116.55786667a37.23733333 37.23733333 0 0 1 0-74.47253333h595.78133334a37.23733333 37.23733333 0 0 1 0 74.47253333z" p-id="9458"></path></svg>

After

Width:  |  Height:  |  Size: 800 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441267509" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5815" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 67.168c-247.04 0-448 172.256-448 384 0 116.512 63.04 226.048 174.048 301.408l84.16 52.032c-3.68 23.552-18.752 74.496-33.44 115.936-4.256 12.064-0.928 25.504 8.448 34.176a32.006 32.006 0 0 0 21.728 8.512c4.416 0 8.832-0.896 13.024-2.752 36.416-16.224 147.456-68.96 187.584-125.376C763.136 831.616 960 660.704 960 451.168c0-211.744-200.96-384-448-384z m68.224 476.8H384.96c-17.664 0-32-14.336-32-32s14.336-32 32-32h195.264c17.696 0 32 14.336 32 32s-14.304 32-32 32z m60.704-128H384.96c-17.664 0-32-14.336-32-32s14.336-32 32-32h255.968c17.696 0 32 14.336 32 32s-14.304 32-32 32z" p-id="5816"></path></svg>

After

Width:  |  Height:  |  Size: 984 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441278876" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6655" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 133.12c208.896 0 378.88 169.984 378.88 378.88S720.896 890.88 512 890.88 133.12 720.896 133.12 512 303.104 133.12 512 133.12m0-71.68C262.144 61.44 61.44 262.144 61.44 512S264.192 962.56 512 962.56 962.56 759.808 962.56 512 761.856 61.44 512 61.44z" p-id="6656"></path><path d="M602.112 784.384h-2.048c-14.336-2.048-24.576-12.288-28.672-24.576l-67.584-356.352-36.864 129.024c-4.096 12.288-16.384 20.48-28.672 20.48h-36.864l-36.864 92.16c-4.096 12.288-16.384 20.48-28.672 20.48s-24.576-8.192-28.672-20.48l-45.056-135.168-14.336 28.672c-4.096 10.24-16.384 18.432-28.672 18.432H184.32c-16.384 0-30.72-14.336-30.72-30.72s14.336-34.816 30.72-34.816h16.384l38.912-81.92c6.144-12.288 16.384-18.432 30.72-18.432 12.288 0 22.528 8.192 26.624 20.48l40.96 126.976 12.288-30.72c4.096-12.288 16.384-20.48 28.672-20.48h34.816l67.584-229.376c4.096-14.336 16.384-22.528 30.72-22.528s26.624 10.24 28.672 24.576l71.68 374.784 92.16-260.096c4.096-12.288 16.384-20.48 28.672-20.48s24.576 8.192 28.672 20.48l40.96 116.736h36.864c16.384 0 30.72 12.288 30.72 30.72 0 16.384-12.288 30.72-30.72 30.72h-59.392c-14.336 0-24.576-8.192-28.672-20.48l-20.48-55.296-100.352 286.72c-4.096 12.288-16.384 20.48-28.672 20.48z" p-id="6657"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441271889" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6095" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 63.68c-247.04 0-448 172.256-448 384 0 116.48 63.008 226.048 170.592 298.944l87.328 71.52c-3.904 19.328-17.408 60.096-32.64 97.536-4.928 12.096-1.984 25.984 7.36 35.072a32.049 32.049 0 0 0 22.272 8.992c4.384 0 8.8-0.896 12.992-2.752 36.416-16.224 147.488-68.96 187.616-125.376C763.136 828.16 960 657.248 960 447.68c0-211.712-200.96-384-448-384z m219.136 342.88l-128.8 188.864c-5.984 8.736-15.872 13.984-26.432 13.984h-0.448c-10.72-0.16-20.672-5.664-26.464-14.688l-91.584-142.208L385.824 592c-5.664 11.072-16.864 17.408-28.512 17.408-4.896 0-9.92-1.12-14.592-3.52-15.712-8.064-21.92-27.328-13.856-43.072L425.76 373.92a31.925 31.925 0 0 1 26.912-17.344c11.52-0.416 22.272 5.024 28.48 14.656l95.456 148.288L678.24 370.528c9.984-14.592 29.856-18.336 44.48-8.416 14.592 9.92 18.368 29.856 8.416 44.448z" p-id="6096"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441270012" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5955" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M867.2 160H160c-54.4 0-96 44.8-96 96v512c0 54.4 41.6 96 96 96h707.2c54.4 0 96-41.6 96-96V256c0-51.2-41.6-96-96-96z m-672 163.2c0-19.2 12.8-32 32-32H416c19.2 0 32 12.8 32 32V512c0 19.2-12.8 32-32 32H227.2c-19.2 0-32-12.8-32-32V323.2zM800 736H224c-19.2 0-32-12.8-32-32s12.8-32 32-32h576c19.2 0 32 12.8 32 32s-12.8 32-32 32zM512 448c0-19.2 12.8-32 32-32h128c19.2 0 32 12.8 32 32s-12.8 32-32 32H544c-19.2 0-32-12.8-32-32z m288-96H544c-19.2 0-32-12.8-32-32s12.8-32 32-32h256c19.2 0 32 12.8 32 32s-12.8 32-32 32z" p-id="5956"></path></svg>

After

Width:  |  Height:  |  Size: 910 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441252941" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4832" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M736 96c31.04 0 51.712 25.856 51.712 62.08v304.96c-129.28 0-232.64 103.36-227.456 232.576 0 113.728 77.504 206.784 180.928 227.456H115.712c-31.04 0-51.712-25.856-51.712-67.2V158.08c0-36.16 20.672-62.016 51.712-62.016z m43.072 413.568l10.88 0.32C883.328 515.392 960 591.872 960 687.808c0 99.648-82.688 183.552-180.928 183.552h-5.12a179.2 179.2 0 0 1-124.16-52.416c-10.24-10.496-15.424-15.744-20.608-26.24a5.888 5.888 0 0 0-0.832-3.072l-3.52-4.288-0.832-3.136a16 16 0 0 1-3.072-4.736l-4.224-11.52-3.072-4.672c0-5.248-5.12-10.496-5.12-15.744l-1.344-5.248c-1.536-3.52-3.84-7.04-3.84-10.496-5.12-10.496-5.12-26.24-5.12-36.736 0-26.24 5.12-47.168 15.424-68.16v-5.248c0-5.248 5.184-15.744 10.368-20.928 0-1.344 0.32-2.304 0.832-3.2l3.52-4.224 0.832-3.072c30.976-47.232 82.688-78.72 149.888-78.72z m0 52.416c-15.488 0-25.856 10.496-25.856 26.24v125.824c0 15.744 10.368 26.24 25.856 26.24H892.8c10.368 0 25.856-10.496 25.856-26.24 0-15.744-10.368-26.24-25.856-26.24h-87.872v-99.584c0-15.744-10.368-26.24-25.856-26.24zM394.88 468.16H198.4a40.768 40.768 0 0 0-41.344 41.408c0 20.672 15.488 41.344 36.16 41.344h196.48c25.792 0 46.464-15.552 46.464-41.344a40.768 40.768 0 0 0-41.344-41.408z m165.44-206.72H198.4a40.768 40.768 0 0 0-41.344 41.344c0 20.672 15.488 41.344 36.16 41.344h361.856a40.768 40.768 0 0 0 41.344-41.344c0-25.856-15.488-41.344-36.16-41.344z" p-id="4833"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441277399" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6515" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M842.688 128H181.312C116.64 128 64 180.64 64 245.312v533.376C64 843.36 116.64 896 181.312 896h661.376C907.36 896 960 843.36 960 778.688V245.312C960 180.64 907.36 128 842.688 128zM288 288c35.36 0 64 28.64 64 64s-28.64 64-64 64c-35.328 0-64-28.64-64-64s28.672-64 64-64z m544 448c0 17.696-14.304 31.488-32 31.488L225.92 768h-0.352c-10.08 0-19.616-4.288-25.664-12.384-6.112-8.192-7.936-18.56-4.896-28.352 2.304-7.488 58.272-183.552 180.064-183.552 38.08 0.896 67.424 9.824 95.776 18.336 35.712 10.72 70.528 19.936 109.664 13.76 20.448-3.296 28.896-23.808 43.328-69.952 19.04-60.8 47.808-152.736 174.656-152.736 17.536 0 31.776 14.08 32 31.616L832 511.616V736z" p-id="6516"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441273689" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6235" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 64C264.96 64 64 264.96 64 512s200.96 448 448 448 448-200.96 448-448S759.04 64 512 64z m0 768.352c-26.496 0-48-21.504-48-48s21.504-48 48-48 48 21.504 48 48-21.504 48-48 48z m88.576-327.168C572.736 532.992 544 561.728 544 587.552v54.112c0 17.664-14.336 32-32 32s-32-14.336-32-32v-54.112c0-52.352 40-92.352 75.328-127.648C581.216 434.016 608 407.264 608 385.92c0-53.344-43.072-96.736-96-96.736-53.824 0-96 41.536-96 94.56 0 17.664-14.336 32-32 32s-32-14.336-32-32c0-87.424 71.776-158.56 160-158.56S672 297.28 672 385.92c0 47.872-36.32 84.16-71.424 119.264z" p-id="6236"></path></svg>

After

Width:  |  Height:  |  Size: 962 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441308883" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8897" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M228.255 913.307H66.103V672.523h162.152v240.784z m243.21 0H309.319V351.483h162.146v561.824z m243.216 0h-162.14v-321.04h162.14v321.04z m243.215 0H795.744V110.693h162.152v802.614z" p-id="8898"></path></svg>

After

Width:  |  Height:  |  Size: 581 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441284945" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7076" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M699.498496 793.02322252c-102.60024889 65.24472889-212.6764563 85.28175408-330.3135763 55.12305778-99.9424-25.61972148-178.67055408-82.76954075-236.59709629-167.90565927-113.18309925-166.34007703-85.29389037-393.90776889 64.40732444-529.93137778 150.44152889-136.70324148 376.79559111-142.24952889 534.40967112-13.84751407 156.78881185 127.72238222 206.19567408 369.53808592 71.21578666 557.56572445 2.20880592 2.34230518 4.50256592 4.86665482 6.90555259 7.26964148 42.9382163 42.96248889 85.96138667 85.8400237 128.81464889 128.87533037 26.06876445 26.19012741 31.72427852 59.41930667 15.44950519 88.61923555-22.9497363 41.19058963-78.49756445 49.23695408-112.20005927 15.83786667-45.21984-44.79506963-90.06345482-89.96636445-135.08911406-134.96775111-2.24521482-2.23307852-4.5996563-4.35693037-7.00264297-6.63855407z m-227.22787555-639.58281482c-165.40558222 0-300.19128889 134.48229925-300.02138075 299.34174815 0.16990815 164.58031408 134.87066075 299.30533925 299.32961185 299.41456593 165.33276445 0.10922667 300.08206222-134.16675555 300.21556148-299.1597037 0.15777185-165.29635555-134.11821037-299.59661037-299.52379258-299.59661038z" p-id="7077"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441320870" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9877" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M956.17988281 446.79003906c-3.50683594-19.66376953-22.35234375-39.46289063-41.85175781-43.92597656l-14.45800781-3.34248047c-34.29140625-10.35351563-64.74550781-33.27539063-84.08232422-66.74589844-19.49941406-33.71132813-23.93789063-72-15.49863281-107.05693359l4.27148437-13.72060547c5.86230469-19.08984375-1.75253906-45.38144531-16.92421875-58.31103515 0 0-13.74873047-11.61035156-52.47949219-34.01367188-38.72460938-22.37519531-55.53896484-28.48535156-55.53896484-28.48535156-18.78925781-6.79130859-45.30146484-0.32607422-58.88408203 14.35253906l-10.19003906 10.95380859c-26.07363281 24.64892578-61.21142578 39.740625-99.83056641 39.740625-38.80546875 0-74.05488281-15.20068359-100.15488281-40.01396484l-9.83320313-10.62773437C387.1953125 90.94199219 360.65498047 84.44951172 341.86748047 91.24433594c0 0-16.81523438 6.07851562-55.62597656 28.48095703-38.66923828 22.40419922-52.33623047 33.9609375-52.33623047 33.9609375-15.22792969 12.92871094-22.86914063 39.11132813-16.95410156 58.28291016l4.24423828 13.85947265c8.32763672 35.02792969 3.83554687 73.23574219-15.49863282 106.92246094-19.39130859 33.60585937-50.146875 56.58398438-84.57539062 66.82324219l-14.1328125 3.23261718c-19.41503906 4.43847656-38.28955078 24.26572266-41.79550781 43.90136719 0 0-3.17548828 17.66601563-3.17548829 62.49902344 0 44.83564453 3.17548828 62.41992188 3.17548829 62.41992187 3.53320313 19.71826172 22.37871094 39.49189453 41.7946289 44.03759766l13.80761719 3.06914063c34.56298828 10.29550781 65.39941406 33.35712891 84.90234375 67.09921875 19.41503906 33.68671875 23.85351563 71.97539063 15.44414062 107.03320312l-4.18974609 13.69335938c-5.91503906 19.06083984 1.72529297 45.3515625 17.00683594 58.27939453 0 0 13.66699219 11.61298828 52.42148437 34.01542968 38.75361328 22.4578125 55.51611328 28.48623047 55.51611328 28.48623047 18.815625 6.79130859 45.27158203 0.27421875 58.85771485-14.29980468l9.72246094-10.45986329c26.10087891-24.92226562 61.37402344-40.09394531 100.23662109-40.09394531 38.83886719 0 74.16914062 15.28154297 100.37988281 40.09394531h0.02460938l9.61523437 10.46074219c13.58261719 14.57226563 39.98408203 21.09023438 58.82519531 14.29980469 0 0 16.7625-6.13476563 55.65410157-28.48710938 38.67363281-22.40332031 52.36523438-34.01542969 52.36523437-34.01542968 15.2296875-12.92695313 22.78828125-39.10869141 16.98310547-58.28027344l-4.27236328-14.1328125c-8.21777344-34.94619141-3.7265625-73.07226563 15.49863281-106.59287109 19.55566406-33.79658203 50.34111328-56.75097656 84.84785156-67.09921875v-0.05712891l13.80410157-3.17460938c19.50029297-4.43935547 38.34580078-24.21035156 41.84912109-43.93125 0 0 3.17636719-17.63789062 3.17636719-62.49902343-0.10898438-44.64316406-3.28447266-62.28105469-3.28447266-62.28105469z m-445.49121093 207.05449219c-79.61923828 0-144.20039063-64.74462891-144.20039063-144.60820312 0-79.75371094 64.58027344-144.44208984 144.20039063-144.44208985 79.61484375 0 144.11425781 64.71650391 144.11425781 144.55195313 0 79.86357422-64.49941406 144.49833984-144.11425781 144.49833984z" p-id="9878"></path></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441259332" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5252" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M926.54933333 370.9952L645.9392 97.8944c-38.87786667-37.6832-112.81066667-37.75146667-151.79093333 0.1024l-348.84266667 341.23093333c-60.17706667 58.368-75.43466667 81.8176-75.43466667 161.04106667v153.53173333c0 141.6192 28.7744 204.8 199.3728 204.8h140.66346667c86.528 0 137.0112-49.7664 206.88213333-118.6816l309.3504-317.5424c19.83146667-19.18293333 31.19786667-46.8992 31.19786667-76.01493333 0-28.91093333-11.22986667-56.38826667-30.78826667-75.3664zM310.40853333 805.0688c-56.45653333 0-102.4-45.94346667-102.4-102.4s45.94346667-102.4 102.4-102.4 102.4 45.94346667 102.4 102.4-45.94346667 102.4-102.4 102.4z" p-id="5253"></path></svg>

After

Width:  |  Height:  |  Size: 1018 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441304345" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8617" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M672 491.968c-83.648 68.288-160 142.208-160 142.208L373.504 467.2l-67.2 67.2s59.392 68.352 112 134.4C471.104 735.104 512 797.12 512 797.12s108.416-123.968 216.448-224.448c60.736-56.448 135.104-121.728 190.784-169.984v458.88c0 54.336-44.096 98.432-98.432 98.432H203.136c-54.336 0-98.432-44.096-98.432-98.432V310.144c0-12.352 4.8-24.256 13.44-33.088l193.92-198.784C321.024 69.184 333.248 64 345.984 64H820.8c54.336 0 98.432 44.096 98.432 98.432V312.64C861.056 352.128 746.176 431.36 672 491.968z" p-id="8618"></path></svg>

After

Width:  |  Height:  |  Size: 897 B

View File

@ -0,0 +1,12 @@
<svg t="1615283148941" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5045"
width="64" height="64">
<path
d="M552.75 563.239c44.4 26.348 99.1 26.348 143.5 0C740.65 536.89 768 488.197 768 435.5c0-81.462-64.247-147.5-143.5-147.5S481 354.038 481 435.5c0 52.697 27.35 101.39 71.75 127.739z"
p-id="5046"></path>
<path
d="M471.264 952c-18.842 0-38.581-1.796-60.115-4.49l-5.384-0.899c-152.533-23.352-256.614-171.55-261.1-177.837-147.149-224.541-73.574-451.777 65.5-577.52C348.34 65.511 578.934 11.621 780.814 174.19c130.102 105.085 169.58 250.588 171.375 256.875v1.797c18.843 102.39 3.59 177.836-45.76 226.337-75.368 72.752-200.086 49.4-217.134 45.807-23.328-2.695-40.376 4.49-52.938 19.76-13.458 17.064-16.15 39.518-11.664 52.991 12.562 37.723 14.356 66.464 5.384 88.02C604.058 922.361 551.12 952 471.264 952z m-51.973-80.488l5.083 0.849c82.179 12.72 132.164-3.393 152.497-49.188 0-0.849 4.236-11.873-6.778-45.796-11.013-30.53-2.541-70.39 19.486-97.528 22.875-28.834 56.763-41.556 96.581-37.315l2.542 0.848c0.847 0 105.9 22.898 160.122-29.683 33.04-32.226 43.207-88.199 28.805-166.221-3.39-11.025-39.819-130.603-144.872-214.562-166.053-135.69-356.674-90.743-471.894 13.57-105.9 96.68-183.843 280.71-53.374 480.007 0.848 0 89.804 127.21 211.802 145.02z"
p-id="5047"></path>
<path
d="M203 529c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m90-115.235A54 54 0 0 1 266 367c0-29.823 24.177-54 54-54s54 24.177 54 54a54 54 0 0 1-81 46.765zM427 278c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m180 44c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m90 144c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z"
p-id="5048"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441281314" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6796" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 64C264.96 64 64 264.96 64 512s200.96 448 448 448 448-200.96 448-448S759.04 64 512 64z m159.264 512H480.16c-17.664 0-32.16-14.464-32.16-32.16V289.088c0-17.664 14.336-32 32-32s32 14.336 32 32V512h159.264c17.696 0 32 14.336 32 32 0 17.696-14.336 32-32 32z" p-id="6797"></path></svg>

After

Width:  |  Height:  |  Size: 661 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441265116" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5675" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512.13653333 899.75239111H98.48604445c-17.72657778 0-23.19928889-5.24515555-22.96035556-22.8352 0.32995555-25.14488889-0.9216-50.49457778 1.8432-75.38915556 9.92142222-89.15626667 78.21084445-161.57582222 164.27235556-174.54648888 11.42328889-1.71804445 23.08551111-2.63964445 34.64533333-2.65102222 157.16124445-0.17066667 314.31111111-0.11377778 471.47235555-0.11377778 100.16995555 0 183.10257778 69.95057778 197.56373334 169.19893333 4.33493333 29.7984 2.62826667 60.49564445 3.16302222 90.79466667 0.14791111 8.23751111-6.98595555 14.57493333-15.29173334 15.37137778-2.93546667 0.28444445-5.92782222 0.17066667-8.88604444 0.17066666H512.13653333z m201.18186667-560.44657778c0 121.05955555-97.60995555 218.30542222-219.63662222 217.69102222-123.0848-0.6144-218.16888889-102.33173333-216.73528889-220.88817777 1.39946667-115.87128889 97.05244445-217.30417778 222.50382222-215.08551111 121.32124445 2.1504 215.26755555 102.68444445 213.86808889 218.28266666z" p-id="5676"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441283344" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6936" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 64C265.6 64 64 265.6 64 512s201.6 448 448 448 448-201.6 448-448S758.4 64 512 64z m179.2 480l-256 156.8c-6.4 3.2-12.8 3.2-19.2 3.2-6.4 0-9.6 0-16-3.2-9.6-6.4-16-16-16-28.8V352c0-12.8 6.4-22.4 16-28.8 9.6-6.4 22.4-6.4 32 0l256 166.4c9.6 6.4 16 16 16 28.8 0 9.6-3.2 22.4-12.8 25.6z" p-id="6937"></path></svg>

After

Width:  |  Height:  |  Size: 687 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441288344" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7356" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M677 339.66666667c36-36 75-90 75-147 0-33-9-60-30-81C683 72.66666667 614 72.66666667 536 72.66666667h-57c-75 0-135 0-174 36-21 21-30 48-30 84 0 60 39 111 72 147C215 408.66666667 125 546.66666667 125 687.66666667c0 261 264 261 390 261s390 0 390-261c0-144-93-279-228-348z m-72 246c18 0 30 12 30 30s-12 30-30 30h-60v30h60c18 0 30 12 30 30s-12 30-30 30h-60v63c0 18-12 30-30 30s-30-12-30-30v-63h-60c-18 0-30-12-30-30s12-30 30-30h60v-30h-60c-18 0-30-12-30-30s12-30 30-30h60V567.66666667l-84-81c-12-12-12-30 0-42 12-12 30-12 42 0l75 72 75-72c12-12 30-12 42 0 12 12 12 30 0 42l-90 87v12h60z" p-id="7357"></path></svg>

After

Width:  |  Height:  |  Size: 986 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441293293" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7776" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M942.656 769.376L602.112 159.584c-22.144-39.712-55.104-62.496-90.304-62.496-35.232 0-68.16 22.784-90.368 62.528L81.312 769.344C59.296 808.8 57.056 848.8 75.2 879.744 93.344 910.624 129.664 928 174.88 928h674.24c45.184 0 81.536-17.376 99.648-48.256 18.176-30.944 15.904-70.912-6.112-110.368zM480 320c0-17.664 14.336-32 32-32s32 14.336 32 32v288c0 17.696-14.336 32-32 32s-32-14.304-32-32V320z m32 512.128c-26.528 0-48-21.504-48-48s21.472-48 48-48 48 21.504 48 48-21.472 48-48 48z" p-id="7777"></path></svg>

After

Width:  |  Height:  |  Size: 881 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441286553" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7216" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M897.8 93.32H126.26c-35.52 0-64.26 28.8-64.26 64.32v548.1c0 35.52 28.74 64.2 64.26 64.2h321.42v96.42H287a32.1 32.1 0 0 0-32.1 32.1v32.1h514.2v-32.1a32.04 32.04 0 0 0-32.1-32.1H576.26V770h321.36c35.52 0 64.32-28.74 64.32-64.2V157.7a64.2 64.2 0 0 0-64.14-64.38zM512 737.9a32.1 32.1 0 1 1 0-64.2 32.1 32.1 0 0 1 0 64.2z m360-95.88H152V180.74h720v461.28z" p-id="7217"></path></svg>

After

Width:  |  Height:  |  Size: 754 B

17
src/main.ts Normal file
View File

@ -0,0 +1,17 @@
import { createApp } from "vue";
import App from "./App.vue";
import { bootstrap } from "./cool";
// mock
// import "./mock";
const app = createApp(App);
// 启动
bootstrap(app)
.then(() => {
app.mount("#app");
})
.catch((err) => {
console.error("COOL-ADMIN 启动失败", err);
});

3
src/mock/index.ts Normal file
View File

@ -0,0 +1,3 @@
// @ts-nocheck
const xhr = new window._XMLHttpRequest();
window.XMLHttpRequest.prototype.upload = xhr.upload;

View File

@ -0,0 +1,4 @@
import "./resize";
export * from "./theme";
export * from "./permission";

View File

@ -0,0 +1,30 @@
import { useBaseStore } from "../store";
import { isObject } from "lodash";
function parse(value: any) {
const { menu } = useBaseStore();
if (typeof value == "string") {
return value ? menu.perms.some((e: any) => e.includes(value.replace(/\s/g, ""))) : false;
} else {
return Boolean(value);
}
}
export function checkPerm(value: any) {
if (!value) {
return false;
}
if (isObject(value)) {
if (value.or) {
return value.or.some(parse);
}
if (value.and) {
return value.and.some((e: any) => !parse(e)) ? false : true;
}
}
return parse(value);
}

View File

@ -0,0 +1,13 @@
import { useEventListener } from "@vueuse/core";
import { useBaseStore } from "../store";
function resize() {
const { app } = useBaseStore();
app.setBrowser();
app.isFold = app.browser.isMini;
}
window.onload = function () {
useEventListener(window, "resize", resize);
resize();
};

View File

@ -0,0 +1,39 @@
import { config } from "/@/cool";
import { basename } from "/@/cool/utils";
import { createLink } from "../utils";
// 主题初始化
if (config.app.theme) {
const { url, color } = config.app.theme;
if (url) {
createLink(url, "theme-style");
}
document.getElementsByTagName("body")[0].style.setProperty("--color-primary", color);
}
// 字体图标库加载
if (config.app.iconfont) {
config.app.iconfont.forEach((e: string) => {
createLink(e);
});
}
// 默认
createLink("//at.alicdn.com/t/font_3254019_60a2xxj8uus.css");
// svg 图标加载
const svgFiles = import.meta.globEager("/src/icons/svg/**/*.svg");
function iconList() {
const list: string[] = [];
for (const i in svgFiles) {
list.push(basename(i).replace(".svg", ""));
}
return list;
}
export { iconList };

View File

@ -0,0 +1,110 @@
<template>
<div class="cl-avatar" :class="[size, shape]" :style="[style]">
<el-image :src="src || modelValue" alt="头像">
<template #error>
<div class="image-slot">
<el-icon :size="20" :color="color"><user /></el-icon>
</div>
</template>
</el-image>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import { isNumber } from "lodash";
import { User } from "@element-plus/icons-vue";
export default defineComponent({
name: "cl-avatar",
components: {
User
},
props: {
modelValue: String,
src: String,
size: {
type: [String, Number],
default: 36
},
shape: {
type: String as PropType<"square" | "circle">,
default: "square"
},
backgroundColor: {
type: String,
default: "#f7f7f7"
},
color: {
type: String,
default: "#ccc"
}
},
setup(props) {
const size = isNumber(props.size) ? props.size + "px" : props.size;
const style = computed(() => {
return {
height: size,
width: size,
backgroundColor: props.backgroundColor
};
});
return {
style
};
}
});
</script>
<style lang="scss" scoped>
.cl-avatar {
overflow: hidden;
margin: 0 auto;
&.large {
height: 50px;
width: 50px;
}
&.medium {
height: 40px;
width: 40px;
}
&.small {
height: 30px;
width: 30px;
}
&.circle {
border-radius: 100%;
}
&.square {
border-radius: 10%;
}
img {
height: 100%;
width: 100%;
}
.el-image {
height: 100%;
width: 100%;
.image-slot {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div ref="editorRef" class="cl-codemirror">
<textarea id="editor" class="cl-code" :height="height" :width="width"></textarea>
<div class="cl-codemirror__tools">
<el-button @click="formatCode">格式化</el-button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, nextTick, onMounted, ref, watch } from "vue";
import CodeMirror from "codemirror";
import beautifyJs from "js-beautify";
import "codemirror/lib/codemirror.css";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/theme/hopscotch.css";
import "codemirror/addon/hint/javascript-hint";
import "codemirror/mode/javascript/javascript";
import { deepMerge } from "/@/cool/utils";
export default defineComponent({
name: "cl-codemirror",
props: {
modelValue: null,
height: String,
width: String,
options: Object
},
emits: ["update:modelValue", "load"],
setup(props, { emit }) {
const editorRef = ref<any>(null);
let editor: any = null;
//
function getValue() {
if (editor) {
return editor.getValue();
} else {
return "";
}
}
//
function setValue(val?: string) {
if (editor) {
editor.setValue(val || "");
}
}
//
function formatCode() {
if (editor) {
editor.setValue(beautifyJs(getValue()));
}
}
//
watch(
() => props.modelValue,
(val: string) => {
if (editor && val != getValue()) {
setValue(val);
}
}
);
onMounted(function () {
nextTick(() => {
//
editor = CodeMirror.fromTextArea(
editorRef.value.querySelector("#editor"),
deepMerge(
{
mode: "javascript",
theme: "hopscotch",
styleActiveLine: true,
lineNumbers: true,
lineWrapping: true,
indentWithTabs: true,
indentUnit: 4,
extraKeys: { Ctrl: "autocomplete" },
foldGutter: true,
autofocus: true,
matchBrackets: true,
autoCloseBrackets: true,
gutters: [
"CodeMirror-linenumbers",
"CodeMirror-foldgutter",
"CodeMirror-lint-markers"
]
},
props.options
)
);
//
editor.on("change", (e: any) => {
emit("update:modelValue", e.getValue());
});
//
setValue(props.modelValue);
//
formatCode();
//
emit("load", editor);
//
editor.setSize(props.width || "auto", props.height || "auto");
});
});
return {
editorRef,
formatCode
};
}
});
</script>
<style lang="scss">
.cl-codemirror {
border-radius: 3px;
border: 1px solid #dcdfe6;
box-sizing: border-box;
border-radius: 3px;
line-height: 150%;
&__tools {
background-color: #322931;
padding: 10px;
border-top: 1px solid #444;
}
}
</style>

View File

@ -0,0 +1,30 @@
<template>
<span class="cl-date-text">{{ value }}</span>
</template>
<script lang="ts">
import { defineComponent, computed } from "vue";
import dayjs from "dayjs";
export default defineComponent({
name: "cl-date-text",
props: {
modelValue: [String, Number],
format: {
type: String,
default: "YYYY-MM-DD HH:mm:ss"
}
},
setup(props) {
const value = computed(() => {
return props.modelValue ? dayjs(props.modelValue).format(props.format) : "";
});
return {
value
};
}
});
</script>

View File

@ -0,0 +1,256 @@
<template>
<div class="cl-editor-quill">
<div ref="Editor" class="editor" :style="style"></div>
<cl-upload-space ref="Upload" :show-btn="false" @confirm="onUploadConfirm" />
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref, watch } from "vue";
import Quill from "quill";
import "quill/dist/quill.snow.css";
import { isNumber } from "lodash";
export default defineComponent({
name: "cl-editor-quill",
props: {
modelValue: null,
options: Object,
height: [String, Number],
width: [String, Number]
},
emits: ["update:modelValue", "load"],
setup(props, { emit }) {
let quill: any = null;
const Editor = ref<any>();
const Upload = ref<any>();
//
const content = ref<string>("");
//
const cursorIndex = ref<number>(0);
//
function uploadFileHandler() {
const selection = quill.getSelection();
if (selection) {
cursorIndex.value = selection.index;
}
Upload.value.open();
}
//
function onUploadConfirm(files: any[]) {
if (files.length > 0) {
//
files.forEach((file, i) => {
if (file.type == "image") {
quill.insertEmbed(
cursorIndex.value + i,
file.type,
file.url,
Quill.sources.USER
);
}
});
//
quill.setSelection(cursorIndex.value + files.length);
}
}
//
function setContent(val: string) {
quill.root.innerHTML = val || "";
}
//
const style = computed<any>(() => {
const height = isNumber(props.height) ? props.height + "px" : props.height;
const width = isNumber(props.width) ? props.width + "px" : props.width;
return {
height,
width
};
});
//
watch(
() => props.modelValue,
(val: string) => {
if (val) {
if (val !== content.value) {
setContent(val);
}
} else {
setContent("");
}
}
);
onMounted(function () {
//
quill = new Quill(Editor.value, {
theme: "snow",
placeholder: "输入内容",
modules: {
toolbar: [
["bold", "italic", "underline", "strike"],
["blockquote", "code-block"],
[{ header: 1 }, { header: 2 }],
[{ list: "ordered" }, { list: "bullet" }],
[{ script: "sub" }, { script: "super" }],
[{ indent: "-1" }, { indent: "+1" }],
[{ direction: "rtl" }],
[{ size: ["small", false, "large", "huge"] }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ font: [] }],
[{ align: [] }],
["clean"],
["link", "image"]
]
},
...props.options
});
//
quill.getModule("toolbar").addHandler("image", uploadFileHandler);
//
quill.on("text-change", () => {
content.value = quill.root.innerHTML;
emit("update:modelValue", content.value);
});
//
setContent(props.modelValue);
//
emit("load", quill);
});
return {
Editor,
Upload,
content,
quill,
cursorIndex,
style,
setContent,
onUploadConfirm
};
}
});
</script>
<style lang="scss" scoped>
.cl-editor-quill {
background-color: #fff;
.ql-snow {
line-height: 22px !important;
}
.el-upload,
#quill-upload-btn {
display: none;
}
.ql-snow {
border: 1px solid #dcdfe6;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More