提交代码

This commit is contained in:
2025-04-12 14:54:02 +08:00
parent f7761e99a1
commit a2e89f5ea1
599 changed files with 194300 additions and 0 deletions

109
src/App.vue Normal file
View File

@ -0,0 +1,109 @@
<template>
<router-view v-slot="{ Component }" v-if="isRouterAlive">
<keep-alive :include="store.getters.keepLiiveRoute">
<Component :is="Component"></Component>
</keep-alive>
</router-view>
</template>
<script setup>
import { ref, nextTick, provide, onMounted } from "vue";
import { useStore } from "vuex";
import { getItem } from "@/utils/storage";
import { qcckPost, qcckGet, qcckPut, qcckDelete } from "@/api/qcckApi.js";
import { generateNewStyle, writeNewStyle } from "@/utils/theme";
const store = useStore();
generateNewStyle(store.getters.mainColor).then((newStyle) => {
writeNewStyle(newStyle);
});
const isRouterAlive = ref(true);
const reload = () => {
isRouterAlive.value = false;
nextTick(() => {
isRouterAlive.value = true;
});
};
provide("reload", reload);
onMounted(() => {
let dept = getItem("deptId");
document.title = "林芝";
});
</script>
<style lang="scss">
@import "./styles/index.scss";
body {
margin: 0px;
padding: 0px;
font-size: 14px;
}
ul {
margin: 0px;
padding: 0px;
}
li {
list-style-type: none;
}
#app {
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, SimSun, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #fff;
overflow-x: auto;
background:#263445;
}
//只显示一排内容
.one_text_detail {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
//只显示二排内容
.two_text_detail {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
//只显示三排内容
.text_detail {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}
// 不显示滚动条
.noScollLine::-webkit-scrollbar {
width: 0 !important;
}
v-deep .el-loading-mask {
background: rgba(0, 0, 0, 0.5) !important;
}
@font-face {
font-family: "DigifaceWide";
src: url("~@/assets/font/DigifaceWide.ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "HANYILINGXINTIJIAN";
src: url("~@/assets/font/HANYILINGXINTIJIAN-1.TTF");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "YSBTH";
src: url("~@/assets/font/YSBTH.ttf");
font-weight: normal;
font-style: normal;
}
</style>

66
src/api/qcckApi.js Normal file
View File

@ -0,0 +1,66 @@
import request from "@/utils/request";
import axios from "axios";
const api = "/mosty-api";
const egisSpace = "/egis-space";
// 选择站口名称
export function egisSpaceGet(fun,coords){
let params = {
pageNum: 1,
pageSize: 1000,
keyword: "",
geometry: `{"type":"Polygon","coordinates":${JSON.stringify(coords)}}`,
};
params.geometry = encodeURIComponent(params.geometry)
let url = egisSpace + '/space/search/custom/ms-dy-intersections'
axios.get(url,{params}).then((res) => {
fun(res.data)
});
}
//get 请求
export const qcckFlvGet = (params = {}, url) => {
return request({
url: url,
method: "get",
params
});
};
//get 请求
export const qcckGet = (params = {}, url) => {
return request({
url: api + url,
method: "get",
params
});
};
//post 请求
export const qcckPost = (data = {}, url) => {
return request({
url: api + url,
method: "post",
data
});
};
//put 请求
export const qcckPut = (data = {}, url) => {
return request({
url: api + url,
method: "put",
data
});
};
//put 请求
export const qcckDelete = (data = {}, url) => {
return request({
url: api + url,
method: "delete",
data
});
};

108
src/api/sys.js Normal file
View File

@ -0,0 +1,108 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-base";
/*
* 登录
* return promise 实例对象
*/
export const login = (data) => {
return request({
url: api + "/login",
method: "POST",
data
});
};
/*
* 获取用户信息
* return promise 实例对象
*/
export const getUserInfo = () => {
return request({
url: api + "/sys/profile",
method: "GET"
});
};
/*
* 获取用户信息
* return promise 实例对象
*/
export const getKaptcha = () => {
return request({
url: api + "/kaptcha",
method: "GET"
});
};
/*
* 多部门时候 切换部门刷新token
* return promise 实例对象
*/
export const refreshToken = (data) => {
return request({
url: api + `/token`,
method: "POST",
data
});
};
/*
*
登出
* return promise 实例对象
*/
export const loginOut = (data) => {
return request({
url: api + "/loginOut",
method: "POST",
data
});
};
/*
*
修改密码
*/
export const editPassword = (data) => {
return request({
url: api + "/sysUser/editPassword",
method: "POST",
data
});
};
// 人员排名统计TOP10
export const ryStatistics = (data) => {
return request({
url: api + "/monitor/operlog/ryStatistics",
method: "POST",
data
});
};
// 部门排名统计TOP10
export const bmStatistics = (data) => {
return request({
url: api + "/monitor/operlog/bmStatistics",
method: "POST",
data
});
};
// 模块排名统计
export const mkStatistics = (data) => {
return request({
url: api + "/monitor/operlog/mkStatistics",
method: "POST",
data
});
};
// 系统使用情况统计数字
export const useStatistics = (data) => {
return request({
url: api + "/monitor/operlog/statistics",
method: "POST",
data
});
};

156
src/api/sysDict.js Normal file
View File

@ -0,0 +1,156 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-base";
/*
* 登录
* return promise 实例对象
*/
export const login = (data) => {
return request({
url: api + "/sys/login",
method: "POST",
data
});
};
/*
* 分页查询所有字典信息
*
*/
export const getAllSysDict = (params) => {
return request({
url: api + "/sysDict/selectPage",
method: "GET",
params
});
};
/*
* 根据字典组件枚举,查询字典信息
*
*/
export const getDictInfoByDictEnum = (params) => {
return request({
url: api + `/sysDict/getElementSysDict`,
method: "GET",
params
});
};
/*
* 修改字典信息
*
*/
export const updateSysDict = (data) => {
return request({
url: api + `/sysDict/updateSysDict`,
method: "POST",
data
});
};
/*
* 新增字典信息
*
*/
export const addSysDict = (data) => {
return request({
url: api + `/sysDict/addSysDict`,
method: "POST",
data
});
};
/*
* 删除字典信息
*
*/
export const deleteSysDict = (data) => {
return request({
url: api + `/sysDict/deleteSysDict`,
method: "POST",
data
});
};
/*
*
根据字典明细编号,查询所有子字典明细信息
*
*/
export const getAllChildItemByCode = (params) => {
return request({
url: api + "/sys-dict-item/getAllChildItemByCode",
method: "GET",
params
});
};
/*
* 根据字典明细编号查询子字典明细信息
*
*/
export const getChildItemByCode = (params) => {
return request({
url: api + "/sys-dict-item/getChildItemByCode",
method: "GET",
params
});
};
/*
* 根据字典编号查询字典信息
*
*/
export const getSysDictByCode = (params) => {
return request({
url: api + "/sysDict/getSysDictByCode",
method: "GET",
params
});
};
/*
* 根据字典编号查询字典信息
*
*/
export const getSysDictByCodeList = (params) => {
return request({
url: api + "/sys-dict-item/selectPage",
method: "GET",
params
});
};
/*
* 修改字典明细信息
*
*/
export const updateSysDictItem = (data) => {
return request({
url: api + "/sys-dict-item/updateSysDictItem",
method: "POST",
data
});
};
/*
*
添加字典明细信息 item
*
*/
export const addSysDictItem = (data) => {
return request({
url: api + `/sys-dict-item/addSysDictItem`,
method: "POST",
data
});
};
/*
* 删除字典信息
*
*/
export const deleteSysDictItem = (data) => {
return request({
url: api + `/sys-dict-item/deleteSysDictItem`,
method: "POST",
data
});
};

606
src/api/user-manage.js Normal file
View File

@ -0,0 +1,606 @@
import request from "@/utils/request";
const api = "/mosty-api/mosty-base";
/*
* 登录
* return promise 实例对象
*/
export const login = (data) => {
return request({
url: api + "/sys/login",
method: "POST",
data
});
};
/*
* 获取所有角色
*
*/
export const getRoleList = (params) => {
return request({
url: api + "/sysRole/selectPage",
method: "GET",
params
});
};
/*
* 新增角色
*/
export const addSysRole = (data) => {
return request({
url: api + "/sysRole/addSysRole",
method: "POST",
data
});
};
/*
* 修改角色信息
*/
export const updateSysRole = (data) => {
return request({
url: api + "/sysRole/updateSysRole",
method: "POST",
data
});
};
/*
*
删除角色信息
*/
export const deleteSysRole = (data) => {
return request({
url: api + "/sysRole/deleteSysRole",
method: "POST",
data
});
};
/*
*
删除用户
*/
export const deleteSysUser = (data) => {
return request({
url: api + "/sysUser/deleteSysUser",
method: "POST",
data
});
};
/*
*
分页查询岗位信息
*
*/
export const selectJobPage = (params) => {
return request({
url: api + "/sysPosition/selectPage",
method: "GET",
params
});
};
/*
* 修改岗位
*/
export const updateSysPosition = (data) => {
return request({
url: api + "/sysPosition/updateSysPosition",
method: "POST",
data
});
};
/*
* 修改岗位
*/
export const addSysPosition = (data) => {
return request({
url: api + "/sysPosition/addSysPosition",
method: "POST",
data
});
};
/*
*
删除角色信息
*/
export const deleteSysPosition = (data) => {
return request({
url: api + "/sysPosition/deleteSysPosition",
method: "POST",
data
});
};
/*
*分页查询菜单信息
*
*/
export const getSystemMeny = (params) => {
return request({
url: api + "/sysMenu/selectPage",
method: "GET",
params
});
};
/*
*添加菜单
*
*/
export const addSysMenu = (data) => {
return request({
url: api + "/sysMenu/addSysMenu",
method: "POST",
data
});
};
/*
*编辑菜单
*
*/
export const updateSysMenu = (data) => {
return request({
url: api + "/sysMenu/updateSysMenu",
method: "POST",
data
});
};
/*
*删除菜单
*
*/
export const deleteSysMenu = (data) => {
return request({
url: api + "/sysMenu/deleteSysMenu",
method: "POST",
data
});
};
/*
*分页查询菜单信息
*
*/
export const getSysConfigList = (params) => {
return request({
url: api + "/sys-config/selectPage",
method: "GET",
params
});
};
/*
*
添加系统配置
*
*/
export const addSysConfig = (data) => {
return request({
url: api + "/sys-config/addSysConfig",
method: "POST",
data
});
};
/*
*
删除系统配置信息
*
*/
export const deleteSysConfig = (data) => {
return request({
url: api + "/sys-config/deleteSysConfig",
method: "POST",
data
});
};
/*
*
修改系统配置信息
*
*/
export const updateSysConfig = (data) => {
return request({
url: api + "/sys-config/updateSysConfig",
method: "POST",
data
});
};
/* 部门 */
/*
*
添加部门
*
*/
export const addSysDept = (data) => {
return request({
url: api + "/sysDept/addSysDept",
method: "POST",
data
});
};
/*
*
删除部门
*
*/
export const deleteSysDept = (data) => {
return request({
url: api + "/sysDept/deleteSysDept",
method: "POST",
data
});
};
/*
*
修改部门
*
*/
export const updateSysDept = (data) => {
return request({
url: api + "/sysDept/updateSysDept",
method: "POST",
data
});
};
/*
*
分页查询部门信息
*
*/
export const selectDeptPage = (params) => {
return request({
// url: api + "/sysDept/selectPage",
url: api + "/sysDept/selectDept",
method: "GET",
params
});
};
/* 部门 end*/
/* 部门 */
/*
*
添加系统版本管理
*
*/
export const addVersionManage = (data) => {
return request({
url: api + "/sys-version-manage/addVersionManage",
method: "POST",
data
});
};
/*
*
删除系统版本管理信息
*
*/
export const deleteVersionManage = (params) => {
return request({
url: api + "/sys-version-manage/deleteVersionManage",
method: "GET",
params
});
};
/*
*
修改系统版本管理
*
*/
export const updateVersionManage = (data) => {
return request({
url: api + "/sys-version-manage/updateVersionManage",
method: "POST",
data
});
};
/* 系统版本管理*/
export const getSysVersionList = (params) => {
return request({
url: api + "/sys-version-manage/selectPage",
method: "GET",
params
});
};
/* 部门 end*/
/*操作日志 */
export const getOperlogList = (data) => {
return request({
url: api + "/monitor/operlog/list",
method: "POST",
data
});
};
/*删除日志 */
export const operlogRemove = (data) => {
return request({
url: api + "/monitor/operlog/remove",
method: "POST",
data
});
};
/*clean日志 */
export const operlogClean = (data) => {
return request({
url: api + "/monitor/operlog/clean",
method: "POST",
data
});
};
//详情
export const operlogDetail = (id) => {
return request({
url: api + `/monitor/operlog/detail/${id}`,
method: "GET"
});
};
/*日志 end*/
/*登录日志 */
export const getSysLoginLogList = (data) => {
return request({
url: api + "/sysLoginLog/list",
method: "POST",
data
});
};
/*删除日志 */
export const sysLogRemove = (data) => {
return request({
url: api + "/sysLoginLog/remove",
method: "POST",
data
});
};
/*clean日志 */
export const LoginlogClean = (data) => {
return request({
url: api + "/sysLoginLog/clean",
method: "POST",
data
});
};
//详情
export const sysLoginogDetail = (id) => {
return request({
url: api + `/sysLoginLog/detail/${id}`,
method: "POST"
});
};
/*登录日志 end*/
/*用户模块*/
/*分页查询用户信息 */
export const getSysUserList = (params) => {
return request({
url: api + "/sysUser/selectPage",
method: "GET",
params
});
};
/*编辑用户信息 */
export const editSysUser = (data) => {
return request({
url: api + "/sysUser/editSysUser",
method: "POST",
data
});
};
/*添加用户信息 */
export const addUser = (data) => {
return request({
url: api + "/sysUser/addUser",
method: "POST",
data
});
};
/*编辑密码 */
export const editPassword = (data) => {
return request({
url: api + "/sysUser/editPassword",
method: "POST",
data
});
};
/*根据id查询用户信息 */
export const getUserInfoToId = (id) => {
return request({
url: api + `/sysUser/getUserInfo/${id}`,
method: "GET"
});
};
/*用户模块end*/
// 查询所有子部门树
export const getAllChildDeptList = (data) => {
return request({
url: api + `/sysDept/getAllChildDeptList`,
method: "POST",
data
});
};
/*
* //通过 userId获取 角色列表
*
*/
export const getUserRoleList = (params) => {
return request({
url: api + `/sysRole/getUserRoleList/${params}`,
method: "GET"
});
};
/*
* //通过 部门id 获取 角色列表
*
*/
export const selectRolePageByDept = (params) => {
return request({
url: api + `/sysDept/selectRolePageByDept`,
method: "GET",
params
});
};
//为用户 授予角色
export const grantRoleToUser = (data) => {
return request({
url: api + `/sysRole/grantRoleToUser`,
method: "POST",
data
});
};
//为部门 授予角色
export const saveRoleDeptInfo = (data) => {
return request({
url: api + `/sysDept/saveRoleDeptInfo`,
method: "POST",
data
});
};
// 添加数据权限
export const saveDataPermission = (data) => {
return request({
url: api + `/sysRole/saveDataPermission`,
method: "POST",
data
});
};
/*分页查询 所有用户
未绑定当前角色的用户 传当前角色id
*/
export const selectUnAccreditPage = (params) => {
return request({
url: api + "/sysUser/selectUnAccreditPage",
method: "GET",
params
});
};
// 查询当前角色下 的所有用户
export const getRoleUserList = (params) => {
return request({
url: api + `/sysRole/getRoleUserList`,
method: "GET",
params
});
};
// 查询当前部门 的所有用户
export const selectUserPageByDept = (params) => {
return request({
url: api + `/sysDept/selectUserPageByDept`,
method: "GET",
params
});
};
// 批量解绑用户角色
export const batchUnboundUserRole = (data) => {
return request({
url: api + `/sysRole/batchUnboundUserRole`,
method: "POST",
data
});
};
// 重置密码
export const resetPassword = (params) => {
return request({
url: api + `/sysUser/resetPassword`,
method: "GET",
params
});
};
// 为角色授予用户
export const grantUserToRole = (data) => {
return request({
url: api + `/sysRole/grantUserToRole`,
method: "POST",
data
});
};
// 获取角色对应权限
export const getRoleMenuIds = (roleId) => {
return request({
url: api + `/sysRole/getRoleMenuIds/${roleId}`,
method: "GET"
});
};
// 获取所有菜单权限
export const getMenuTree = (params) => {
return request({
url: api + `/sysMenu/selectList`,
method: "GET",
params
});
};
// 为角色修改权限
export const saveRoleMenuInfo = (data) => {
return request({
url: api + `/sysRole/saveRoleMenuInfo`,
method: "POST",
data
});
};
// 获取用户列表
export const getPasswordLevel = (params) => {
return request({
url: api + `/sysUser/getPasswordLevel`,
method: "GET",
params
});
};
// 获取带部门的用户列表
export const selectUserDeptPage = (data = {}) => {
return request({
url: api + `/sysUser/selectUserDeptPage`,
method: "POST",
data
});
};
///unifiedLogin
export const unifiedLogin = (data) => {
return request({
url: api + `/unifiedLogin`,
method: "POST",
data
});
};

View File

@ -0,0 +1,273 @@
::v-deep .el-button--default {
color: #fff;
border: 1px solid #cccccc;
background: #818080;
}
::v-deep .el-button {
color: #fff;
border: 1px solid #cccccc;
--el-button-bg-color: #818080;
}
::v-deep .el-button:focus,
::v-deep .el-button:hover {
background-color: #818080;
}
:v-deep .el-card {
border: 1px solid #146bbe;
background: #00143d;
padding: 10px 0;
}
::v-deep .el-form-item__label {
color: #fff;
}
::v-deep .el-input__inner {
background-color: #ffffff;
border: 1px solid #e9e9e9;
color: #000;
&:hover {
border: 1px solid #0065d8;
}
&:focus {
border: 1px solid #1c84fa;
box-shadow: 0px 0px 8px #0a6bfc;
}
}
.el-button.is-disabled,
.el-button.is-disabled:focus,
.el-button.is-disabled:hover {
color: var(--el-button-disabled-text-color);
cursor: not-allowed;
background-image: none;
background-color: #808596;
border-color: var(--el-button-disabled-border-color);
}
::v-deep .el-input-group__append {
background-color: #ffffff;
border: 1px solid #e9e9e9;
color: #000;
}
::v-deep .el-select:hover:not(.el-select--disabled) .el-input__inner {
border: 1px solid #0065d8;
}
::v-deep .el-table {
background-color: #ffffff;
--el-table-border-color: #e4e7ed;
--el-table-row-hover-bg-color: #f5f7fa;
}
::v-deep .el-table__inner-wrapper{
background: #fff;
}
::v-deep .el-table th.el-table__cell {
background: #ffffff;
color: #000;
}
::v-deep .el-table td.el-table__cell {
color: #000;
background: #ffffff;
}
::v-deep .el-pagination button:disabled {
background-color: transparent;
color: #84a2be;
}
::v-deep .el-pagination button {
background-color: transparent;
color: rgb(255, 255, 255);
}
::v-deep .el-pager li {
background: transparent;
color: #8fceff;
}
::v-deep .el-pager li.active {
background: transparent;
color: #ffa861;
}
::v-deep .el-tree {
background: transparent;
color: #24b6dd;
}
::v-deep .el-checkbox {
color: #fff;
}
// ::v-deep .el-tree-node__content {
// background: none;
// }
::v-deep .is-focusable {
background:transparent !important;
}
::v-deep .el-tree-node__label {
background: #1f4164 !important;
}
::v-deep .el-tree-node__content:hover {
color: #61f9ff;
background: transparent;
}
::v-deep .el-button--primary {
background: #1983e5;
border: 1px solid #1983e5;
&:hover {
background: #0084ff;
border: 1px solid #0084ff;
}
}
::v-deep .el-dialog__title {
color: #fff;
}
::v-deep .el-dialog__header,
::v-deep .el-dialog__body,
::v-deep .el-dialog__footer,
::v-deep .el-card__body,
::v-deep .el-table {
// background: #02163b;
background: #02163b;
}
::v-deep .user-main-wrap {
border: 1px solid #07376d;
}
::v-deep .el-textarea__inner {
background-color: #ffffff;
border: 1px solid #e9e9e9;
color: #000;
&:hover {
border: 1px solid #0065d8;
}
&:focus {
border: 1px solid #1c84fa;
box-shadow: 0px 0px 8px #0a6bfc;
}
}
::v-deep .el-input .el-input__count .el-input__count-inner {
background: transparent;
color: #fff;
}
::v-deep .el-textarea .el-input__count {
background: transparent;
color: #fff;
}
::v-deep .el-select__popper.el-popper {
background: #16284c;
border: #16284c;
}
::v-deep .el-range-input {
background: transparent;
color: #fff;
}
::v-deep .el-range-separator {
color: #fff;
}
::v-deep .el-button--danger {
background: #f56c6c;
border: 1px solid #f56c6c;
}
::v-deep .el-tree {
--el-tree-node-hover-bg-color: #083960;
}
::v-deep .el-tree-node__label {
background: transparent !important;
}
::v-deep .el-card {
border: 1px solid #07539a;
color: #fff;
}
::v-deep .el-collapse {
background: transparent;
color: #fff;
--el-collapse-header-bg-color: transparent;
--el-collapse-header-text-color: #fff;
--el-collapse-content-bg-color: transparent;
--el-collapse-content-text-color: #fff;
--el-collapse-border-color: #0d3f6e;
}
::v-deep .el-tabs__item {
color: rgb(206, 208, 220);
}
::v-deep .el-tabs__nav-wrap::after {
background: #0d3f6e;
}
::v-deep .el-upload--picture-card {
background-color: #112b63;
border: 1px dashed #4579b5;
}
::v-deep .el-upload-list--picture-card .el-upload-list__item {
background-color: #10295b;
border: 1px solid #19538a;
color: #ced0dc;
}
.toastui-editor-defaultUI {
position: relative;
border: 1px solid #dadde6;
height: 100%;
font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial",
"나눔바른고딕", "Nanum Barun Gothic", "맑은고딕", "Malgun Gothic",
sans-serif;
border-radius: 4px;
background: #fff;
color: #303133;
}
::v-deep .el-dialog__body {
padding: 10px 20px;
}
::v-deep .el-pagination__total,
::v-deep .el-pagination__jump {
color: #bdc7da;
}
::v-deep .el-radio {
color: rgb(206, 208, 220);
}
::v-deep .el-tag {
background: transparent;
border: 1px solid #19538a;
margin: 0 0.2rem;
}
::v-deep .el-select .el-select__tags .el-tag--info {
background: transparent;
border: 1px solid #19538a;
color: #0065d8;
}
// ::v-deep .el-overlay .el-overlay-dialog .el-dialog{
// border: 1px solid red;
// }
::v-deep .el-overlay .el-overlay-dialog .el-dialog .el-dialog__body .tabBox {
height: 450px;
}
::v-deep .el-date-editor .el-range-separator {
color: #fcfcfc;
}
::v-deep .el-date-editor .el-range-input {
color: #ffffff;
}
::v-deep .el-input.is-disabled .el-input__inner {
background-color: #ffffff;
border: 1px solid #e9e9e9;
color: #000;
}
::v-deep .el-select {
width: 100%;
}

307
src/assets/css/layout.scss Normal file
View File

@ -0,0 +1,307 @@
header {
height: 88px;
background: url('~@/assets/images/top.png') no-repeat center center;
background-size: 100% 100%;
display: flex;
justify-content: space-between;
align-items: center;
.logo{
white-space: nowrap;
padding-left: 8px;
font-size:55px;
letter-spacing: 1px;
font-family: "YSBTH";
background: linear-gradient(180deg, #FFFFFF 52.4658203125%, #89AFCF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color:transparent ;
text-shadow: 4px 4px 4px rgba(255,255,255,0.15);
}
.right {
display: flex;
height: 100%;
align-items: center;
z-index: 1999;
position: relative;
padding-right: 10px;
.detail {
display: flex;
cursor: pointer;
.hd {
white-space: nowrap;
color: #ffffff;
font-size: 14px;
line-height: 20px;
margin: 10px 10px 0 10px;
}
.el-dropdown {
width: 30px;
height: 47px;
margin-top: 13px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
@keyframes rotateCircleSecondB {
from {
transform: rotate(-360deg);
-ms-transform: rotate(-360deg);
-moz-transform: rotate(-360deg);
-webkit-transform: rotate(-360deg);
}
to {
transform: rotate(0deg);
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
}
}
//新增弹窗样式
.total {
color: #fff;
height: 34px;
line-height: 44px;
.numb {
font-size: 24px;
display: inline-block;
margin: 0 8px;
}
}
.dialog::-webkit-scrollbar-track {
background-color: rgb(2, 19, 74);
}
.dialog::-webkit-scrollbar {
width: 8px;
}
.dialog::-webkit-scrollbar-thumb {
background-color: rgb(26, 5, 132);
}
.dialog {
position: absolute;
height: calc(100vh - 133px);
overflow: auto;
border: 1px solid #F1F4F8;
top: 5px;
right: 10px;
left: 10px;
background-color: #fff;
z-index: 998;
color: #fff;
padding: 20px;
box-sizing: border-box;
.head_box {
height: 48px;
border-bottom: 1px solid #F1F4F8;
color: #000;
display: flex;
justify-content: space-between;
align-items: center;
.title{
position: relative;
padding-left: 10px;
&::before{
position: absolute;
content: '';
top: 0;
left: 0;
width: 5px;
height: 20px;
border-radius: 4px;
background: #2D95FF;
}
}
}
&::v-deep .el-form--inline {
display: flex;
flex-wrap: wrap;
padding: 2rem 12rem 0rem 12rem;
}
&::v-deep .el-form-item--default {
width: 23%;
padding-bottom: 20px;
margin: 0 1%;
}
&::v-deep .el-form-item--default.two {
width: 46%;
padding-bottom: 20px;
margin: 0 1%;
}
&::v-deep .el-form-item--default.one {
width: 92%;
padding-bottom: 20px;
margin: 0 1%;
}
&::v-deep .el-textarea__inner {
height: 7.5em;
border: 1px solid #F1F4F8;
background-color: #02163b;
}
}
.searchBox {
padding: 15px 15px 0 15px;
border-radius: 1px;
position: relative;
background: #fff;
border-radius: 4px;
}
.app-main {
height: calc(100vh - 126px);
position: relative;
overflow: hidden;
padding: 0px 20px 20px 20px;
box-sizing: border-box;
background: #e9edf6;
.titleBox {
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
z-index: 2;
background: #fff;
padding: 0 10px;
box-sizing: border-box;
border-radius: 4px;
margin: 5px 0;
.title {
height: 60px;
line-height: 60px;
font-size: 18px;
color: #000;
}
.btnBox {
margin-top: 14px;
}
}
.tabBox {
width: 100%;
position: relative;
background: #fff;
border-radius: 4px;
height: calc(100vh - 124px);
.el-table--fit {
width: calc(100% - 20px) !important;
position: absolute;
top: 10px;
right: 10px;
left: 10px;
height: calc(100% - 100px);
overflow: auto;
}
.fenye {
background: #fff;
border-width: 0 1px 1px 1px;
position: absolute;
right: 0px;
left: 0px;
padding-right: 10px;
.el-pagination{
display: flex;
align-items: center;
justify-content: flex-end;
}
}
}
}
::v-deep .el-card {
--el-card-border-color: #143578;
--el-card-border-radius: 4px;
--el-card-padding: 20px;
--el-card-bg-color: #17096130;
}
::v-deep .el-dialog {
--el-dialog-bg-color: #061639;
}
.main-box {
display: flex;
margin-top: 15px;
.treeBox {
// width: 280px;
flex-shrink: 0;
border: solid #0a467e;
border-width: 1px 0 1px 1px;
overflow-y: auto;
overflow-x: hidden;
}
.tabBox {
width: calc(100% - 1px);
}
.user-main-wrap {
overflow: hidden;
width: calc(100% - 260px);
.el-table--fit {
float: right;
width: 800px;
}
}
}
.content-box-sun{
display: flex;
.org-box{
flex: 1;
.org-content-box {
width: 95%;
.org-search-box {
display: flex;
}
.tree-box{
height: 750px;
overflow: auto;
}
}
}
.right-box-sun{
flex: 4;
}
}
.titleBoxs {
height: 60px;
display: flex;
justify-content: space-between;
position: relative;
z-index: 2;
.title {
height: 60px;
line-height: 60px;
font-size: 18px;
color: #fff;
}
.btnBox {
margin-top: 14px;
}
}

365
src/assets/css/pulic.scss Normal file
View File

@ -0,0 +1,365 @@
.font10 {
font-size: 10px;
}
.font12 {
font-size: 12px;
}
.font14 {
font-size: 14px;
}
.font16 {
font-size: 16px;
}
.font18 {
font-size: 18px;
}
.font20 {
font-size: 20px;
}
.font22 {
font-size: 22px;
}
.font24 {
font-size: 24px;
}
.font28 {
font-size: 28px;
}
.font36 {
font-size: 36px;
}
.upColor {
color: #d9001b;
}
.downColor {
color: #95f204;
}
// 分割线
.divider {
background: linear-gradient(
90.143958942072deg,
rgba(14, 48, 115, 1) 0%,
rgba(70, 159, 251, 1) 50%,
rgba(14, 48, 115, 1) 100%
);
height: 1px;
}
// 不显示滚动条
.noScollLine::-webkit-scrollbar {
width: 0 !important;
}
.cardBorder {
border: 1px solid rgba(24, 99, 232, 1);
}
// echarts背景样式
.echartBoxBg1 {
background-color: rgba(0, 0, 0, 0.266666666666667);
border-radius: 10px;
padding: 5px;
}
//状态栏
.warning {
background-color: #fff4f6;
color: #f4002c;
}
.finish {
background-color: #e7f8f0;
color: #0acf83;
}
.waiting {
background-color: #fff6e8;
color: #fe7f2e;
}
.ellipsis2 {
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 表格里面给人的名字加边框
.tableUserName {
line-height: 24px;
font-size: 14px;
padding: 2px 0px;
border: 1px solid #4d67eb;
color: #4d67eb;
width: 60px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
// 滚动
.scrollbar {
overflow: overlay;
}
// 浮动
.fl {
float: left;
}
.fr {
float: right;
}
.pointer {
cursor: pointer;
}
/**************文字位置**************/
.tl {
text-align: left;
}
.tc {
text-align: center;
}
.tr {
text-align: right;
}
.strong {
font-weight: bold;
}
/**************flex************/
.flex {
display: flex;
}
.flex-grow1 {
flex-grow: 1;
}
.shrink0 {
flex-shrink: 0;
}
.flex-warp {
flex-wrap: wrap;
}
.flex-nowrap {
flex-wrap: nowrap;
}
.dir-column {
flex-direction: column;
}
.just-between {
justify-content: space-between;
}
.just-around {
justify-content: space-around;
}
.just-center {
justify-content: center;
}
.just-end {
justify-content: flex-end;
}
.just-start {
justify-content: flex-start;
}
.align-start {
align-items: start;
}
.align-center {
align-items: center;
}
.align-bottom {
align-items: flex-end;
}
/**********文本省略***********/
.nowrap {
white-space: nowrap;
}
.text1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text2 {
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.text3 {
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.hidden {
overflow: hidden;
}
.hide {
display: none;
}
.show {
display: block;
}
/**********字体大小和边距***********/
@for $i from 1 through 100 {
.f#{$i} {
font-size: #{$i}px;
}
//外边距
.mg#{$i} {
margin: #{$i}px;
}
.mt#{$i} {
margin-top: #{$i}px;
}
.mr#{$i} {
margin-right: #{$i}px;
}
.mb#{$i} {
margin-bottom: #{$i}px;
}
.ml#{$i} {
margin-left: #{$i}px;
}
//内边距
.pd#{$i} {
padding: #{$i}px;
}
.pt#{$i} {
padding-top: #{$i}px;
}
.pr#{$i} {
padding-right: #{$i}px;
}
.pb#{$i} {
padding-bottom: #{$i}px;
}
.pl#{$i} {
padding-left: #{$i}px;
}
.br#{$i} {
border-radius: #{$i}px;
}
//宽度
.w#{$i} {
width: #{$i}px;
}
.ww#{$i} {
width: #{$i}+ "%";
}
.hh#{$i} {
height: #{$i}+ "%";
}
//高度
.h#{$i} {
height: #{$i}px;
}
//行高
.lh#{$i} {
line-height: #{$i}px;
}
//自适应大号字体(通常为统计数字 18-30)
.font_size_big{
font-size: clamp(1.125rem, -0.894rem + 2.31vw, 1.875rem);
}
//自适应一号字体(通常为一级标题 14-18)
.font_size_title{
font-size: clamp(0.875rem, 0.37rem + 0.58vw, 1.063rem);
}
//自适应统计字体(通常为统计数字 14-22)
.font_size1{
font-size: clamp(0.875rem, -0.471rem + 1.54vw, 1.375rem);
}
//自适应二号字体(通常为二级标题 14-16)
.font_size2{
font-size: clamp(0.75rem, 0.077rem + 0.77vw, 1rem);
}
//自适应普通字体(通常为默认大小 10-14)
.font_size_default{
font-size: clamp(0.625rem, -0.048rem + 0.77vw, 0.875rem);
}
}
@font-face {
font-family: "DigifaceWide";
src: url("~@/assets/font/DigifaceWide.ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "HANYILINGXINTIJIAN";
src: url("~@/assets/font/HANYILINGXINTIJIAN-1.TTF");
font-weight: normal;
font-style: normal;
}

Binary file not shown.

Binary file not shown.

BIN
src/assets/font/YSBTH.ttf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

BIN
src/assets/images/aside.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
src/assets/images/bg01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

BIN
src/assets/images/bg_02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

BIN
src/assets/images/bg_03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/assets/images/bg_04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/images/bg_05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/assets/images/bg_06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
src/assets/images/bg_07.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
src/assets/images/bg_08.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src/assets/images/bg_09.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
src/assets/images/bg_10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
src/assets/images/bg_11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 2C10.477 2 6 6.477 6 12C6 19.5 16 30 16 30C16 30 26 19.5 26 12C26 6.477 21.523 2 16 2ZM16 16C13.791 16 12 14.209 12 12C12 9.791 13.791 8 16 8C18.209 8 20 9.791 20 12C20 14.209 18.209 16 16 16Z" fill="#00f0ff" stroke="#ffffff" stroke-width="1"/>
</svg>

After

Width:  |  Height:  |  Size: 401 B

BIN
src/assets/images/meun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
src/assets/images/peo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/assets/images/top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,67 @@
<template>
<el-breadcrumb class="breadcrumb-wrap" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in breadcrumData" :key="item.path">
<!---不可点击-->
<span class="no-redirect" v-if="index === breadcrumData.length - 1">{{ item.meta.title }}</span>
<!---可点击项-->
<span class="redirect" v-else @click="onLinkClick(item)">{{ item.meta.title }}</span>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script setup>
import { useStore } from 'vuex'
import { watch, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
//生成数组数据
const breadcrumData = ref([]);
const getBreadcrumData = () => {
//当前路由的标准化路由纪录
breadcrumData.value = route.matched.filter(item => item.meta && item.meta.title)
}
//watch监听路由变化
watch(route, () => {
getBreadcrumData();
}, {
immediate: true
})
const store = useStore();
const linkHoverColor = ref(store.getters.cssVar.menuBg);
const router = useRouter();
const onLinkClick = (item) => {
router.push(item.path)
}
</script>
<style lang="scss" scoped>
.breadcrumb-wrap {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
.redirect {
color: #666;
font-weight: 600;
cursor: pointer;
}
.redirect:hover {
// 将来需要进行主题替换,所以这里不去写死样式
color: v-bind(linkHoverColor);
}
}
</style>

View File

@ -0,0 +1,51 @@
<template>
<div>
<template v-for="(item, index) in options">
<template v-if="values.includes(item.value)">
<span
v-if="item.elTagType == 'default' || item.elTagType == '' || tag == false"
:key="item.value"
:index="index"
:class="item.elTagType"
>{{ item.label }}</span>
<el-tag
v-else
:disable-transitions="true"
:key="item.value + ''"
:index="index"
:type="item.elTagType === 'primary' ? '' : item.elTagType"
:class="item.elTagType"
>{{ item.label }}</el-tag
>
</template>
</template>
</div>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
// 数据
options: {
type: Array,
default: null
},
tag: false,
value: [Number, String, Array]
});
const values = computed(() => {
if (props.value !== null && typeof props.value !== "undefined") {
return Array.isArray(props.value) ? props.value : [String(props.value)];
} else {
return [];
}
});
</script>
<style scoped>
.el-tag + .el-tag {
margin-left: 10px;
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<el-form ref="formRef" :model="groupData" :rules="rules">
<el-form-item
:label-width="LABEL_WIDTH"
prop="modelValue"
label="邮箱"
>
<el-input
v-bind="$attrs"
v-model="groupData.modelValue"
@input="onInput()"
@blur="validate()"
max="11"
></el-input>
</el-form-item>
</el-form>
</template>
<script setup>
import { LABEL_WIDTH } from '@/constant';
import { ref, defineProps, defineEmits, defineExpose } from 'vue'
const formRef = ref(null);
const props = defineProps({
isRequired: {
type: Boolean,
default: false
}
})
// import { validateIdentity } from './rules'
const groupData = ref({
modelValue: ''
});
const emits = defineEmits(['update:modelValue']);
const onInput = (e) => {
emits('update:modelValue', groupData.value.modelValue)
}
const isBX = ref(false)
const validateIdentity = () => {
return (rule, value, callback) => {
const reg = /^([a-zA-Z0-9]+[-_\.]?)+@[a-zA-Z0-9]+\.[a-z]+$/
if (!value) {
} else {
if (!reg.test(value)) {
return callback(new Error('请输入正确的邮箱地址'));
} else {
callback();
}
}
};
};
// 验证规则
const rules = ref({
modelValue: [
{
required: props.isRequired,
message: '请输入邮箱',
trigger: 'blur'
},
{
trigger: 'blur',
validator: validateIdentity()
}
]
})
// 校验是否 符合规则 。 把当前组件名通过 emits分发出去
const validate = () => {
formRef.value.validate((valid) => {
if (valid) {
emits('validateStatus', { 'Email': true })
} else {
emits('validateStatus', { 'Email': false })
}
})
if (!props.isRequired && groupData.value.modelValue.length === 0) {
emits('validateStatus', { 'Email': true })
}
}
const childMethod = () => {
groupData.value.modelValue = ""
}
// 主动暴露childMethod方法
defineExpose({ childMethod })
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,68 @@
<template>
<el-form ref="formRef" :model="groupData" :rules="rules">
<el-form-item :label-width="LABEL_WIDTH" prop="modelValue" label="身份证号">
<el-input
v-bind="$attrs"
v-model="groupData.modelValue"
@input="onInput()"
@blur="validate()"
></el-input>
</el-form-item>
</el-form>
</template>
<script setup>
import { LABEL_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, defineExpose } from "vue";
import { validateIdentity } from "./rules";
const props = defineProps({
isRequired: {
type: Boolean,
default: false
}
});
const groupData = ref({
modelValue: ""
});
const formRef = ref(null);
const emits = defineEmits(["videoListShowFn"]);
const onInput = (e) => {
emits("update:modelValue", groupData.value.modelValue);
};
// 验证规则
const rules = ref({
modelValue: [
{
required: props.isRequired,
message: "请输入身份证",
trigger: "blur"
},
{
trigger: "change",
validator: validateIdentity()
}
]
});
// 校验是否 符合规则 。 把当前组件名通过 emits分发出去
const validate = () => {
formRef.value.validate((valid) => {
if (valid) {
emits("validateStatus", { IdentityCard: true });
} else {
emits("validateStatus", { IdentityCard: false });
}
});
if (!props.isRequired && groupData.value.modelValue.length === 0) {
emits("validateStatus", { IdentityCard: true });
}
};
const childMethod = () => {
groupData.value.modelValue = "";
};
// 主动暴露childMethod方法
defineExpose({ childMethod });
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,79 @@
export const validateIdentity = () => {
return (rule, value, callback) => {
if (!value) {
// return callback(new Error('身份证号不能为空'));
} else if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(value)) {
callback(new Error('输入的身份证长度或格式错误'));
}
//身份证城市
var aCity = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外'
};
if (!aCity[parseInt(value.substr(0, 2))]) {
callback(new Error('身份证地区非法'));
}
// 出生日期验证
var sBirthday = (
value.substr(6, 4) +
'-' +
Number(value.substr(10, 2)) +
'-' +
Number(value.substr(12, 2))
).replace(/-/g, '/'),
d = new Date(sBirthday);
if (
sBirthday !==
d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()
) {
callback(new Error('身份证上的出生日期非法'));
}
// 身份证号码校验
var sum = 0,
weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],
codes = '10X98765432';
for (var i = 0; i < value.length - 1; i++) {
sum += value[i] * weights[i];
}
var last = codes[sum % 11]; //计算出来的最后一位身份证号码
if (value[value.length - 1] !== last) {
callback(new Error('输入的身份证号非法'));
}
callback();
};
};

View File

@ -0,0 +1,86 @@
<template>
<el-form ref="formRef" :model="groupData" :rules="rules">
<el-form-item :label-width="LABEL_WIDTH" prop="modelValue" label="手机号">
<el-input v-bind="$attrs" v-model="groupData.modelValue" @input="onInput()" @blur="validate()" max="11">
</el-input>
</el-form-item>
</el-form>
</template>
<script setup>
import { LABEL_WIDTH } from '@/constant';
import { ref, defineProps, defineEmits, defineExpose } from 'vue'
const formRef = ref(null);
const props = defineProps({
isRequired: {
type: Boolean,
default: false
}
})
const isOk = ref()
const groupData = ref({
modelValue: ''
});
const emits = defineEmits(['update:modelValue']);
const onInput = (e) => {
emits('update:modelValue', groupData.value.modelValue)
}
const isBX = ref(false)
const validateIdentity = () => {
return (rule, value, callback) => {
if (!value) {
} else {
const reg = /^1[3|4|5|7|8][0-9]\d{8}$/
if (reg.test(value)) {
callback();
} else {
return callback(new Error('请输入正确的手机号'));
}
}
};
};
// 验证规则
const rules = ref({
modelValue: [
{
required: props.isRequired,
message: '请输入手机号',
trigger: 'blur'
},
{
min: 11,
message: '手机号格式不正确',
trigger: 'blur'
},
{
trigger: 'change',
validator: validateIdentity()
}
]
})
// 校验是否 符合规则 。 把当前组件名通过 emits分发出去
const validate = () => {
formRef.value.validate((valid) => {
if (valid) {
emits('validateStatus', { Phone: true })
isOk.value = true
} else {
emits('validateStatus', { Phone: false })
isOk.value = false
}
})
if (!props.isRequired && groupData.value.modelValue.length === 0) {
emits('validateStatus', { Phone: true })
isOk.value = true
}
}
const childMethod = () => {
groupData.value.modelValue = ""
}
// 主动暴露childMethod方法
defineExpose({ childMethod })
</script>

View File

@ -0,0 +1,307 @@
<template>
<div class="form-item-box zj-addressSelect-wrap" :style="{ width: width }">
<el-select :placeholder="placeholder" :clearable="true" v-model="value" popper-class="adderss-select"
@clear="handleClear">
<el-option value="1" style="display: none"></el-option>
<el-input v-if="filterable" v-model="filterText" style="margin-bottom: 5px; font-size: 12px"
:prefix-icon="Search" />
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane name="province" :label="province ? province : '请选择'">
<div class="citylist">
<ul>
<li @click="chooseProvince(item)" v-for="item in provinceList" :key="item.code"
:class="{ selected: provinceId == item.code }">
{{ item.name }}
</li>
</ul>
</div>
</el-tab-pane>
<el-tab-pane name="city" v-if="cityList.length > 0" :label="city ? city : '请选择'">
<div class="citylist">
<ul>
<li @click="chooseCity(item)" v-for="item in cityList" :class="{ selected: cityId == item.code }"
:key="item.code">
{{ item.name }}
</li>
</ul>
</div>
</el-tab-pane>
<el-tab-pane name="area" v-if="areaList.length > 0" :label="area ? area : '请选择'">
<div class="citylist">
<ul>
<li @click="chooseArea(item)" v-for="item in areaList" :key="item.code"
:class="{ selected: areaId == item.code }">
{{ item.name }}
</li>
</ul>
</div>
</el-tab-pane>
<el-tab-pane name="street" v-if="streetList.length > 0" :label="street ? street : '请选择'">
<div class="citylist">
<ul>
<li @click="chooseStreet(item)" v-for="item in streetList" :key="item.code"
:class="{ selected: streetId == item.code }">
{{ item.name }}
</li>
</ul>
</div>
</el-tab-pane>
</el-tabs>
</el-select>
<!-- <el-icon class="errorIcon">
<circle-close-filled />
</el-icon>
<el-icon class="checkIcon">
<circle-check-filled />
</el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { nextTick, ref, watch } from "vue";
import { Search } from "@element-plus/icons-vue";
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
const props = defineProps({
placeholder: {
default: "选择地址",
type: String
},
filterable: {
default: false,
type: Boolean
},
address: {
default: () => [],
type: Array
},
defaultConf: {
type: Object,
default: () => ({
children: "",
label: "",
id: ""
})
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const filterText = ref("");
const activeName = ref("province");
const value = ref("");
const valueId = ref([]);
const province = ref("");
const provinceId = ref("");
const provinceList = ref([]);
provinceList.value = require("@/constant/pca-code.json");
const city = ref("");
const cityId = ref("");
const cityList = ref([]);
const area = ref("");
const areaId = ref("");
const areaList = ref([]);
const street = ref("");
const streetId = ref("");
const streetList = ref([]);
const provinceListFilter = ref([]);
provinceListFilter.value = require("@/constant/pca-code.json");
const cityListFilter = ref([]);
const areaListFilter = ref([]);
const streetListFilter = ref([]);
nextTick(() => {
if (props.address.length > 0) {
init(props.address);
}
});
watch(filterText, (val) => {
filterNode(val);
});
const handleClick = () => {
filterText.value = "";
filterNode("");
};
const filterNode = (val) => {
if (activeName.value === "province") {
if (val !== "") {
provinceList.value = provinceListFilter.value.filter(
(item) => item[props.defaultConf.label].indexOf(val) !== -1
);
} else {
provinceList.value = provinceListFilter.value;
}
} else if (activeName.value === "city") {
if (val !== "") {
cityList.value = cityListFilter.value.filter(
(item) => item[props.defaultConf.label].indexOf(val) !== -1
);
} else {
cityList.value = cityListFilter.value;
}
} else if (activeName.value === "area") {
if (val !== "") {
areaList.value = areaListFilter.value.filter(
(item) => item[props.defaultConf.label].indexOf(val) !== -1
);
} else {
areaList.value = areaListFilter.value;
}
} else if (activeName.value === "street") {
if (val !== "") {
streetList.value = streetListFilter.value.filter(
(item) => item[props.defaultConf.label].indexOf(val) !== -1
);
} else {
streetList.value = streetListFilter.value;
}
}
};
const chooseProvince = (e) => {
province.value = e[props.defaultConf.label];
provinceId.value = e[props.defaultConf.id];
value.value = province.value;
valueId.value = [provinceId.value];
emits("handleChange", valueId.value);
city.value = "";
cityId.value = "";
cityList.value = [];
areaList.value = [];
streetList.value = [];
filterText.value = "";
provinceList.value.forEach((el) => {
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
if (el[props.defaultConf.children]) {
activeName.value = "city";
cityList.value = el[props.defaultConf.children];
cityListFilter.value = el[props.defaultConf.children];
}
}
});
};
const chooseCity = (e) => {
city.value = e[props.defaultConf.label];
cityId.value = e[props.defaultConf.id];
area.value = "";
areaId.value = "";
areaList.value = [];
streetList.value = [];
filterText.value = "";
value.value = province.value + "/" + city.value;
valueId.value = [provinceId.value, cityId.value];
emits("handleChange", valueId.value);
cityList.value.forEach((el) => {
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
if (el[props.defaultConf.children]) {
activeName.value = "area";
areaList.value = el[props.defaultConf.children];
areaListFilter.value = el[props.defaultConf.children];
}
}
});
};
const chooseArea = (e) => {
area.value = e[props.defaultConf.label];
areaId.value = e[props.defaultConf.id];
street.value = "";
streetId.value = "";
streetList.value = [];
filterText.value = "";
value.value = province.value + "/" + city.value + "/" + area.value;
valueId.value = [provinceId.value, cityId.value, areaId.value];
emits("handleChange", valueId.value);
areaList.value.forEach((el) => {
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
if (el[props.defaultConf.children]) {
streetList.value = el[props.defaultConf.children];
activeName.value = "street";
streetListFilter.value = el[props.defaultConf.children];
}
}
});
};
const chooseStreet = (e) => {
street.value = e[props.defaultConf.label];
streetId.value = e[props.defaultConf.id];
value.value =
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
valueId.value = [
provinceId.value,
cityId.value,
areaId.value,
streetId.value
];
emits("handleChange", valueId.value);
};
const handleClear = () => {
activeName.value = "province";
value.value = "";
valueId.value = [];
province.value = "";
provinceId.value = "";
city.value = "";
cityId.value = "";
cityList.value = [];
area.value = "";
areaId.value = "";
areaList.value = [];
street.value = "";
streetId.value = "";
streetList.value = [];
cityListFilter.value = [];
areaListFilter.value = [];
streetListFilter.value = [];
filterText.value = "";
filterNode("");
emits("handleChange", []);
};
const treeValueFind = (tree, arr, newArr = []) => {
tree.forEach((el) => {
if (el[props.defaultConf.id] === arr) {
newArr.push(el);
}
if (el[props.defaultConf.children]) {
treeValueFind(el[props.defaultConf.children], arr, newArr);
}
});
return newArr;
};
const init = (data) => {
let obj1 = treeValueFind(provinceList.value, data[0])[0];
province.value = obj1[props.defaultConf.label];
provinceId.value = obj1[props.defaultConf.id];
cityList.value = obj1[props.defaultConf.children];
cityListFilter.value = obj1[props.defaultConf.children];
value.value = province.value;
if (data[1]) {
let obj2 = treeValueFind(provinceList.value, data[1])[0];
city.value = obj2[props.defaultConf.label];
cityId.value = obj2[props.defaultConf.id];
areaList.value = obj2[props.defaultConf.children];
areaListFilter.value = obj2[props.defaultConf.children];
value.value = province.value + "/" + city.value;
}
if (data[2]) {
let obj3 = treeValueFind(provinceList.value, data[2])[0];
area.value = obj3[props.defaultConf.label];
areaId.value = obj3[props.defaultConf.id];
streetList.value = obj3[props.defaultConf.children];
streetListFilter.value = obj3[props.defaultConf.children];
value.value = province.value + "/" + city.value + "/" + area.value;
}
if (data[3]) {
let obj4 = treeValueFind(provinceList.value, data[3])[0];
street.value = obj4[props.defaultConf.label];
streetId.value = obj4[props.defaultConf.id];
value.value =
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
}
};
</script>
<style lang="scss" scoped>
.zj-addressSelect-wrap {
::v-deep .el-select {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<!--选择图标-->
<div class="form-item-box choose-icon-zj" :style="{ width: width }">
<el-autocomplete v-bind="$attrs" v-model="modelValue" :fetch-suggestions="querySearch"
popper-class="choose-icon-zj-autocomplete" :placeholder="placeholder" @change="onInput" @select="handleSelect">
<template #prefix>
<SvgIcon :icon="modelValue"></SvgIcon>
</template>
<template #default="{ item }">
<SvgIcon :icon="item.link"></SvgIcon>
<div class="value">{{ item.value }}</div>
</template>
</el-autocomplete>
<!-- <el-icon class="errorIcon">
<circle-close-filled />
</el-icon>
<el-icon class="checkIcon">
<circle-check-filled />
</el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, defineExpose, onMounted } from "vue";
const props = defineProps({
placeholder: {
default: "请输入图标名称",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const links = ref([]);
const querySearch = (queryString, cb) => {
const results = queryString
? links.value.filter(createFilter(queryString))
: links.value;
cb(results);
};
const createFilter = (queryString) => {
return (restaurant) => {
return (
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
);
};
};
const handleSelect = (item) => {
emits("update:modelValue", item.value);
};
const handleIconClick = (ev) => {
};
const loadAll = () => {
const svgRequire = require.context("@/icons/svg", false, /\.svg$/);
const re = svgRequire.keys().map((svgIcon) => {
const iconName = svgIcon.split("/")[1];
const prefixIconName = iconName.split(".")[0];
return { value: prefixIconName, link: prefixIconName };
});
return re;
};
const iconListShow = ref(false);
const showIconList = () => {
iconListShow.value = true;
};
onMounted(() => {
links.value = loadAll();
});
const emits = defineEmits(["update:modelValue"]);
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,32 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-date-picker style="width:100%" v-model="modelValue" type="date" v-bind="$attrs" @change="onInput" :placeholder="placeholder" value-format="YYYY-MM-DD"/>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, defineExpose } from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
},
});
const emits = defineEmits(["update:modelValue"]);
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>

View File

@ -0,0 +1,119 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-cascader
style="width: 100%"
class="el-cascader-zj"
:show-all-levels="false"
clearable
filterable
:placeholder="modelValue ? placeholder : '请选择部门'"
:options="tableData"
v-model="oldmodelValue"
@change="handleChange"
:props="endProps"
/>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { qcckPost, qcckGet, qcckFlvGet } from "@/api/qcckApi.js";
import {
ref,
defineProps,
defineEmits,
defineExpose,
computed,
onMounted,
watch
} from "vue";
import { selectDeptPage } from "@/api/user-manage";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择",
type: String
},
multiple: {
default: false,
type: Boolean
},
isAll: {
default: 100,
type: Number
},
modelValue: {
type: Array || String,
default: []
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const modelShow = ref(false);
const oldmodelValue = ref([]);
const listQuery = ref({
deptname: "",
deptcode: "",
parentid: ""
});
const depList = ref([])
//配置项
const endProps = {
children: "childDeptList",
value: "orgCode",
label: "orgName",
checkStrictly: true,
multiple: props.multiple,
lazy: true,
lazyLoad(node, resolve) {
listQuery.value.parentid = node.data.id;
selectDeptPage(listQuery.value).then((res) => {
depList.value = depList.value.concat(res)
//处理部门是否包含下级
for (let i = 0; i < res.length; i++) {
res[i].leaf = !res[i].hasChildren;
}
resolve(res);
});
}
};
const tableData = ref([]);
const getSysMenuTree = async () => {
const res = await selectDeptPage(listQuery.value);
tableData.value = res;
depList.value = res
};
onMounted(() => {
getSysMenuTree();
});
watch(
() => props.modelValue,
(val) => {
console.log(val,'val');
oldmodelValue.value = val;
},
{ deep: true, immediate: true }
);
const emits = defineEmits(["update:modelValue",'getDepValue']);
const handleChange = (e) => {
console.log(e,'e');
if (props.multiple === true) {
const data = e.map((item) => {return item[item.length - 1];});
emits("update:modelValue", data);
} else {
const data = e ? e[e.length - 1] : "";
emits("update:modelValue", data);
let obj = depList.value.find(item=>{ return item.orgCode == data})
emits("getDepValue", obj);
}
};
</script>
<style lang="scss" scoped>
.el-cascader-zj {
width: 100%;
}
</style>

View File

@ -0,0 +1,158 @@
<template>
<div class="departmentTree-box" :style="{ width: width, height: '100%' }">
<div class="depar_hear">
<el-input
v-model="listQuery.deptname"
v-if="filterable"
clearable
:debounce="500"
@input="filterTextChange"
placeholder="请输入筛选条件"
/>
</div>
<div class="depar_foot">
<el-tree
ref="treeRef"
class="filter-tree"
:props="endProps"
lazy
:load="loadNode"
@node-click="nodeClick"
:filter-node-method="filterNode"
:data="treeData"
/>
</div>
</div>
</template>
<script setup>
import { debounce } from "lodash";
import { getItem } from "@/utils/storage";
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, watch, computed, onMounted } from "vue";
import { selectDeptPage, getAllChildDeptList } from "@/api/user-manage";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择",
type: String
},
multiple: {
default: false,
type: Boolean
},
filterable: {
default: false,
type: Boolean
},
modelValue: {
type: Number
},
width: {
default: COMPONENT_WIDTH,
type: String
},
isBmId:{
type:Boolean,
default:false
}
});
const listQuery = ref({
deptname: "",
deptcode: "",
parentid: ""
});
const treeRef = ref(null);
const node_had = ref([]);
const resolve_had = ref([]);
//防抖处理
const filterTextChange = debounce(inputChange, 500);
onMounted(() => {});
//获取部门数据
function getTreeData() {
selectDeptPage(listQuery.value).then((res) => {
for (let i = 0; i < res.length; i++) {
res[i].leaf = !res[i].hasChildren;
}
treeData.value = res;
});
}
//搜索查询
function inputChange(e) {
selectDeptPage(listQuery.value).then((res) => {
treeData.value = res;
});
}
watch(
() => listQuery.value.deptname,
(val) => {
treeRef.value.filter("tree", val);
}
);
const endProps = {
children: "childDeptList",
value: "id",
label: "orgName",
isLeaf: "leaf"
};
const treeData = ref([]);
//懒加载方法
async function loadNode(node, resolve) {
listQuery.value.parentid = node.data.id;
if (node.level === 0) {
node_had.value = node;
resolve_had.value = resolve;
getTreeData();
}
if (node.level >= 1) {
selectDeptPage(listQuery.value).then((res) => {
for (let i = 0; i < res.length; i++) {
res[i].leaf = !res[i].hasChildren;
}
resolve(res);
});
}
}
const filterNode = (value, data) => {
if (!value) return true;
return data.orgName.includes(value);
};
const nodeClick = (node) => {
if(props.isBmId){
emits("update:modelValue", node.id);
}else{
emits("update:modelValue", node.orgCode);
}
};
const emits = defineEmits(["update:modelValue"]);
const handleChange = (e) => {
if (props.multiple === true) {
const data = e.map((item) => {
return item[item.length - 1];
});
emits("update:modelValue", data);
} else {
const data = e[0];
emits("update:modelValue", data);
}
};
</script>
<style lang="scss" scoped>
.depar_hear {
height: 32px;
}
.depar_foot {
height: calc(100% - 32px);
overflow: auto;
width: 280px;
width: 100%;
min-width: 300px;
}
.departmentTree-box {
overflow: auto;
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<el-dialog
title="导出预览"
width="1400px"
:model-value="modelValue"
@close="closed"
>
<el-table :data="data" :id="myId" style="width: 100%" border>
<el-table-column label="序号" type="index" align="center" width="80" />
<el-table-column
v-for="(item, index) in tabOption"
:key="index + 'tab'"
:prop="item.prop"
:label="item.label"
align="center"
>
<template v-if="item.dict" #default="{ row }">
<dict-tag :options="item.dict" :value="row[item.prop]" :tag="false" />
</template>
</el-table-column>
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="exportExcel">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { defineProps, ref, onMounted, getCurrentInstance } from "vue";
import FileSaver from "file-saver";
import * as XLSX from "xlsx";
const tabRef = ref(null);
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
tabOption: {
type: Array,
require: []
},
data: {
type: Array,
required: []
},
myId: {
type: String,
require: ""
},
title: {
type: String,
require: ""
}
});
const emits = defineEmits(["update:modelValue"]);
const closed = () => {
emits("update:modelValue", false);
};
const { proxy } = getCurrentInstance();
function exportExcel() {
let xlsxParam = { raw: true };
let wb = XLSX.utils.table_to_book(
document.querySelector("#" + props.myId),
xlsxParam
);
let wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array"
});
closed();
try {
FileSaver.saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
`${props.title}.xlsx`
);
} catch (e) {
if (typeof console !== "undefined") console.log(e, wbout);
}
return wbout;
}
</script>
<style>
</style>

View File

@ -0,0 +1,80 @@
<template>
<div class="form-item-box zj-email-wrap" :style="{ width: width }">
<el-autocomplete v-model="email" v-bind="$attrs" :placeholder="placeholder" :fetch-suggestions="querySearch"
:trigger-on-focus="false" class="inline-input" @select="handleSelect" @input="onInput" />
<!-- <el-icon class="errorIcon">
<circle-close-filled />
</el-icon>
<el-icon class="checkIcon">
<circle-check-filled />
</el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { ref, defineProps, defineEmits, defineExpose, onMounted } from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写邮箱",
type: String
},
email: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const emits = defineEmits(["update:email"]);
const onInput = (e) => {
emits("update:email", e);
};
const restaurants = ref([]);
const createFilter = (queryString) => {
return (item) => {
return item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0;
};
};
const querySearch = (queryString, callback) => {
let results = JSON.parse(JSON.stringify(restaurants.value)); //把数组的浅复制换成深复制
if (queryString.indexOf("@") > -1) {
results.length = 0;
callback(results);
return false;
}
for (let item in results) {
results[item].value = queryString + "" + restaurants.value[item].value;
}
callback(results);
};
const loadAll = () => {
return [
{ value: "@qq.com" },
{ value: "@mosty.com" },
{ value: "@163.com" },
{ value: "@outlook.com" },
{ value: "@sohu.com" }
];
};
const handleSelect = (item) => {
emits("update:email", item.value);
};
onMounted(() => {
restaurants.value = loadAll();
});
</script>
<style lang="scss" scoped>
.zj-email-wrap {
::v-deep .el-autocomplete {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,247 @@
<template>
<div class="main-box">
<div class="file_box" v-for="(item, index) in fileList" :key="index">
<div class="show_file" :style="{ width: width, height: width }">
<div class="icon_box_y" :style="{ width: width, height: width }">
<svg-icon :icon="getSuffix(item.url)" />
<span class="file_name_box">{{ item.name }}</span>
</div>
<div class="load_and_del" :style="{ width: width, height: width }">
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
<DeleteFilled v-if="props.isEdit" @click="delFile(index)" />
</el-icon>
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
<Download @click="downloadFile(item.url)" />
</el-icon>
</div>
</div>
</div>
<div class="file_box" v-if="fileList.length != props.limit && props.isEdit">
<div class="upload_img" :style="{ width: width, height: width }">
<div class="icon_box" :style="{ width: width, height: width }">
<el-icon :size="30" color="#aaaaaa">
<Plus />
</el-icon>
</div>
<div class="file_box_item" :style="{ width: width, height: width }">
<input
type="file"
:style="{ width: width, height: width }"
class="file_input"
id="file"
@change="fileChange"
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
ref,
defineProps,
defineEmits,
defineExpose,
computed,
onMounted
} from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import request from "@/utils/request";
import axios from "axios";
const props = defineProps({
modelValue: {
type: String,
default: ""
},
width: {
type: String,
default: "150px"
},
limit: {
type: Number,
default: 1
},
isEdit: {
type: Boolean,
default: false
}
});
const fileList = ref([]);
const count = ref(0); // 上传的数量
const emits = defineEmits(["update:modelValue", "handleChange"]);
//获取后缀
const getSuffix = (fileName) => {
let suffix = "";
try {
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4);
if (suffix.indexOf("?") !== -1) suffix = suffix.replaceAll("?", "");
} catch (err) {
suffix = "";
return "OTHER";
}
// fileName无后缀返回 false
if (!suffix) return "";
// 图片格式
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
if (imglist.includes(suffix)) return "IMG";
//txt
if (suffix === "txt") return "TXT";
//excel XLS
const excelist = ["xls", "xlsx"];
if (excelist.includes(suffix)) return "XLS";
// 匹配 word
var wordlist = ["doc", "docx"];
if (wordlist.includes(suffix)) return "DOC";
//pdf
if (suffix === "pdf") return "PDF";
//视频 音频
var videolist = [
"mp4",
"m2v",
"mkv",
"rmvb",
"wmv",
"avi",
"flv",
"mov",
"m4v"
];
if (videolist.includes(suffix)) return "VIDEO";
var musiclist = ["mp3", "wav", "wmv"];
if (musiclist.includes(suffix)) return "MUSIC";
var pptlist = ["ppt", "pptx"];
if (pptlist.includes(suffix)) return "PPT";
//压缩包
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
if (yslist.includes(suffix)) return "YS";
//否则返回other
return "OTHER";
};
// 删除
function delFile(index) {
fileList.value = fileList.value.filter((item, i) => {
return i !== index;
});
}
// 文件下载
function downloadFile(url) {
window.open('/mosty-api/mosty-base/minio/image/download/'+url, "_blank");
}
// 选择文件
function fileChange(e) {
let file = document.getElementById("file").files[0];
let name = file.name;
let formData = new FormData();
formData.append("file", file);
axios
.post("/mosty-api/mosty-base/minio/image/upload/id", formData, {
"Content-type": "multipart/form-data"
})
.then((res) => {
if (res.status == 200 && res.data && res.data.code === 10000) {
let url = res.data.data;
let f = {
url: url,
name: name
};
fileList.value.push(f);
count.value = count.value + 1;
let list = fileList.value.map((item) => {
return item.url;
});
emits("handleChange", JSON.stringify(list));
} else {
ElMessage.warning("文件上传失败");
}
});
}
onMounted(() => {
if (props.modelValue) {
let list = JSON.parse(props.modelValue);
list.forEach((item, index) => {
let temp = {
url: item,
name: "文件" + (index + 1)
};
fileList.value.push(temp);
});
count.value = list.length;
}
});
</script>
<style scoped lang="scss">
.main-box {
width: 100%;
.file_box {
background-color: #112b63;
border: 1px dashed #4579b5;
margin: 10px 0 0 10px;
border-radius: 5px;
position: relative;
.show_file {
overflow: hidden;
box-sizing: border-box;
&:hover > .load_and_del {
display: block;
}
.load_and_del {
display: none;
position: absolute;
top: 0;
left: 0;
.load_and_del_icon {
cursor: pointer;
margin-left:5px;
margin-top: 5px;
}
}
.icon_box_y {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.file_name_box {
margin-top: 10px;
width: 80%;
line-height: 30px;
height: 30px;
overflow: hidden;
text-align: center;
}
}
::v-deep .svg-icon {
font-size: 48px;
}
}
.upload_img {
position: relative;
.icon_box {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
z-index: 1;
}
.file_box_item {
position: absolute;
opacity: 0;
z-index: 2;
top: 0;
left: 0;
.file_input {
cursor: pointer;
}
}
.file_box_item_show {
position: absolute;
top: 0;
left: 0;
}
}
}
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="form-item-box zk-frameWork-wrap" :style="{ width: width }">
<el-select
:model-value="frameWork"
:placeholder="placeholder"
@clear="handleClear"
@change="selectChange"
:clearable="clearable"
v-bind="$attrs"
:multiple="multiple"
popper-class="frameWork-select"
>
<el-option value="1" style="display: none"></el-option>
<el-input
v-if="filterable"
v-model="filterText"
style="width: 96% !important; margin: 0 2%; font-size: 12px"
:prefix-icon="Search"
/>
<div class="alllist">
<el-tree
ref="tree"
:data="treeData"
:props="defaultConf"
default-expand-all
:filter-node-method="filterNode"
:show-checkbox="multiple"
:node-key="nodeKey"
@check-change="handleCheckChange"
@node-click="clickNode"
/>
</div>
</el-select>
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { nextTick, ref, watch } from "vue";
import { Search } from "@element-plus/icons-vue";
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
const props = defineProps({
clearable: {
default: false,
type: Boolean
},
multiple: {
default: false,
type: Boolean
},
filterable: {
default: false,
type: Boolean
},
treeData: {
default: () => [],
type: Array
},
placeholder: {
default: "选择组织机构",
type: String
},
defaultConf: {
type: Object,
default: () => ({
children: "children",
label: "label"
})
},
frameWork: {
type: [String, Array],
default: ""
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const nodeKey = "id";
const filterText = ref("");
const mineStatusValue = ref([]); //选中状态存贮
nextTick(() => {
if (props.frameWork) {
if (typeof props.frameWork === "string") {
//传过来的默认值类型
if (props.frameWork) {
tree.value.setCheckedKeys([props.frameWork], false);
}
} else {
if (props.frameWork.length > 0) {
tree.value.setCheckedKeys(props.frameWork, false);
}
}
mineStatusValue.value = treeValueFind(props.treeData, props.frameWork);
}
});
const tree = ref(null);
let deferTimer;
watch(filterText, (val) => {
tree.value.filter(val);
});
const filterNode = (value, data) => {
if (!value) return true;
return data[props.defaultConf.label].indexOf(value) !== -1;
};
//多选选中
const handleCheckChange = () => {
const res = tree.value.getCheckedNodes(true, true); // 这里两个true1. 是否只是叶子节点 2. 是否包含半选节点
mineStatusValue.value = res;
clearTimeout(deferTimer);
deferTimer = setTimeout(() => {
emits("handleChange", res);
}, 200);
};
//节点选择
const clickNode = (data, node, obj) => {
if (props.multiple) {
// 多选不执行
const index = mineStatusValue.value.findIndex((d) => d.id === data.id);
if (index > -1) {
tree.value.setChecked(data, false);
} else {
tree.value.setChecked(data, true);
}
return;
}
if (!data.children) {
mineStatusValue.value.push(data.id);
tree.value.setCheckedKeys([data.id], false);
}
};
//select值变化
const selectChange = (e) => {
if (!props.multiple || !props.treeData.length) {
return false;
}
const arrNew = [];
const dataLength = mineStatusValue.value.length;
const eleng = e.length;
for (let i = 0; i < dataLength; i++) {
for (let j = 0; j < eleng; j++) {
if (e[j] === mineStatusValue.value[i][props.defaultConf.label]) {
arrNew.push(mineStatusValue.value[i][nodeKey]);
break;
}
}
}
setTimeout(() => {
tree.value.setCheckedKeys(arrNew, false);
}, 200);
};
//select clear
const handleClear = (e) => {
mineStatusValue.value = [];
tree.value.setCheckedKeys([], false);
};
const treeValueFind = (tree, arr, newArr = []) => {
if (typeof arr === "string") {
tree.forEach((el) => {
if (el[nodeKey] === arr) {
newArr.push(el);
}
if (el[props.defaultConf.children]) {
treeValueFind(el[props.defaultConf.children], arr, newArr);
}
});
} else {
for (let i = arr.length; i >= 0; i--) {
tree.forEach((el) => {
if (el[nodeKey] === arr[i]) {
newArr.push(el);
arr.splice(i, 1);
}
if (el[props.defaultConf.children] && arr.length > 0) {
treeValueFind(el[props.defaultConf.children], arr, newArr);
}
});
}
}
return newArr;
};
</script>
<style lang="scss" scoped>
.optionclass {
height: auto;
padding: 0;
position: relative;
width: 100%;
overflow-y: overflow;
}
.zk-frameWork-wrap {
.el-select {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-cascader
class="el-cascader-zj"
:placeholder="placeholder"
:options="tableData"
v-bind="$attrs"
v-model="modelValue"
@change="handleChange"
:props="endProps"
:filterable="filterable"
/>
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { ref, defineProps, defineEmits, defineExpose,computed } from "vue";
import { getSystemMeny } from "@/api/user-manage";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择",
type: String
},
multiple: {
default: false,
type: Boolean
},
filterable: {
default: false,
type: Boolean
},
modelValue: {
default: [],
type: Array
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const endProps = computed(() => {
let re = { children: 'sysMenuList', value: 'id', label: 'menuName' }
if (props.multiple === true) {
re.multiple = true;
}
return re;
})
const tableData = ref([]);
const getSysMenuTree = async () => {
const params = {
menuName: "",
current: 1,
size: 999
}
const res = await getSystemMeny(params);
tableData.value = res?.records;
};
getSysMenuTree();
const emits = defineEmits(["update:modelValue"]);
const handleChange = (e) => {
if (props.multiple === true) {
const data = e.map((item) => {
return item[item.length - 1];
});
emits("update:modelValue", data);
} else {
const data = e ? e[e.length - 1] : ''
emits("update:modelValue", data);
}
};
</script>
<style lang="scss" scoped>
.el-cascader-zj{
width: 100%;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<div
class="form-item-box"
:style="{ width: width}"
>
<el-input
:placeholder="placeholder"
v-bind="$attrs"
v-model="modelValue"
@input="onInput"
></el-input>
<!-- <el-icon class="errorIcon"><circle-close-filled /></el-icon>
<el-icon class="checkIcon"><circle-check-filled /></el-icon> -->
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { defineProps, defineEmits } from "vue";
const props = defineProps({
placeholder: {
default: "请输入身份证号",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const emits = defineEmits(["update:modelValue"]);
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>

View File

@ -0,0 +1,71 @@
<template>
<div class="markdown-wrap">
<!---->
<div id="markdown-box">
<strong v-html="modelValue"></strong>
</div>
<div style="margin-top: 1vw">
<el-button type="primary" @click="saveEdit">确定详情信息</el-button>
</div>
</div>
</template>
<script setup>
import MKEditor from "@toast-ui/editor";
import "@toast-ui/editor/dist/toastui-editor.css";
import "@toast-ui/editor/dist/i18n/zh-cn.js";
import { COMPONENT_WIDTH } from "@/constant";
import {
ref,
defineProps,
defineEmits,
defineExpose,
onMounted,
watch
} from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写手机号",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: "800px",
type: String
}
});
let mkEditor;
let el;
onMounted(() => {
el = document.querySelector("#markdown-box");
initEditor();
});
const emits = defineEmits(["update:modelValue"]);
const initEditor = () => {
mkEditor = new MKEditor({
el,
height: "700px",
previewStyle: "vertical",
language: "zh-CN",
initiaValue:props.modelValue
});
mkEditor.getMarkdown();
};
const saveEdit = () => {
emits("update:modelValue", mkEditor.getHTML());
};
const onInput = (e) => {
emits("update:modelValue", e);
};
//回显
</script>
<style lang="scss" scoped>
.markdown-wrap {
}
</style>

View File

@ -0,0 +1,31 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-input :placeholder="placeholder" v-bind="$attrs" v-model="modelValue" @input="onInput" ></el-input>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, defineExpose } from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写手机号",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const emits = defineEmits(["update:modelValue"]);
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>

View File

@ -0,0 +1,32 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-input :placeholder="placeholder" v-bind="$attrs" v-model="modelValue" @input="onInput" ></el-input>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { ref, defineProps, defineEmits, defineExpose } from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写手机号",
type: String
},
modelValue: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const emits = defineEmits(["update:modelValue"]);
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,109 @@
<template>
<div class="form-item-box">
<el-select v-model="province" clearable placeholder="请选择省份">
<el-option v-for="item in areas" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
</el-option>
</el-select>
<el-select clearable :disabled="!province" style="margin: 0 10px" v-model="city" placeholder="请选择城市">
<el-option v-for="item in selectCity" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
</el-option>
</el-select>
<el-select clearable :disabled="!province || !city" v-model="area" placeholder="请选择区域">
<el-option v-for="item in selectArea" :value="item.code" :label="item.name" :key="item.code">{{ item.name }}
</el-option>
</el-select>
</div>
</template>
<script setup>
import allAreas from "@/constant/pca-code.json";
import {
ref,
defineProps,
defineEmits,
defineExpose,
computed,
watch
} from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择省市区",
type: String
},
modelValue: {
default: "",
type: String
}
});
let province = ref("");
let city = ref("");
let area = ref("");
let areas = ref(allAreas);
let selectCity = ref([]);
let selectArea = ref([]);
//分发事件给父组件
//分发事件给父组件
const emits = defineEmits(["update:modelValue"]);
//监听省份变化
watch(
() => province.value,
(val) => {
if (val) {
let cities = areas.value.find(
(item) => item.code === province.value
)?.children;
selectCity.value = cities;
}
city.value = "";
area.value = "";
}
);
//监听城市变化
watch(
() => city.value,
(val) => {
if (val) {
let area = selectCity.value.find(
(item) => item.code === city.value
)?.children;
selectArea.value = area;
}
area.value = "";
}
);
//监听区域变化
watch(
() => area.value,
(val) => {
let provinceData = {
code: province.value,
name:
province.value &&
allAreas.find((item) => item.code === province.value).name
};
let cityData = {
code: city.value,
name:
city.value &&
selectCity.value &&
selectCity.value.find((item) => item.code === city.value).name
};
let areaData = {
code: val,
name:
val &&
selectArea.value &&
selectArea.value.find((item) => item.code === val).name
};
emits("update:modelValue", `${provinceData},${cityData},${areaData}`);
}
);
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,62 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-cascader class="el-cascader-zj" :props="{ value: 'label', label: 'label', children: 'children' }"
:options="arercity" expand-trigger="hover" change-on-select @change="onInChange" :placeholder="placeholder"
v-bind="$attrs" v-model="value"></el-cascader>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import allAreas from "./provicesData";
import {
ref,
defineProps,
defineEmits,
defineExpose,
computed,
nextTick,
watch
} from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择地区位置",
type: String
},
provinces2: {
default: () => [],
type: Array
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const value = ref([]);
nextTick(() => {
if (props.provinces2.length > 0) {
init(props.provinces2);
}
});
const init = (data) => { };
const registerAddress = ref([]);
const arercity = ref(allAreas);
const emits = defineEmits(["update:provinces2"]);
const onInChange = (e) => {
emits("update:provinces2", e);
};
// const onInput = (e) => {
// emits("update:provinces2", e);
// };
</script>
<style lang="scss" scoped>
.el-cascader-zj {
width: 100%;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,288 @@
<template>
<div>
<el-dialog
:title="titleValue"
width="1400px"
:model-value="modelValue"
@close="closed"
>
<el-form :model="listQuery" :inline="true">
<el-form-item label="所属部门">
<MOSTY.Department width="100%" clearable v-model="listQuery.ssbmdm" />
</el-form-item>
<el-form-item label="圈层名称">
<el-input
v-model="listQuery.qcmc"
placeholder="请输入圈层名称"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="info" @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
<div class="tabBox" style="margin-top: 0px" v-if="modelValue">
<el-table
ref="multipleUserRef"
@selection-change="handleSelectionChange"
:data="tableData"
border
style="width: 100%"
:row-key="keyid"
height="450"
>
<el-table-column
type="selection"
width="55"
:reserve-selection="true"
v-if="props.multiple"
/>
<el-table-column width="55" #default="{ row }" v-else>
<el-radio v-model="ridioIndex" :label="row.id"></el-radio>
</el-table-column>
<el-table-column
label="序号"
type="index"
align="center"
sortable
width="80"
/>
<el-table-column
sortable
prop="ssbm"
label="所属部门"
show-overflow-tooltip
align="center"
></el-table-column>
<el-table-column
sortable
prop="qcmc"
show-overflow-tooltip
label="圈层名称"
align="center"
>
</el-table-column>
<el-table-column
sortable
prop="qclx"
show-overflow-tooltip
label="圈层类型"
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_QCLX" :value="row.qclx" :tag="false" />
</template>
</el-table-column>
<el-table-column
sortable
prop="qcjb"
show-overflow-tooltip
label="圈层等级"
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_QCDJ" :value="row.qcjb" :tag="false" />
</template>
</el-table-column>
</el-table>
</div>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[2, 5, 10, 20]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import {
defineProps,
watch,
ref,
onMounted,
nextTick,
getCurrentInstance
} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_QCLX, D_BZ_QCDJ } = proxy.$dict("D_BZ_QCLX", "D_BZ_QCDJ");
const props = defineProps({
//是否显示
modelValue: {
type: Boolean,
required: true
},
//标题
titleValue: {
type: String,
default: "选择圈层"
},
//是否多选
multiple: {
default: true,
type: Boolean
},
//已经选中得数据回显
data: {
type: Array,
default: []
}
});
const keyid = (row) => {
return row.id;
};
const total = ref(0);
const ridioIndex = ref(null);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
qcmc: "",
ssbmdm: ""
});
const form = ref({});
const tableData = ref([]);
const emits = defineEmits(["close", "choosedQc"]);
const closed = () => {
emits("close", false);
};
const reset = () => {
listQuery.value = {
pageCurrent: 1,
pageSize: 20,
qcmc: "",
ssbmdm: ""
};
getListData();
};
//确认选中
const onComfirm = () => {
if (props.multiple) {
//多选
const List = JSON.parse(JSON.stringify(multipleSelectionUser.value));
if (List.length === 0) {
proxy.$message.warning("请选择圈层");
return;
}
emits("choosedQc", List);
} else {
//单选
if (![ridioIndex.value][0]) {
proxy.$message.warning("请选择圈层");
return;
}
const info = tableData.value.find((item) => {
return item.id === ridioIndex.value;
});
emits("choosedQc", [info]);
}
closed();
};
onMounted(() => {
getListData();
});
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageSize = currentPage;
getListData();
};
//圈层数据
const getListData = async () => {
qcckGet(listQuery.value, "/mosty-jcgl/qc/selectQcList").then((res) => {
tableData.value = res?.records;
multipleUser(props.data, tableData.value);
total.value = Number(res.total);
});
};
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const multipleUserRef = ref(null); //表单
//多选选中的数据
const multipleSelectionUser = ref([]);
const handleSelectionChange = (val) => {
multipleSelectionUser.value = val;
};
//回显
function multipleUser(row, list) {
if (row) {
if (props.multiple) {
row.forEach((item) => {
list.forEach((select) => {
if (item.id == select.id) {
if (multipleUserRef.value) {
multipleUserRef.value.toggleRowSelection(select, true);
}
}
});
});
}
}
}
watch(
() => props.modelValue,
(val) => {
if (val === true) {
handleFilter();
}
}
);
watch(
() => props.data,
(val) => {
if (multipleUserRef.value) multipleUser(val, tableData.value);
}
);
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
::v-deep .el-form--inline {
padding-left: 0 !important;
}
::v-deep .el-radio__label {
display: none;
}
</style>
<style lang="scss" >
.el-dialog {
--el-dialog-bg-color: #001238 !important;
}
.el-dialog__title {
color: #fff !important;
}
</style>

View File

@ -0,0 +1,49 @@
<template>
<div class="Select-wrap" :style="{ width: width }">
<el-select :disabled="props.disabled" v-bind="$attrs" v-model="modelValue" @change="hanlderSelect" :popper-class="selectOption.length > 20 ? 'nation-select' : ''" :placeholder="placeholder">
<el-option v-for="item in dictEnum" :key="item.value" :label="item.zdmc || item.label" :value="item.dm || item.value">
</el-option>
</el-select>
</div>
</template>
<script setup>
import { nextTick, onBeforeMount, ref } from "vue";
const emits = defineEmits(["change"]); //子组件向父组件事件传递
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择",
type: String
},
disabled:{
default: false,
type: Boolean
},
modelValue: {
default: "",
type: String
},
dictEnum: {
default: Array,
type: String
},
width: {
default: '100%',
type: String
}
});
const selectOption = ref([]);
const hanlderSelect = (data) => {
emits("change", data);
};
</script>
<style lang="scss" scoped>
.Select-wrap {
::v-deep .el-select {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,52 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-select :disabled="disabled" v-model="sex" placeholder="请选择性别" @change="onChange">
<el-option
v-for="item in D_BZ_XB"
:key="item"
:label="item.zdmc"
:value="item.dm"
></el-option>
</el-select>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import {
ref,
defineProps,
defineEmits,
defineExpose,
getCurrentInstance,
onBeforeMount
} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB");
const props = defineProps({
//获取组件传值
sex: {
type: String
},
disabled:{
type:Boolean,
default:false
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const emits = defineEmits(["update:sex"]);
const onChange = (e) => {
emits("update:sex", e);
};
</script>
<style lang="scss" scoped>
.manIcon,
.womanIcon {
font-size: 30px;
}
</style>

View File

@ -0,0 +1,49 @@
<template>
<div class="form-item-box zj-packageSelect-wrap" :style="{ width: width }">
<el-select v-bind="$attrs" :model-value="modelValue" @change="hanlderSelect" :popper-class="selectOption.length > 20 ? 'nation-select' : ''">
<el-option v-for="item in selectOption" :key="item.id" :label="item.postName" :value="item.id">
</el-option>
</el-select>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from '@/constant';
import { onBeforeMount, ref } from "vue";
import { selectJobPage } from "@/api/user-manage";
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
const props = defineProps({
//获取组件传值
placeholder: {
default: "请选择",
type: String
},
modelValue: {
default: "",
type: String
},
dictEnum: {
default: "",
type: String
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const selectOption = ref([]);
onBeforeMount(async () => {
const res = await selectJobPage({ page: 1, size: 9999 });
selectOption.value = [...res.records];
});
const hanlderSelect = (data) => {
emits("handleChange", data);
};
</script>
<style lang="scss" scoped>
.zj-packageSelect-wrap {
::v-deep .el-select {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,299 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-upload
v-bind="$attrs"
:headers="headers"
:multiple="false"
class="avatar-uploader"
:limit="props.limit"
:action="actionUrl"
list-type="picture-card"
:file-list="fileList"
show-file-list
:on-exceed="handleExceed"
:on-success="handlerSuccess"
:before-upload="beforeImgUpload"
>
<template #default>
<el-icon> <Plus /> </el-icon>
</template>
<template #file="{ file }">
<div v-if="props.isImg">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon>
<zoom-in />
</el-icon>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
</span>
</span>
</div>
<div v-else>
<div class="file-wrap">
<span>
<svg-icon :icon="getSuffix(file.name)" />
</span>
<span class="file-name">{{ file.name }}</span>
</div>
<span class="el-upload-list__item-actions">
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<el-icon>
<Download />
</el-icon>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
</span>
</span>
</div>
</template>
</el-upload>
<el-dialog v-model="dialogVisible">
<img style="width: 100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import {
ref,
defineProps,
defineEmits,
defineExpose,
computed,
watch,
onMounted
} from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type from "element-plus/es/components/upload/src/upload.type";
import { useStore } from "vuex";
const props = defineProps({
//获取组件传值
modelValue: {
type: Array,
default: []
},
limit: {
type: Number,
default: 1
},
isImg: {
type: Boolean,
default: true
},
width: {
default: COMPONENT_WIDTH,
type: String
}
});
const actionUrl = computed(() =>
props.isImg
? "/mosty-api/mosty-base/minio/image/upload/id"
: "/mosty-api/mosty-base/minio/file/upload"
);
const emits = defineEmits(["update:modelValue", "handleChange"]);
//获取后缀
const getSuffix = (fileName) => {
let suffix = "";
try {
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4); //截取最后一个点号后4个字符
} catch (err) {
suffix = "";
return "OTHER";
}
// fileName无后缀返回 false
if (!suffix) return "";
// 图片格式
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
if (imglist.includes(suffix)) return "IMG";
//txt
if (suffix === "txt") return "TXT";
//excel XLS
const excelist = ["xls", "xlsx"];
if (excelist.includes(suffix)) return "XLS";
// 匹配 word
var wordlist = ["doc", "docx"];
if (wordlist.includes(suffix)) return "DOC";
//pdf
if (suffix === "pdf") return "PDF";
//视频 音频
var videolist = [
"mp4",
"m2v",
"mkv",
"rmvb",
"wmv",
"avi",
"flv",
"mov",
"m4v"
];
if (videolist.includes(suffix)) return "VIDEO";
var musiclist = ["mp3", "wav", "wmv"];
if (musiclist.includes(suffix)) return "MUSIC";
var pptlist = ["ppt", "pptx"];
if (pptlist.includes(suffix)) return "PPT";
//压缩包
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
if (yslist.includes(suffix)) return "YS";
//否则返回other
return "OTHER";
};
const imageUrl = ref("");
const store = useStore();
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const disabled = ref(false);
const headers = ref({
Authorization: store.getters.token
});
onMounted(() => {
if (props.modelValue) {
fileList.value = props.modelValue.map((el) => {
return {
url: `/mosty-api/mosty-base/minio/image/download/` + el
};
});
}
});
const fileList = ref([]);
const handlerSuccess = (res, file) => {
file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
fileList.value.push(file);
props.modelValue.push(res.data);
emits("handleChange", props.modelValue);
// emits("update:modelValue", props.modelValue);
};
const handlePreview = (file) => {};
const handleExceed = (files, fileList) => {
ElMessage.warning(`限制,只能上传${props.limit}个文件或图片`);
};
const beforeImgUpload = (file) => {
if (props.isImg) {
let isIMG = false;
if (getSuffix(file.name) === "IMG") {
isIMG = true;
}
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isIMG) {
ElMessage.error("上传图片只能是jpg/png/jpeg/bmp/gif格式!");
}
if (!isLt5M) {
ElMessage.error("上传图片大小不能超过 5MB!");
}
return isIMG && isLt5M;
} else {
return true;
}
};
const handleAvatarSuccess = (res, file) => {
imageUrl.value = URL.createObjectURL(file.raw);
};
//查询图片
const handlePictureCardPreview = (file) => {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
};
const handleDownload = (file) => {
window.open(file.response.data);
};
const handleRemove = (file) => {
let index = fileList.value.findIndex(function (item) {
return item.url === file.url;
});
fileList.value.splice(index, 1);
props.modelValue.splice(index, 1);
emits("handleChange", props.modelValue);
// emits("update:modelValue", props.modelValue);
};
</script>
<style lang="scss" scoped>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.file-wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
::v-deep .svg-icon {
font-size: 48px;
margin: 28px 0 2px 0;
}
.file-name {
width: 88%;
font-size: 14px;
line-height: 22px;
text-align: center;
overflow: hidden;
/*将对象作为弹性伸缩盒子模型显示*/
display: -webkit-box;
/*设置子元素排列方式*/
-webkit-box-orient: vertical;
/*设置显示的行数,多出的部分会显示为...*/
-webkit-line-clamp: 2;
}
}
</style>

View File

@ -0,0 +1,40 @@
import AddressSelect from "./AddressSelect/index.vue";
import FrameWork from "./FrameWork/index.vue";
import FrameWork2 from "./FrameWork2/index.vue";
import Phone from "./Phone/index.vue";
import IdentityCard from "./IdentityCard/index.vue";
import Email from "./Email/index.vue";
import Other from "./Other/index.vue";
import Sex from "./Sex/index.vue";
import Select from "./Select/index.vue";
import Upload from "./Upload/index.vue";
import Department from "./Department/index.vue";
import DepartmentTree from "./DepartmentTree/index.vue";
import ChooseIcon from "./ChooseIcon/index.vue";
import StationSelect from "./StationSelect/index.vue";
import Provinces from "./Provinces2/index.vue";
import MarkdownEdit from "./MarkdownEdit/index.vue";
import FileUpload from "./FileUpload/index.vue";
import RichOnly from "./RichOnly/index.vue";
import Date from "./Date/index.vue";
export {
AddressSelect,
FrameWork,
Phone,
IdentityCard,
Email,
Other,
Sex,
Select,
Upload,
FrameWork2,
Department,
DepartmentTree,
ChooseIcon,
StationSelect,
Provinces,
MarkdownEdit,
FileUpload,
RichOnly,
Date
};

View File

@ -0,0 +1,63 @@
<template >
<!---外部图标-->
<div
v-bind="$attrs"
v-if="isExternal"
:style="styleExternalIcon"
class="svg-external-icon svg-icon"
:class="className"
/>
<!--内部图标-->
<svg v-else class="svg-icon" :class="className" aria-hidden="true" v-bind="$attrs">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup>
import { isExternal as external } from '@/utils/validate'
import { defineProps, computed } from 'vue'
const props = defineProps({
// icon 图标
icon: {
type: String,
required: true
},
// 图标类名
className: {
type: String,
default: ''
}
})
/**
* 判断是否为外部图标
*/
const isExternal = computed(() => external(props.icon))
/**
* 外部图标样式
*/
const styleExternalIcon = computed(() => ({
mask: `url(${props.icon}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.icon}) no-repeat 50% 50%`
}))
/**
* 项目内图标
*/
const iconName = computed(() => `#icon-${props.icon}`)
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div ref="watermarkContainerRef" class="watermark-container">
<!-- 插槽-->
<slot></slot>
</div>
</template>
<script setup>
import { ref, onMounted, watchEffect, onUnmounted, computed } from "vue";
// 使用 defineProps 定义一个组件的 props这些 props 描述了组件从父组件接收的属性
const props = defineProps({
// 文本内容,类型为字符串,必须提供,默认值为'张苹果博客'
text: {
type: Array,
required: true,
default: []
},
// 字体大小类型为数字默认值为10
fontSize: {
type: Number,
default: 15
},
// 间距类型为数字默认值为2
gap: {
type: Number,
default: 2
},
// 颜色,类型为字符串,默认值为' rgba(136, 135, 135, 0.58)'
color: {
type: String,
default: "rgba(136, 135, 135, 0.58)"
},
//角度 类型为数字 默认值 -45
angle: {
type: Number,
default: -45
}
});
/**
* 绘制多行文本
* @param ctx canvas对象
* @param words 文本数组
* @param x 坐标
* @param y 坐标(行高)
* @param maxWidth 最大宽度
*/
function drawTextWithWrap(ctx, words, x, y, maxWidth) {
let line = "";
const row = JSON.parse(JSON.stringify(y)); //拷贝一份Y的 行间距
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n];
const metrics = ctx.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > maxWidth) {
ctx.fillText(line, x, y);
line = words[n];
y = row * (n + 1);
} else {
line = testLine;
}
}
ctx.fillText(line, x, y);
}
// 定义一个用于绘制水印的函数,这里可以封装一下单独引入。
// 它是一个计算属性,意味着它的值会根据其依赖的 props 的变化而自动重新计算
const waterMarkBg = (props) => {
return computed(() => {
// 创建一个新的 canvas 元素
const canvas = document.createElement("canvas");
// 获取设备的像素比如果未定义则默认为1
const devicePixelRatio = window.devicePixelRatio || 1;
// 根据像素比计算字体大小
const fontSize = props.fontSize * devicePixelRatio;
// 设置字体样式
const font = fontSize + "px serif";
// 获取 canvas 的 2D 渲染上下文
const ctx = canvas.getContext("2d");
// 设置字体
ctx.font = font;
// 测量文本的宽度
// const { width } = ctx.measureText(props.text);
// 计算 canvas 的大小,至少为 60并根据文本宽度和间距因子进行调整
const canvasSize = Math.max(60, 180) * props.gap + devicePixelRatio;
// 设置 canvas 的宽高
canvas.width = canvasSize;
canvas.height = canvasSize;
// 将 canvas 的原点移动到中心
ctx.translate(canvas.width / 5, canvas.height / 5);
// 旋转 canvas 45 度
ctx.rotate((Math.PI / 180) * props.angle);
// 设置填充颜色
ctx.fillStyle = props.color;
// 设置文本对齐方式和基线
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// 再次设置字体
ctx.font = font;
drawTextWithWrap(ctx, props.text, 0, 25, 100);
// 在 canvas 上填充文本
// ctx.fillText(props.text, 0, 0);
// 返回一个对象,包含 base64 编码的图片数据、canvas 的大小和样式尺寸
return {
base64: canvas.toDataURL(),
size: canvasSize,
styleSize: canvasSize / devicePixelRatio
};
});
};
// 用于存储 MutationObserver 的变量
let ob;
// 用于存储水印 div 的变量
let div;
// 调用 waterMarkBg 函数获取水印相关的计算属性
const bg = waterMarkBg(props);
// 创建一个 ref 用于存储水印容器的 DOM 引用
const watermarkContainerRef = ref("");
// 创建一个 ref 用于标记水印是否需要重新生成
const flag = ref(0);
// 在组件挂载后执行
onMounted(() => {
// 创建一个新的 MutationObserver用于监听水印容器的变化
ob = new MutationObserver((records) => {
// 遍历所有的变化记录
for (const record of records) {
// 遍历所有被移除的节点
for (const dom of record.removedNodes) {
// 如果被移除的节点是水印 div则更新 flag 的值并返回
if (dom === div) {
flag.value++;
return;
}
}
// 如果变化的节点就是水印 div则更新 flag 的值并返回
if (record.target === div) {
flag.value++;
return;
}
}
});
// 包括子节点的变化、属性的变化以及子树的变化
ob.observe(watermarkContainerRef.value, {
childList: true,
attributes: true,
subtree: true
});
});
//卸载
onUnmounted(() => {
ob && ob.disconnect();
div = null;
});
// 生成水印
watchEffect(() => {
// 触发 watchEffect 的重新执行
flag.value;
// 如果水印容器没有值,则直接返回,不执行后续操作
if (!watermarkContainerRef.value) {
return;
}
// 如果之前已经存在水印 div则先移除它
if (div) {
div.remove();
}
// 创建一个新的 div 元素用于作为水印的容器
div = document.createElement("div");
// 从计算属性 bg 中获取 base64 编码的图片数据和样式尺寸
const { base64, styleSize } = bg.value;
// 设置 div 的背景图片为水印图片的 base64 编码
div.style.backgroundImage = `url(${base64})`;
// 设置背景图片的尺寸
div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
// 设置背景图片重复显示
div.style.backgroundRepeat = "repeat";
// 设置水印 div 的 z-index 为 9999以确保它显示在大多数其他元素之上
div.style.zIndex = 9999;
// 设置水印 div 不响应鼠标事件,如点击、悬停等
div.style.pointerEvents = "none";
// 设置水印 div 的位置为绝对定位
div.style.position = "absolute";
// 使用 inset 属性设置 div 占据整个父容器的空间
div.style.inset = "0";
// 将水印 div 添加到水印容器中
watermarkContainerRef.value.appendChild(div);
});
</script>
<style scoped>
.watermark-container {
position: relative;
height: 100vh;
color: rgba(136, 135, 135, 0.58);
}
</style>

View File

@ -0,0 +1,214 @@
<template>
<div style="width: 100%">
<!-- hasChildren要在tableData中定义表示当前行有没有下一级 children要在tableData中定义表示下一级的数据-->
<el-table
ref="multipleTableRef"
:data="tableData"
@selection-change="handleSelectionChange"
@current-change="handleCurrentChange"
@row-click="singleElection"
:row-key="getConfiger.rowKey"
:border="getConfiger.border"
:default-expand-all="getConfiger.defaultExpandAll"
:stripe="getConfiger.stripe"
:height="tableHeight"
v-loading="tableConfiger.loading"
:lazy="getConfiger.lazy"
:load="load"
:tree-props="treePros"
style="width: 100%"
:header-cell-class-name="() => 'HeadBgColor'"
:highlight-current-row="getConfiger.showSelectType === 'radio'"
:row-style="{ height: getConfiger.rowHeight === 'auto' ? getConfiger.rowHeight : getConfiger.rowHeight + 'px'}"
>
<el-table-column
type="selection"
width="55"
v-if="getConfiger.showSelectType === 'checkBox'"
/>
<el-table-column
width="55"
v-else-if="getConfiger.showSelectType === 'radio'"
#default="{ row }"
>
<el-radio
class="radio"
v-model="getConfiger.radioChoose"
:label="row[getConfiger.rowKey]"
>&nbsp;</el-radio
>
</el-table-column>
<el-table-column
type="index"
label="序号"
v-if="getConfiger.showIndex"
width="60"
:align="getConfiger?.align"
/>
<el-table-column
v-for="(item, index) in tableColumn"
:align="getConfiger?.align"
:prop="item.prop"
:key="index"
:label="item.label"
:width="item.width"
style="width: 100%; font-size: 14px"
:show-overflow-tooltip="item.showOverflowTooltip || false"
:sortable="item.sortable || false"
>
<!-- 使用自定义 -->
<template v-if="item.showSolt" #default="scope">
<slot :name="item.prop" v-bind="scope"></slot>
</template>
<!-- 默认 -->
<template v-else #default="{ row }">
{{ row[item.prop] }}
</template>
</el-table-column>
<!-- 操作 -->
<el-table-column
v-if="getConfiger.haveControls"
:fixed="fixed"
:label="getConfiger.controls"
:width="controlsWidth"
:align="getConfiger?.align"
>
<template #default="scope">
<slot name="controls" v-bind="scope"></slot>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { nextTick, onMounted, reactive, ref, watch, watchEffect } from "vue";
const props = defineProps({
tableConfiger: {
type: Object,
default: () => {}
},
tableData: {
type: Array,
default: () => []
},
tableColumn: {
type: Array,
default: () => {
return [];
}
},
controlsWidth: {
type: Number,
default: 180
},
tableHeight: {
type: Number
},
treePros: {
type: Object,
default: {
children: "children",
hasChildren: "hasChildren"
}
},
fixed: {
type: String,
default: "right"
}
});
// 可选的时候选择的数据
const emit = defineEmits(["chooseData"]);
const multipleTableRef = ref();
const currentRow = ref();
let getConfiger = reactive({
showSelectType: null, // 显示多选还是单选还是没有选择 checkBox/radio/null
showIndex: true, // 是否显示索引
rowKey: null, // 如果是树形表格必须设置rowKey
border: true, // 是否显示边框
defaultExpandAll: false, // 是否展开全部
loading: false,
align: "center", // 列的对齐方式 left / center / right
haveControls: true, // 是否有操作列
controls: "操作", // 操作列的表头
stripe: false, // 是否有斑马线
lazy: true, // 树形表格的懒加载必须在tableDatez中给有children的项设置 hasChildren: true,才会显示展开icon
portUrl: "", // 当树形表格使用懒加载的时候传入的请求路径/接口用于懒加载数据
defaultSelectKeys: [], // 默认选中的key集合
radioChoose: "", // 单选时选中的值------------- 待完成
rowHeight: "41" // 每行的高度
});
watchEffect(() => {
getConfiger = { ...getConfiger, ...props.tableConfiger };
setDefaultChoose();
});
onMounted(() => {
setDefaultChoose();
});
// 可选的时候选择的数据
const handleSelectionChange = (val) => {
emit("chooseData", val);
};
// 单选的时候选择的数据
const handleCurrentChange = (val) => {
currentRow.value = val;
emit("chooseData", val);
};
const singleElection = (val) => {
if (getConfiger.showSelectType === "radio") {
getConfiger.radioChoose = val[getConfiger.rowKey];
emit("chooseData", val);
}
};
// 懒加载数据的方法
const load = (date, treeNode, resolve) => {
setTimeout(() => {
resolve([
{
id: 31,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles"
},
{
id: 32,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles"
}
]);
}, 1000);
};
// 设置默认选中(在调用的父页面要确保 tableData传出来了如果延迟传过来默认选中不会生效
function setDefaultChoose() {
nextTick(() => {
// 多选的默认选中
if (
props.tableConfiger.defaultSelectKeys?.length > 0 &&
props.tableConfiger.showSelectType === "checkBox"
) {
props.tableData.forEach((item) => {
if (
props.tableConfiger.defaultSelectKeys.findIndex(
(v) => v === item[props.tableConfiger.rowKey]
) > -1
) {
multipleTableRef.value.toggleRowSelection(item, true);
}
});
// 单选的默认选中
} else if (
props.tableConfiger.defaultSelectKeys &&
props.tableConfiger.defaultSelectKeys?.length > 0 &&
props.tableConfiger.showSelectType === "radio"
) {
getConfiger.radioChoose = props.tableConfiger.defaultSelectKeys[0];
}
});
}
</script>
<style lang = "scss">
</style>

View File

@ -0,0 +1,71 @@
<template>
<div class="pageTitle" :style="`margin-bottom: ${marginBottom}px;background-color: ${backgroundColor}`">
<div class="title">
<ul class="flex" v-if="Array.isArray(title)">
<li :class=" idx == active ? 'hedBtn':''" @click="handleBtn(it,idx)" class="pointer ml10 mr10" v-for="(it,idx) in title" :key="it">{{ it }}</li>
</ul>
<div class="font" v-else>{{ title }}</div>
</div>
<div class="cnetr">
<slot name="center"></slot>
</div>
<div class="right">
<slot> </slot>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
defineProps({
title: {
type: String,
default: ""
},
marginBottom: {
type: Number,
default: 0
},
active: {
type: Number,
default: 0
},
backgroundColor: {
type: String,
default: "rgb(255, 255, 255, 0)"
}
});
const emit = defineEmits(["update:active","change"]);
const handleBtn = (it, idx) => {
emit("update:active", idx);
emit("change", idx);
};
</script>
<style lang = "scss" scoped>
.pageTitle {
width: 100%;
border-radius: 6px;
display: flex;
justify-content: space-between;
align-items: center;
min-height: 52px;
.title {
display: flex;
margin: auto 0;
.icon {
margin: auto 0;
}
.font {
vertical-align: middle;
font-size: 18px;
}
}
.hedBtn{
color: #0072ff;
}
}
</style>

View File

@ -0,0 +1,88 @@
<!--
* @Author: 表格分页
* @Date: 2023-10-20 09:34:38
* @LastEditTime: 2023-11-13 18:34:05
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \project\src\components\aboutTable\Pages\index.vue
-->
<template>
<div class="fenye" :style="{ top: tableHeight+10 + 'px' }">
<el-pagination
:current-page="
pageData.configer.currentPage ||
pageData.configer.pageNo ||
pageData.configer.current ||
pageData.configer.pageCurrent ||
pageData.configer.pageNum"
:page-size="pageData.configer.pageSize || pageData.configer.size"
:page-sizes="pageSizeArr"
:small="small"
:disabled="disabled"
:background="background"
layout="total, sizes, prev, pager, next, jumper"
:total="pageData.configer.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script setup>
import { reactive, ref, watchEffect } from "vue";
const props = defineProps({
pageSizeArr: {
type: Array,
default: () => [10, 20, 50, 100]
},
background: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
small: {
type: Boolean,
default: false
},
marginTop: {
type: Number,
default: 10
},
tableHeight: {
type: Number
},
pageConfiger: {
type: Object,
default: () => {
return {
pageSize: 10,
currentPage: 1,
total: 0
};
}
}
});
const pageData = reactive({
configer: {}
});
const emit = defineEmits(["changeSize", "changeNo"]);
// 改变每页条数
const handleSizeChange = (val) => {
emit("changeSize", val);
};
// 翻页
const handleCurrentChange = (val) => {
emit("changeNo", val);
};
watchEffect(() => {
pageData.configer = props.pageConfiger;
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,564 @@
<template>
<div
v-loading="loadingPage"
class="pageSearch searchBox"
:style="`margin-bottom: ${marginBottom}px;background-color: ${backgroundColor}`"
>
<div class="box">
<div v-for="(item, index) in getArr" :key="index" class="item">
<div class="label" v-if="item.label">{{ item.label }}</div>
<!-- select -->
<el-select
v-if="item.showType === 'select'"
v-model="searchObj[item.prop]"
:multiple="item.multiple"
:clearable="item.clearable"
:filterable="item.filterable"
:placeholder="item.placeholder"
collapse-tags
collapse-tags-tooltip
>
<el-option
v-for="obj in getOptions[item.prop]"
:key="obj.value"
:label="obj.label || obj.lable"
:value="obj.value"
/>
</el-select>
<!-- input -->
<el-input
v-else-if="item.showType === 'input'"
class="input"
v-model="searchObj[item.prop]"
:clearable="item.clearable"
:placeholder="item.placeholder"
/>
<!-- 日期段选择器 -->
<el-date-picker
v-else-if="item.showType === 'daterange'"
v-model="searchObj[item.prop]"
type="daterange"
unlink-panels
:range-separator="item.rangeSeparator"
:start-placeholder="item.startPlaceholder"
:end-placeholder="item.endPlaceholder"
:shortcuts="item.shortcuts"
:disabledDate="disabledDate"
value-format="YYYY-MM-DD"
/>
<el-date-picker
v-else-if="item.showType === 'date'"
v-model="searchObj[item.prop]"
type="date"
:placeholder="item.placeholder"
:disabled-date="disabledDate"
:shortcuts="item.shortcuts"
value-format="YYYY-MM-DD"
>
</el-date-picker>
<!-- checkbox -->
<template v-else-if="item.showType === 'department'">
<MOSTY.Department clearable v-model="item.ssbmdm" />
</template>
<!-- checkbox -->
<template v-else-if="item.showType === 'checkbox'">
<el-checkbox
v-if="item.showSelectAll"
v-model="item.checkAll"
:indeterminate="item.isIndeterminate"
@change=" (val) => { handleCheckAllChange(val, item); }"
>全选</el-checkbox>
<el-checkbox-group
v-model="searchObj[item.prop]"
@change=" (val) => { handleCheckedCitiesChange(val, item); }" >
<el-checkbox
v-for="obj in item.options"
:key="obj.value"
:label="obj.value"
>{{ obj.label }}</el-checkbox
>
</el-checkbox-group>
</template>
<!-- radio -->
<el-radio-group
v-else-if="item.showType === 'radio'"
v-model="searchObj[item.prop]"
@change="(val) => { handleRadioChange(val, item);}">
<el-radio
v-for="obj in item.options"
:key="obj.value"
:label="obj.value"
>{{ obj.label }}</el-radio
>
</el-radio-group>
<!-- 级联选择 -->
<el-cascader
v-else-if="item.showType === 'cascader'"
@change="changeca"
v-model="searchObj[item.prop]"
:props="item.props"
:show-all-levels="item.showAllLevels"
:clearable="item.clearable"
:options="getOptions[item.prop]"
:placeholder="item.placeholder"
/>
<div v-else-if="item.showType === 'defaultSlot'">
<slot name="defaultSlot"></slot>
</div>
</div>
<div class="flex">
<el-button type="primary" @click="submit">确定</el-button>
<el-button type="" @click="reset">重置</el-button>
<slot> </slot>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, watch, watchEffect, nextTick, getCurrentInstance, toRefs } from "vue";
import * as MOSTY from "@/components/MyComponents/index";
const { proxy } = getCurrentInstance();
const props = defineProps({
searchArr: {
type: Array,
default: () => {
return [
{
showType: "select",
prop: "selectKey",
options: [
{
value: 1,
label: "选择1"
}
],
defaultVal: "",
label: "选择",
dict: "" // 字典编码
},
{
showType: "input",
prop: "inputKey",
defaultVal: "",
label: "输入"
},
{
showType: "daterange",
prop: "daterangeKey",
defaultVal: "",
label: "输入"
},
{
showType: "date",
prop: "date",
defaultVal: ""
},
{
showType: "checkbox",
prop: "checkboxKey1",
options: [
{
value: 1,
label: "选择1"
}
],
defaultVal: ""
},
{
showType: "cascader",
prop: "cascaderKey",
label: "级联选择",
checkStrictly: false, //点击任意选中
defaultVal: ""
},
{
showType: "radio",
defaultVal: ""
// prop: "cascaderKey",
// label: "级联选择",
// checkStrictly: false //点击任意选中
},
{
showType: "defaultTime",
prop: "timeField",
options: [],
}
];
}
},
marginBottom: {
type: Number,
default: 15
},
backgroundColor: {
type: String,
default: "rgb(255, 255, 255, 1)"
}
});
let loadingPage = ref(false);
const isShowDate = ref(false);
const emit = defineEmits(["submit", "reset"]);
let searchObj = reactive({});
const timeConfig = reactive({ //时间字典筛选和自定义日期组件相关数据
typeValue:"01", //时间字典类型默认
timeArry:[], //时间筛选自定义默认值
})
//全所或自定义选择按钮
const slectType = ref('qs');
// select 的一些默认配置
const selectDefault = {
clearable: true, // 是否可以清空
filterable: true, // 是否可以筛选
multiple: false, // 是否多选
placeholder: "请选择"
};
// 重新定义下拉框的选项
let getOptions = reactive({});
// input 的一些默认配置
const inputDefault = {
clearable: true, // 是否可以清空
placeholder: "请输入"
};
const shortcuts = [
{
text: "今天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 0);
return [start, end];
}
},
{
text: "昨天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
return [start, end];
}
},
{
text: "最近7天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
return [start, end];
}
},
{
text: "最近30天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
return [start, end];
}
},
{
text: "最近90天",
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
return [start, end];
}
}
];
// daterange 的一些默认配置
const daterangeDefault = {
rangeSeparator: "至",
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
shortcuts: [], // 快捷选择
defaultShortcuts: true // 是否显示快捷选择 如果要自定义快捷选择传入一个shortcuts就可以了
};
// date 的一些默认配置
const defaultDate = {
clearable: true, // 是否可以清空
placeholder: "请输入",
shortcuts: [], // 快捷选择
defaultShortcuts: true // 是否显示快捷选择 如果要自定义快捷选择传入一个shortcuts就可以了
};
const dateShortcuts = [
{
text: "今天",
value: new Date()
},
{
text: "昨天",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
return date;
}
},
{
text: "7天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
return date;
}
},
{
text: "30天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 30);
return date;
}
},
{
text: "90天前",
value: () => {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 90);
return date;
}
}
];
//自定义时间选择 item 配置项 value 选中的值
const screenSelect = (item,value) => {
if(value == "08"){
searchObj[item.prop] = value;
isShowDate.value = true;
}else{
timeConfig.typeValue = value;
searchObj[item.prop] = value;
submit();
}
}
//自定义时间确定时间
const chooseDateOk = (item) => {
timeConfig.typeValue = "08";
if(timeConfig.timeArry && timeConfig.timeArry.length){ //选择了时间
searchObj[item.propStart] = timeConfig.timeArry[0];
searchObj[item.propEnd] = timeConfig.timeArry[1];
}else{ //清空了时间
searchObj[item.prop] = "01";
timeConfig.typeValue = "01";
}
isShowDate.value = false;
submit();
}
//全所-部门选择回调
const organizatioHland = (val) => {
let item = getArr.find(item=>item.showType == 'qsOrZdy');
searchObj[item.propBm] = val?.data?.orgCode || "";
if (!val || val == "") { //清空了部门选择后清空责任区ID
slectType.value = "qs";
delete searchObj[item.propZrq];
}
submit()
};
//全所-责任区回调
const zrqHland = (val) => {
let item = getArr.find(item=>item.showType == 'qsOrZdy');
searchObj[item.propZrq] = val || ""; //责任区选择
submit();
};
//自定义时间取消事件
const popoverCancel = (item) => {
isShowDate.value = false;
}
// 设置不可选的日期
const disabledDate = (time) => {
return time.getTime() > Date.now();
};
// checkbox 的一些默认配置
const defaultCheckbox = reactive({
defaultVal: [],
checkAll: false, // 全选的值
isIndeterminate: false, // 控制全选按钮样式
showSelectAll: true // 是否显示全选
});
// 全选复选框的选中与不选中
const handleCheckAllChange = (val, obj) => {
searchObj[obj.prop] = val ? obj.checkboxValueArr : [];
obj.isIndeterminate = false;
};
// 单个复选框的选中与不选中
const handleCheckedCitiesChange = (value, obj) => {
const checkedCount = value.length;
obj.checkAll = checkedCount === obj.checkboxValueArr.length;
obj.isIndeterminate =
checkedCount > 0 && checkedCount < obj.checkboxValueArr.length;
};
//单选
const handleRadioChange = (val, obj) => {
console.log(val, obj);
};
// cascader 的一些默认配置
let defaultCascader = {
filterable: true, // 是否可以搜索
clearable: true, // 是否可以清空
placeholder: "请选择",
checkStrictly: true, // 控制是否父子联动(是否可以选择任意节点)
showAllLevels: false, // 是否显示完整路径
lazy: true, // 是否懒加载 当设置为false时就要传入options
portUrl: "", // 这里必须写 接口地址
props: {
label: "label",
value: "value",
children: "children"
},
options: []
};
// 在懒加载状态下cascader 的props的一些配置
const cascaderLazyProps = reactive({
value: "value",
label: "label",
lazy: true,
lazyLoad(node, resolve) {
// 这里要根据实际情况修改
const { level } = node;
let options = [];
switch (level) {
case 0:
options = [
{
value: 1,
label: "选择1",
leaf: false // 表示有下一级 必须有这个表示 不然获取不到值
},
{
value: 2,
label: "选择2",
leaf: false // 表示有下一级
},
{
value: 3,
label: "选择3",
leaf: false // 表示有下一级
},
{
value: 4,
label: "选择4",
leaf: true // 表示没有下一级了
}
];
break;
case 1:
options = [
{
value: 11,
label: "选择1_1",
leaf: true // 表示没有下一级了
},
{
value: 21,
label: "选择2_1",
leaf: true // 表示没有下一级了
},
{
value: 31,
label: "选择3_1",
leaf: true // 表示没有下一级了
},
{
value: 41,
label: "选择4_1",
leaf: true // 表示没有下一级了
}
];
}
resolve(options);
}
});
// 级联框选择
function changeca(v) {
console.log("vvvv", v);
}
// 获取到传过来的参数
let getArr = reactive([]);
const submit = () => {
emit("submit", searchObj);
};
const reset = () => {
getArr.forEach((item) => {
searchObj[item.prop] = item.defaultVal ;
});
emit("submit", searchObj);
emit("reset", false);
};
let dataOptions = reactive([]); //时间字典筛选
watchEffect(() => {
loadingPage.value = true;
getArr = JSON.parse(JSON.stringify(props.searchArr));
getArr = getArr.map((item) => {
switch (item.showType) {
case "select":
item = { ...selectDefault, ...item };
item.options = reactive(item.options);
getOptions[item.prop] = item.options;
break;
case "input":
item = { ...inputDefault, ...item };
break;
case "daterange":
item = { ...daterangeDefault, ...item };
if (item.defaultShortcuts) {
item.shortcuts = shortcuts;
}
break;
case "date":
item = { ...defaultDate, ...item };
if (item.defaultShortcuts) {
item.shortcuts = dateShortcuts;
}
break;
case "checkbox":
item = reactive({ ...defaultCheckbox, ...item });
item.checkboxValueArr = item.options.map((obj) => {
return obj.value;
});
break;
case "cascader":
item = { ...defaultCascader, ...item };
if (item.lazy) {
cascaderLazyProps.checkStrictly = item.checkStrictly;
item.props = { ...cascaderLazyProps, ...(item.props || {}) };
delete item.options;
} else {
item.props = {
...defaultCascader.props,
...(item.props || {}),
...{ checkStrictly: item.checkStrictly }
};
getOptions[item.prop] = reactive(item.options);
}
break;
}
loadingPage.value = false;
searchObj[item.prop] = item.defaultVal ;
return item;
});
});
</script>
<style lang = "scss" scoped>
.pageSearch {
.box {
display: flex;
flex-wrap: wrap;
.item {
display: flex;
margin-right: 20px;
margin-bottom: 15px;
}
.label {
margin: auto;
margin-right: 5px;
white-space: nowrap;
color: #000;
}
}
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<div class="checkBox">
<el-checkbox class="checkall" :class="customClass" v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAll">全部</el-checkbox>
<el-checkbox-group v-model="hasChecked" @change="handleCheckedChange">
<span class="zwModel" :class="customClass"></span>
<el-checkbox :class="customClass" v-for="item in checkedList" :key="item" :label="item" :style="{width:props.width || 'auto'}">{{item}}</el-checkbox>
</el-checkbox-group>
</div>
</template>
<script setup>
import { ref, defineProps, watch, defineEmits } from "vue";
const emits = defineEmits(["changeData"]);
const props = defineProps({
data: {
type: Object,
default: {
list: [],
hasChoose: []
}
},
width:String,
customClass:String //自定义样式
});
const checkAll = ref(false);
const isIndeterminate = ref(true);
const hasChecked = ref([]); //已经全选的数据
const checkedList = ref([]);
watch(
() => props.data,
(val) => {
hasChecked.value = val.hasChoose;
checkedList.value = val.list;
handleChange(val.hasChoose); //判断是否全选
},
{
deep: true,
immediate: true
}
);
// 全选
function handleCheckAll(val) {
hasChecked.value = val ? checkedList.value : [];
isIndeterminate.value = false;
emits("changeData", hasChecked.value);
}
// 处理多选框改变
function handleCheckedChange(val) {
handleChange(val);////判断是否全选
emits("changeData", hasChecked.value);
}
//判断是否全选
function handleChange(val) {
let checkCount = val.length;
let len = checkedList.value.length;
checkAll.value = checkCount == len ? true : false;
isIndeterminate.value = checkCount > 0 && checkCount < len ? true : false;
}
</script>
<style lang="scss" scoped>
.checkBox {
display: flex;
flex-wrap:nowrap;
width:100%;
height:100%;
.checkall {
margin: 0 20px 0 4px;
}
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<transition name="el-zoom-in-center">
<div
class="el-popper is-pure is-light el-dropdown__popper ba-contextmenu"
:style="`top: ${state.axis.y + 18}px;left: ${ state.axis.x - 14 }px;width:150px`"
:key="Math.random()"
v-show="state.show"
aria-hidden="false"
data-popper-placement="bottom"
>
<ul class="el-dropdown-menu">
<template v-for="(item, idx) in props.items" :key="idx">
<li
class="el-dropdown-menu__item"
:class="item.disabled ? 'is-disabled' : ''"
tabindex="-1"
@click="onContextmenuItem(item)"
>
<Icon size="12" :name="item.icon" />
<span>{{ item.label }}</span>
</li>
</template>
</ul>
<span
class="el-popper__arrow"
:style="{ left: `${state.arrowAxis}px` }"
></span>
</div>
</transition>
</template>
<script setup>
import {
onMounted,
onUnmounted,
reactive,
toRaw,
defineProps,
defineEmits
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
const route = useRoute();
const props = defineProps({
items: {
type: Array,
default: []
}
});
const emits = defineEmits(["contextmenuItemClick"]);
const state = reactive({
show: false,
axis: {
x: 0,
y: 0
},
menu: {},
arrowAxis: 10
});
const onShowContextmenu = (menu, axis) => {
state.menu = menu;
state.axis = axis;
state.show = true;
};
const onContextmenuItem = (item) => {
if (item.disabled) return;
item.menu = toRaw(state.menu);
emits("contextmenuItemClick", item);
};
const onHideContextmenu = () => {
state.show = false;
};
defineExpose({
onShowContextmenu,
onHideContextmenu
});
onMounted(() => {
document.body.addEventListener("click", onHideContextmenu);
});
onUnmounted(() => {
document.body.removeEventListener("click", onHideContextmenu);
});
</script>
<style scoped lang="scss">
.ba-contextmenu {
z-index: 9999;
position: fixed;
}
.el-popper,
.el-popper.is-light .el-popper__arrow::before {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border: none;
}
.el-dropdown-menu__item {
padding: 8px 20px;
user-select: none;
}
.el-dropdown-menu__item .icon {
margin-right: 5px;
}
.el-dropdown-menu__item:not(.is-disabled) {
&:hover {
background-color: var(--el-dropdown-menuItem-hover-fill);
color: var(--el-dropdown-menuItem-hover-color);
.fa {
color: var(--el-dropdown-menuItem-hover-color) !important;
}
}
}
</style>

View File

@ -0,0 +1,179 @@
<template>
<div class="exportBox">
<el-dialog
v-model="show"
title="导入文件"
width="400px"
:show-close="true"
:center="true"
:before-close="handleClose"
>
<div class="uplodBox">
<el-upload
action="#"
drag
:on-success="handleSuccess"
:on-change="handleChange"
:show-file-list="true"
:file-list="fileDate"
accept=".xls,.xlsx"
:auto-upload="false"
>
<el-icon class="el-icon-upload" size="100"><upload-filled /></el-icon>
<div class="el-upload-text">
拖动或者点击上传或者<span @click.stop="downloadModel" class="model">下载模板</span>
</div>
<div>仅支持扩展名.xls , xlsx</div>
</el-upload>
</div>
<div class="check">
<el-checkbox true-label="true" false-label="false" v-model="isSelect"
>是否替换已存在的数据</el-checkbox
>
</div>
<div class="foot">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script setup>
import axios from "axios";
import { ElMessage } from "element-plus";
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
import { useStore } from "vuex";
import { ref, defineProps, defineEmits, watch } from "vue";
const store = useStore();
const props = defineProps({
show: { type: Boolean, default: false },
lx:{ type: String, default:'policeF'}
});
const headers = ref({
Authorization: "Bearer " + store.getters.token
});
const isSelect = ref(false);
const emits = defineEmits(["closeImport", "handleImport"]);
const fileDate = ref([]);
const filesList = ref({});
const baseUrl = ref('')//上传地址
const modelUrl = ref('')//下载模板地址
watch(()=>props.lx,(val)=>{
let url = ''
let moyRL = ''
switch (val) {
case 'policeF':
baseUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importTemplate'
break;
case 'car':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importTemplate'
break;
case 'jyqx':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importTemplate'
break;
case 'znzb':
baseUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importTemplate'
break;
default:
break;
}
},{
immediate:true
})
// 关闭
function handleClose() {
fileDate.value = [];
filesList.value = {};
emits("closeImport");
}
// 覆盖前一个文件
function handleChange(file, fileList) {
const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1);
let whiteList = ["xls", "xlsx"];
if (!whiteList.includes(fileSuffix)) {
fileList.splice(0, 1);
filesList.value = {};
ElMessage.warning("上传只能是.xls、.xlsx 格式,请重新上传");
return false;
} else {
if (fileList.length > 1) {
fileList.splice(0, 1);
}
filesList.value = file;
}
}
// 上传成功
function handleSuccess(row) {}
// 下载模板
function downloadModel() {
window.open(modelUrl.value, "_self");
}
// 确定上传
function onComfirm() {
if (filesList.value.length <= 0) {
ElMessage.warning("请上传文件");
} else {
let file = filesList.value.raw;
let formData = new FormData();
formData.append("file", file);
formData.append("updateSupport", isSelect.value);
axios.post(baseUrl.value, formData, {"Content-type": "multipart/form-data"})
.then((res) => {
if (res.status == 200) {
let { data, message, code } = res.data;
if (code == -1) ElMessage({ type:'warning', message:message, dangerouslyUseHTMLString:true });
if(code == 10000) ElMessage({ type:'success', message:data, dangerouslyUseHTMLString:true });
emits("handleImport");
handleClose();
} else {
ElMessage.warning("文件上传失败");
}
});
}
}
</script>
<style lang="scss" scoped>
.exportBox {
.uplodBox {
width: 100%;
.el-icon {
font-size: 64px;
color: #505050;
}
.el-icon-upload {
top: 33px;
}
::v-deep .el-upload-dragger {
line-height: 50px;
}
.el-upload-text {
color: #505050;
> .model {
color: #409eff;
}
}
}
.foot {
text-align: center;
margin: 10px 0;
}
.check {
height: 20px;
}
}
</style>
<style>
.el-upload-list__item-name {
color: #fff;
}
</style>

16
src/constant/formula.json Normal file
View File

@ -0,0 +1,16 @@
{
"shade-1": "color(primary shade(10%))",
"light-1": "color(primary tint(10%))",
"light-2": "color(primary tint(20%))",
"light-3": "color(primary tint(30%))",
"light-4": "color(primary tint(40%))",
"light-5": "color(primary tint(50%))",
"light-6": "color(primary tint(60%))",
"light-7": "color(primary tint(70%))",
"light-8": "color(primary tint(80%))",
"light-9": "color(primary tint(90%))",
"subMenuHover": "color(primary tint(70%))",
"subMenuBg": "color(primary tint(80%))",
"menuHover": "color(primary tint(90%))",
"menuBg": "color(primary)"
}

23
src/constant/index.js Normal file
View File

@ -0,0 +1,23 @@
// 用于保存各种常量
export const TOKEN = "token";
//时间戳
export const TIME_STAMP = "timeStamp";
//定义超时时长 2小时
export const TOKEN_TIMEOUT_VSLUE = 24 * 3600 * 1000 * 30;
//主题色保存的key
export const MAIN_COLOR = "mainColor";
//默认主题色
export const DEFAULT_COLOR = "#409eff";
// tags
export const TAGS_VIEW = "tagsView";
//form 表单 label-width
export const LABEL_WIDTH = "100px";
//form 表单 自定义宽度
export const COMPONENT_WIDTH = "240px";

225
src/constant/nation.json Normal file
View File

@ -0,0 +1,225 @@
[{
"id": "01",
"name": "汉族"
},
{
"id": "02",
"name": "蒙古族"
},
{
"id": "03",
"name": "回族"
},
{
"id": "04",
"name": "藏族"
},
{
"id": "05",
"name": "维吾尔族"
},
{
"id": "06",
"name": "苗族"
},
{
"id": "07",
"name": "彝族"
},
{
"id": "08",
"name": "壮族"
},
{
"id": "09",
"name": "布依族"
},
{
"id": "10",
"name": "朝鲜族"
},
{
"id": "11",
"name": "满族"
},
{
"id": "12",
"name": "侗族"
},
{
"id": "13",
"name": "瑶族"
},
{
"id": "14",
"name": "白族"
},
{
"id": "15",
"name": "土家族"
},
{
"id": "16",
"name": "哈尼族"
},
{
"id": "17",
"name": "哈萨克族"
},
{
"id": "18",
"name": "傣族"
},
{
"id": "19",
"name": "黎族"
},
{
"id": "20",
"name": "傈僳族"
},
{
"id": "21",
"name": "佤族"
},
{
"id": "22",
"name": "畲族"
},
{
"id": "23",
"name": "高山族"
},
{
"id": "24",
"name": "拉祜族"
},
{
"id": "25",
"name": "水族"
},
{
"id": "26",
"name": "东乡族"
},
{
"id": "27",
"name": "纳西族"
},
{
"id": "28",
"name": "景颇族"
},
{
"id": "29",
"name": "柯尔克孜族"
},
{
"id": "30",
"name": "土族"
},
{
"id": "31",
"name": "达斡尔族"
},
{
"id": "32",
"name": "仫佬族"
},
{
"id": "33",
"name": "羌族"
},
{
"id": "34",
"name": "布朗族"
},
{
"id": "35",
"name": "撒拉族"
},
{
"id": "36",
"name": "毛难族"
},
{
"id": "37",
"name": "仡佬族"
},
{
"id": "38",
"name": "锡伯族"
},
{
"id": "39",
"name": "阿昌族"
},
{
"id": "40",
"name": "普米族"
},
{
"id": "41",
"name": "塔吉克族"
},
{
"id": "42",
"name": "怒族"
},
{
"id": "43",
"name": "乌孜别克族"
},
{
"id": "44",
"name": "俄罗斯族"
},
{
"id": "45",
"name": "鄂温克族"
},
{
"id": "46",
"name": "崩龙族"
},
{
"id": "47",
"name": "保安族"
},
{
"id": "48",
"name": "裕固族"
},
{
"id": "49",
"name": "京族"
},
{
"id": "50",
"name": "塔塔尔族"
},
{
"id": "51",
"name": "独龙族"
},
{
"id": "52",
"name": "鄂伦春族"
},
{
"id": "53",
"name": "赫哲族"
},
{
"id": "54",
"name": "门巴族"
},
{
"id": "55",
"name": "珞巴族"
},
{
"id": "56",
"name": "基诺族"
}
]

14538
src/constant/pca-code.json Normal file

File diff suppressed because it is too large Load Diff

6
src/directives/index.js Normal file
View File

@ -0,0 +1,6 @@
import permission from "./permission";
export default app => {
app.directive('permission',permission)
}

View File

@ -0,0 +1,34 @@
import store from '@/store'
function checkPermission(el,binding) {
//获取对应的权限
const { value } = binding;
//获取当前用户的所有功能权限
const buttonPermission = store.getters.userInfo?.permission?.buttonPermission;
//value必须是一个数组
if (value && value instanceof Array && buttonPermission.length > 0) {
//匹配对应的指令
const hasPermission = buttonPermission.some(item => {
return value.includes(item)
})
//匹配失败
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new ErrorEvent('v-permisss value must 酱紫【"admin" ,"login"】...')
}
}
export default {
//在绑定 元素的父组件被挂载之后调用
mounted (el,binding) {
checkPermission(el,binding)
},
// 在包含组件的VNode 及其子组件的VNode更新后调用
update (el,binding) {
checkPermission(el,binding)
}
}

29
src/filters/index.js Normal file
View File

@ -0,0 +1,29 @@
import dayjs from "dayjs";
// https://dayjs.fenxianglu.cn/category/display.html#%E6%A0%BC%E5%BC%8F%E5%8C%96
const dateFilter = (val, format = "YYYY-MM-DD HH:mm:ss") => {
if (val) {
if (!isNaN(val)) {
val = parseInt(val);
}
return dayjs(val).format(format);
} else {
return '--'
}
};
const isAvailable = (val) => {
if (val === 0) return true;
if (val == null || val == undefined || val == '' || val == 'undefined' || val == 'null') {
return false
} else {
return true
}
}
export default (app) => {
app.config.globalProperties.$filters = {
dateFilter,
isAvailable
};
};

15
src/icons/index.js Normal file
View File

@ -0,0 +1,15 @@
// 1.导入所有的svg图标
// 2.完成SvgIcon的全局注册
import SvgIcon from '@/components/SvgIcon';
// https://webpack.docschina.org/guides/dependency-management/#requirecontext
// 通过 require.context() 函数来创建自己的 context
const svgRequire = require.context('./svg', false, /\.svg$/);
// 此时返回一个 require 的函数,可以接受一个 request 的参数,用于 require 的导入。
// 该函数提供了三个属性,可以通过 require.keys() 获取到所有的 svg 图标
// 遍历图标,把图标作为 request 传入到 require 导入函数中,完成本地 svg 图标的导入
svgRequire.keys().forEach((svgIcon) => svgRequire(svgIcon));
export default (app) => {
app.component('SvgIcon', SvgIcon);
};

1
src/icons/svg/DOC.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#4876F9" /><path d="M428.0192 768l77.1072-282.6688h1.4208L583.1808 768h43.0464L723.2 428.8h-43.52l-74.2656 284.5696H603.52L526.8864 428.8h-42.0992L407.68 713.3696h-1.8944L331.52 428.8H288l96.9728 339.2z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#B5C8FC" /></svg>

After

Width:  |  Height:  |  Size: 690 B

1
src/icons/svg/IMG.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#F6AD00" /><path d="M258.528 742.0672L351.8336 604.928a14.5024 14.5024 0 0 1 22.1696-2.1824l61.664 60.416 135.296-212.064a14.5024 14.5024 0 0 1 24.8064 0.5568l168.1024 291.328a14.5024 14.5024 0 0 1-12.5696 21.7664H270.528a14.5024 14.5024 0 0 1-12.0064-22.6816z" fill="#FFF7F7" /><path d="M359.616 431.5456m-73.1456 0a73.1456 73.1456 0 1 0 146.2912 0 73.1456 73.1456 0 1 0-146.2912 0Z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#FBDE99" /></svg>

After

Width:  |  Height:  |  Size: 871 B

1
src/icons/svg/MUSIC.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#7C8EEE" /><path d="M702.2976 579.2896l-298.5664 177.984c-19.9488 12.0192-45.3312-2.4128-45.3312-25.856v-355.968c0-22.848 25.3824-37.2736 45.3312-25.856l298.56 177.984c19.3408 12.032 19.3408 40.288 0 51.712z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#CAD1F8" /></svg>

After

Width:  |  Height:  |  Size: 695 B

1
src/icons/svg/OTHER.svg Normal file
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="1646892663179" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18971" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1014.272 251.392L762.88 10.752C756.736 5.12 749.568 2.048 741.376 2.048h-465.92C227.84 2.048 189.44 40.448 189.44 88.064V296.96H89.6C42.496 296.96 4.608 334.848 4.608 381.952v439.296c0 47.104 37.888 84.992 84.992 84.992H189.44v26.624c0 47.616 38.4 86.016 86.016 86.016h662.016c47.616 0 86.016-38.4 86.016-86.016V273.408c0-8.192-3.072-16.384-9.216-22.016zM757.76 91.136L925.184 250.88l-167.424-4.608V91.136zM89.6 844.8c-12.8 0-23.552-10.752-23.552-23.552V381.952c0-12.8 10.752-23.552 23.552-23.552h439.296c12.8 0 23.552 10.752 23.552 23.552v439.296c0 12.8-10.752 23.552-23.552 23.552H89.6z m872.448 88.064c0 13.312-11.264 24.576-24.576 24.576H275.456c-13.312 0-24.576-11.264-24.576-24.576V906.24h278.016c47.104 0 84.992-37.888 84.992-84.992V381.952c0-47.104-37.888-84.992-84.992-84.992H250.88V88.064c0-13.312 11.264-24.576 24.576-24.576H696.32V276.48c0 16.896 12.8 30.208 29.696 30.72l236.032 6.144v619.52zM262.656 707.584h-0.512z" fill="#646464" p-id="18972"></path><path d="M115.712 636.928l146.432 70.656v-53.248L173.056 614.4l89.6-39.936v-53.248l-146.944 71.168zM271.36 728.064h26.624l47.616-227.84h-26.624zM353.792 574.464l89.088 39.936-89.088 39.936v53.248l146.944-70.656v-44.544l-146.944-71.168z" fill="#646464" p-id="18973"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

1
src/icons/svg/PDF.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#FA4E4E" /><path d="M678.304 689.632c-34.5536-2.5664-67.8208-15.3984-94.6944-38.496-52.4672 11.5456-102.3808 28.224-152.288 48.7616C391.6544 770.4704 354.5408 806.4 322.5472 806.4c-6.4 0-14.0736-1.28-19.1936-5.1328-14.08-6.4128-21.7536-20.5312-21.7536-34.6432 0-11.552 2.56-43.6288 124.128-96.2432 28.16-51.328 49.9072-103.936 67.8272-159.1104-15.36-30.7968-48.6272-106.5088-25.6-144.9984 7.68-14.1184 23.04-21.8176 39.68-20.5312 12.7936 0 25.5872 6.4128 33.2672 16.6784 16.64 23.0976 15.36 71.8592-6.4 143.7184a386.9056 386.9056 0 0 0 79.3408 102.656c26.88-5.1392 53.7472-8.9856 80.6208-8.9856 60.1472 1.28 69.1072 29.5104 67.8272 46.1952 0 43.6288-42.2336 43.6288-63.9872 43.6288z m-358.3104 79.552l3.84-1.28c17.9136-6.4128 31.9872-19.2448 42.2272-35.9296-19.2 7.6992-34.5536 20.5312-46.0672 37.216z m170.1952-384.9472h-3.84c-1.28 0-3.84 0-5.12 1.28-5.12 21.8112-1.28 44.9088 7.68 65.44 7.68-21.8112 7.68-44.9088 1.28-66.72z m8.96 186.0608l-1.28 2.56-1.28-1.28c-11.52 29.5168-24.32 59.0272-38.3936 87.2576l2.56-1.28v2.56a743.6992 743.6992 0 0 1 87.0208-25.664l-1.28-1.28h3.84c-19.2-19.2512-37.1136-41.0624-51.1872-62.8736z m174.0352 68.0064c-11.52 0-21.7536 0-33.2736 2.56 12.8 6.4192 25.6 8.9856 38.3936 10.272 8.96 1.28 17.92 0 25.5936-2.5664 0-3.8528-5.12-10.2656-30.7136-10.2656z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#FDB8B8" /></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
src/icons/svg/PPT.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#FF9333" /><path d="M427.8976 768V610.9568H539.776c87.7952 0 132.224-38.1824 132.224-114.016C672 421.6448 628.1024 384 540.3136 384H384v384h43.8976z m109.7408-195.2256H427.8976v-150.592h109.7408c30.5088 0 52.992 5.92 67.9808 18.8288 14.9888 11.2896 22.4832 30.112 22.4832 55.936 0 25.8112-7.488 44.6336-21.952 57.0048-14.9824 12.3648-37.4656 18.816-68.512 18.816z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#FFD3AD" /></svg>

After

Width:  |  Height:  |  Size: 851 B

1
src/icons/svg/TXT.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#8289AD" /><path d="M536.9088 768V422.1824H672V384H358.4v38.1824h135.0912V768z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#CDCFDE" /></svg>

After

Width:  |  Height:  |  Size: 566 B

1
src/icons/svg/VIDEO.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#F16C00" /><path d="M727.8016 510.9952a58.7456 58.7456 0 0 1-8.8 21.1392c-3.4944 5.312-7.04 8.8704-10.592 7.0656-3.4944 0-5.2992-22.944-6.9952-26.5024a68.5376 68.5376 0 0 1-5.2928-19.392c-1.7536-14.1184-7.0464-26.5472-15.8976-31.808-8.7936-7.0592-21.0816-12.3712-36.9728-15.936a116.0896 116.0896 0 0 1-47.5776-21.1328c-14.0864-10.624-29.9264-19.4368-38.72-30.0608-8.8512-8.8128-15.8976-10.624-19.392-8.8128-5.2992 1.7536-7.0464 7.0656-7.0464 12.3712v328.48c0 8.8704-1.7472 19.4368-5.2992 30.0608-3.4944 10.624-5.2992 21.184-14.0928 31.7568-8.7936 10.624-21.1328 17.6832-36.9728 24.7488-15.8976 7.0656-35.232 10.624-56.4224 12.3712a127.7184 127.7184 0 0 1-63.4112-12.3712 126.4384 126.4384 0 0 1-44.0256-33.568c-10.592-14.1248-15.8912-28.2496-15.8912-45.9392 0-15.872 7.104-31.7568 22.9376-45.888 14.0928-14.1248 29.9328-24.7424 47.5712-30.0544 17.5936-5.312 33.4848-8.8128 49.3248-8.8128 15.8912 0 40.5248 0 52.864 3.552 12.2944 3.5072 21.1456 5.312 28.1856 7.0656V346.688c0-10.624 3.5008-19.392 8.8-26.4512 5.2928-7.0656 14.0864-10.624 22.88-12.3712 8.8512-1.7536 15.8976 0 21.1904 5.312 5.2992 3.5008 0 10.6176 6.9952 17.6256 5.2992 7.0656 12.3456 15.936 21.1904 26.5024 8.7936 10.624 19.3344 19.4368 33.4272 28.256 12.3456 8.8128 22.9376 14.1248 31.7312 19.4368 8.8 3.5072 17.6448 7.0656 24.6912 10.624 7.04 3.5008 15.84 7.008 22.8864 12.32 7.04 5.312 15.8912 12.3712 24.6336 22.9952 8.8448 10.624 14.0928 19.3856 15.8912 30.0032 0 10.624 0 21.1904-1.7984 30.0096v0.0512z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#F9C499" /></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

1
src/icons/svg/XLS.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#4CB050" /><path d="M400.256 768l114.656-164.5696L630.1632 768H684.8L541.4208 568.4736 674.4768 384H619.84L514.912 533.5104 410.496 384h-54.6176l131.9872 184.4736L345.6 768z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#B7DFB9" /></svg>

After

Width:  |  Height:  |  Size: 661 B

1
src/icons/svg/YS.svg Normal file
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 class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M160 0h512l256 256v704c0 35.3472-28.6528 64-64 64H160c-35.3472 0-64-28.6528-64-64V64c0-35.3472 28.6528-64 64-64z" fill="#576A95" /><path d="M582.4 629.2544v139.0592a34.7328 34.7328 0 0 1-10.208 24.5824 34.8608 34.8608 0 0 1-24.6272 10.1824H476.4352a34.8736 34.8736 0 0 1-24.6272-10.176A34.7328 34.7328 0 0 1 441.6 768.3072V629.2544h140.8z m-34.8352 79.6672H476.4352v69.824h71.1296v-69.824z m33.6704-218.7264v69.824H511.2768v-69.824h69.9584zM512.1472 0v70.4H582.4v70.4H512.1408v65.184H582.4v70.4H512.1472V345.92H582.4v69.536H512.1472v69.5296H441.6V415.4496h70.2528V345.9136H441.6V276.384h70.2528v-70.4H441.6v-70.4h70.2528V70.4H441.6V0h70.5472z" fill="#FFFFFF" /><path d="M672 0l256 256h-192c-35.3472 0-64-28.6528-64-64V0z" fill="#BBC3D4" /></svg>

After

Width:  |  Height:  |  Size: 1010 B

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<svg t="1626927201034" class="icon" viewBox="0 0 1079 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1754" width="128" height="128"><path d="M915.601 192.981H432.435c-27.528 0-50.048 22.58-50.048 50.168s22.528 50.176 50.048 50.176h483.166c27.537 0 50.048-22.58 50.048-50.176s-22.52-50.168-50.048-50.168zM276.975 203.99l-42.77-6.22c-3.404-0.717-6.348-2.927-7.56-5.778l-18.927-40.524c-7.244-15.787-28.475-15.787-35.737 0.034l-18.842 40.328c-1.817 3.397-4.557 5.615-7.45 5.914l-42.862 6.23c-16.52 2.747-23.04 23.398-11.256 35.694l30.823 31.104c2.483 2.594 3.66 6.076 3.046 9.242l-7.467 44.092c-2.645 17.237 14.533 30.284 29.099 21.998l38.118-20.65c3.09-1.784 6.23-1.784 9.2-0.068l38.331 20.77c14.473 8.234 31.65-4.813 29.022-21.965l-7.458-44.058c-0.316-3.447 0.793-7.023 3.089-9.42l30.703-30.985c11.836-12.348 5.325-32.99-11.102-35.738zM915.6 469.555H432.435c-27.528 0-50.048 22.58-50.048 50.16 0 27.587 22.528 50.175 50.048 50.175h483.166c27.537 0 50.048-22.58 50.048-50.176 0-27.58-22.52-50.159-50.048-50.159z m-638.626 7.996l-42.77-6.22c-3.404-0.726-6.348-2.936-7.56-5.778l-18.927-40.525c-7.244-15.795-28.475-15.795-35.737 0.034l-18.842 40.329c-1.817 3.396-4.557 5.615-7.45 5.914l-42.862 6.229c-16.52 2.748-23.04 23.398-11.256 35.678l30.823 31.104c2.483 2.585 3.66 6.075 3.046 9.233l-7.467 44.1c-2.645 17.237 14.533 30.285 29.099 21.999l38.118-20.65c3.09-1.784 6.23-1.784 9.2-0.069l38.331 20.77c14.473 8.235 31.65-4.813 29.022-21.965l-7.458-44.066c-0.316-3.439 0.793-7.014 3.089-9.412l30.703-30.976c11.836-12.348 5.325-32.998-11.102-35.73zM915.6 760.149H432.435c-27.528 0-50.048 22.58-50.048 50.168s22.528 50.176 50.048 50.176h483.166c27.537 0 50.048-22.58 50.048-50.176s-22.52-50.168-50.048-50.168z m-638.626 1.954l-42.77-6.22c-3.404-0.717-6.348-2.927-7.56-5.777l-18.927-40.525c-7.244-15.787-28.475-15.787-35.737 0.042l-18.842 40.329c-1.817 3.396-4.557 5.606-7.45 5.905l-42.862 6.23c-16.52 2.756-23.04 23.398-11.256 35.694l30.823 31.104c2.483 2.594 3.66 6.085 3.046 9.242l-7.467 44.092c-2.645 17.237 14.533 30.284 29.099 21.999l38.118-20.643c3.09-1.792 6.23-1.792 9.2-0.076l38.331 20.77c14.473 8.234 31.65-4.813 29.022-21.965l-7.458-44.058c-0.316-3.447 0.793-7.023 3.089-9.42l30.703-30.985c11.836-12.356 5.325-32.998-11.102-35.738z" p-id="1755"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg t="1626927228541" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1896" width="128" height="128"><path d="M895.146667 189.44H793.6v-19.626667c0-11.093333-9.386667-21.333333-22.186667-21.333333H652.8c-6.826667-25.6-20.48-47.786667-38.4-64.853333C587.946667 58.88 552.106667 42.666667 512 42.666667s-75.946667 15.36-102.4 40.96c-18.773333 17.92-32.426667 40.106667-38.4 64.853333H252.586667c-12.8 0-22.186667 9.386667-22.186667 21.333333v19.626667H128.853333c-20.48 0-36.693333 16.213333-36.693333 34.986667v721.066666c0 19.626667 16.213333 34.986667 36.693333 34.986667h766.293334c20.48 0 36.693333-15.36 36.693333-34.986667V224.426667c0-18.773333-16.213333-34.986667-36.693333-34.986667z m-454.826667-75.946667c17.92-17.92 43.52-28.16 70.826667-28.16 28.16 0 52.906667 10.24 71.68 28.16 10.24 9.386667 18.773333 22.186667 23.893333 34.986667H417.28c5.12-12.8 12.8-24.746667 23.04-34.986667z m-165.546667 77.653334h474.453334v66.56H274.773333v-66.56z m583.68 719.36H166.4V260.266667H230.4v18.773333c0 11.946667 9.386667 21.333333 22.186667 21.333333h518.826666c12.8 0 22.186667-9.386667 22.186667-21.333333v-18.773333h64.853333v650.24z m-563.2-349.866667c-20.48 0-36.693333 15.36-36.693333 35.84 0 19.626667 16.213333 34.986667 36.693333 34.986667s36.693333-15.36 36.693334-34.986667c0.853333-19.626667-16.213333-35.84-36.693334-35.84z m0 149.333333c-20.48 0-36.693333 15.36-36.693333 34.986667s16.213333 34.986667 36.693333 34.986667 36.693333-15.36 36.693334-34.986667c0.853333-19.626667-16.213333-34.986667-36.693334-34.986667z m431.786667-284.16H406.186667c-12.8 0-22.186667 9.386667-22.186667 21.333334s9.386667 21.333333 22.186667 21.333333h320.853333c11.946667 0 22.186667-9.386667 22.186667-21.333333-0.853333-11.093333-10.24-21.333333-22.186667-21.333334z m-431.786667-13.653333c-20.48 0-36.693333 16.213333-36.693333 34.986667 0 19.626667 16.213333 35.84 36.693333 35.84s36.693333-16.213333 36.693334-35.84c0.853333-18.773333-16.213333-34.986667-36.693334-34.986667z m431.786667 311.466667H406.186667c-12.8 0-22.186667 9.386667-22.186667 21.333333s9.386667 21.333333 22.186667 21.333333h320.853333c11.946667 0 22.186667-9.386667 22.186667-21.333333-0.853333-11.093333-10.24-21.333333-22.186667-21.333333z m0-148.48H406.186667c-12.8 0-22.186667 9.386667-22.186667 21.333333 0 11.093333 9.386667 20.48 22.186667 20.48h320.853333c11.946667 0 22.186667-9.386667 22.186667-20.48-0.853333-11.946667-10.24-21.333333-22.186667-21.333333z" p-id="1897"></path></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<svg t="1628162061044" class="icon" viewBox="0 0 1194 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5669" width="128" height="128"><path d="M475.192889 24.860444l-12.401778-19.911111H336.156444c-24.064 0-43.690667 7.395556-62.577777 21.788445-3.413333 2.616889-6.826667 5.461333-10.410667 8.704l-20.821333 19.342222-200.590223 199.111111c-37.205333 36.977778-47.388444 104.106667-3.072 159.061333l7.395556 7.168 36.067556 27.989334c27.136 21.504 54.272 43.576889 79.587555 65.024l12.174222 10.467555 24.576 21.731556 12.117334 11.036444 8.760889 8.305778v336.554667c0 64.853333 76.003556 115.939556 142.165333 115.939555H830.577778l8.305778-0.227555c64.056889-3.982222 133.802667-53.589333 133.802666-115.712v-335.075556l72.078222-62.065778 100.522667-85.333333 4.721778-4.664889c49.948444-57.628444 45.681778-127.772444-2.161778-175.217778L959.886222 55.523556c-39.708444-39.253333-62.577778-50.232889-101.603555-50.517334h-128.284445l-12.572444 19.057778c-3.413333 5.12-12.515556 15.075556-27.192889 25.6-25.315556 18.090667-56.775111 28.899556-95.402667 28.899556-38.570667 0-69.347556-10.808889-93.866666-28.672a106.723556 106.723556 0 0 1-25.770667-25.031112z m297.699555 65.024h85.105778l6.485334 0.227556c8.817778 0.853333 13.937778 4.380444 30.151111 20.195556l193.706666 189.098666 3.811556 4.152889c11.548444 14.051556 12.174222 30.378667-1.706667 49.208889l-2.901333 3.640889-54.215111 45.966222-87.552 74.922667-57.912889 50.062222v373.873778c0 9.216-32.540444 31.118222-57.287111 31.118222H361.472c-24.746667 0-57.230222-21.902222-57.230222-31.118222v-372.053334l-12.515556-12.458666a988.16 988.16 0 0 0-36.238222-34.247111l-13.937778-12.401778a2901.105778 2901.105778 0 0 0-106.894222-88.576l-32.369778-25.201778 2.446222 3.413333c-14.620444-18.147556-11.719111-37.148444-3.185777-45.624888l199.68-198.087112 13.880889-13.084444 7.224888-6.485333a77.937778 77.937778 0 0 1 2.844445-2.275556l3.015111-2.161778a12.856889 12.856889 0 0 1 7.964444-2.104889l82.545778-0.056888 6.257778 6.542222c7.224889 7.224889 15.928889 14.791111 25.998222 22.186666 38.570667 28.046222 86.641778 44.942222 143.872 44.942223 57.002667 0 105.415111-16.839111 144.611556-44.714667 13.710222-9.784889 24.803556-19.740444 33.507555-28.899556h-0.056889z" fill="#4A4A4A" p-id="5670"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>

After

Width:  |  Height:  |  Size: 2.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="1646468335217" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5413" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M384 146.285714l-21.321143 64H64V658.285714l82.761143-82.761143a64 64 0 0 1 84.516571-5.339428l6.034286 5.339428L320 658.285714l118.528-142.262857 137.472 206.262857L512 914.285714H64a64.036571 64.036571 0 0 1-63.561143-56.539428L0 850.285714V210.285714a64 64 0 0 1 56.539429-63.561143L64 146.285714h320z m576 0c32.877714 0 59.867429 24.649143 63.561143 56.539429L1024 210.285714v640a64 64 0 0 1-56.539429 63.561143L960 914.285714H640l64-192-194.377143-291.584 81.92-98.230857a63.963429 63.963429 0 0 1 92.342857-6.326857l5.412572 5.632 270.701714 315.830857V210.285714H490.678857L512 146.285714h448zM288.036571 274.285714c17.846857 0 34.596571 4.864 48.932572 13.385143L320 338.285714l52.150857 78.226286a96 96 0 1 1-84.114286-142.262857z" p-id="5414"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

After

Width:  |  Height:  |  Size: 497 B

View File

@ -0,0 +1 @@
<svg t="1628162413572" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1118" width="128" height="128"><path d="M730.4 694.4h174.4c6.4 0 13.6-2.4 18.4-7.2 9.6-9.6 9.6-25.6 0-35.2-4.8-4.8-11.2-7.2-18.4-7.2H668c-2.4 0-4 0.8-5.6 0.8-0.8 0-1.6 0-2.4 0.8-0.8 0-1.6 0.8-2.4 1.6-0.8 0.8-1.6 0.8-1.6 0.8-1.6 0.8-2.4 2.4-4 3.2-1.6 0.8-2.4 2.4-3.2 4-0.8 0.8-0.8 1.6-0.8 1.6-0.8 0.8-0.8 1.6-1.6 2.4 0 0.8-0.8 1.6-0.8 2.4-0.8 1.6-0.8 4-1.6 6.4v234.4c0 6.4 2.4 12.8 7.2 17.6 9.6 9.6 25.6 9.6 35.2 0 4.8-4.8 7.2-11.2 7.2-18.4v-171.2l220.8 220.8c9.6 9.6 25.6 9.6 35.2 0 9.6-9.6 9.6-25.6 0-35.2l-219.2-222.4zM644.8 353.6v1.6c0 2.4 0.8 4 0.8 5.6 0 0.8 0 1.6 0.8 2.4 0 0.8 0.8 1.6 1.6 2.4 0.8 0.8 0.8 1.6 0.8 1.6 0.8 1.6 2.4 2.4 3.2 4 1.6 0.8 2.4 2.4 4 3.2 0.8 0.8 1.6 0.8 1.6 0.8 0.8 0.8 1.6 0.8 2.4 1.6 0.8 0 1.6 0 2.4 0.8 1.6 0.8 4 0.8 6.4 1.6h234.4c6.4 0 12.8-2.4 17.6-7.2 9.6-9.6 9.6-25.6 0-35.2-4.8-4.8-11.2-7.2-18.4-7.2H731.2L952 106.4c9.6-9.6 9.6-25.6 0-35.2s-25.6-9.6-35.2 0L695.2 292V117.6c0-6.4-2.4-13.6-7.2-18.4-9.6-9.6-25.6-9.6-35.2 0-4.8 4.8-7.2 12-7.2 18.4l-0.8 236c0-0.8 0 0 0 0z m-266.4 316v-1.6c0-2.4-0.8-4-0.8-6.4 0-0.8 0-1.6-0.8-2.4 0-0.8-0.8-1.6-0.8-2.4 0-0.8-0.8-1.6-0.8-1.6-0.8-1.6-2.4-2.4-3.2-4-0.8-0.8-2.4-2.4-4-3.2-0.8-0.8-1.6-0.8-1.6-0.8-0.8-0.8-1.6-0.8-2.4-1.6-0.8 0-1.6-0.8-2.4-0.8-1.6-0.8-4-0.8-5.6-0.8h-237.6c-6.4 0-12.8 2.4-18.4 7.2-9.6 9.6-9.6 25.6 0 35.2 4.8 4.8 12 7.2 18.4 7.2h174.4L72 916c-9.6 9.6-9.6 25.6 0 35.2 9.6 9.6 25.6 9.6 35.2 0l220.8-220.8v171.2c0 6.4 2.4 12.8 7.2 18.4 9.6 9.6 25.6 9.6 35.2 0 4.8-4.8 7.2-11.2 7.2-17.6l0.8-232.8z m-85.6-341.6h-171.2c-6.4 0-12.8 2.4-18.4 7.2-9.6 9.6-9.6 25.6 0 35.2 4.8 4.8 11.2 7.2 17.6 7.2h234.4c2.4 0 4-0.8 6.4-1.6 0.8 0 1.6 0 2.4-0.8 0.8 0 1.6-0.8 2.4-1.6 0.8-0.8 1.6-0.8 1.6-0.8 1.6-0.8 2.4-2.4 4-3.2 0.8-1.6 2.4-2.4 3.2-4 0-0.8 0.8-1.6 0.8-1.6 0-0.8 0.8-1.6 1.6-2.4 0-0.8 0-1.6 0.8-2.4 0.8-1.6 0.8-4 0.8-5.6V117.6c0-6.4-2.4-12.8-7.2-18.4-9.6-9.6-25.6-9.6-35.2 0-4.8 4.8-7.2 12-7.2 18.4V292l-221.6-220.8c-9.6-9.6-25.6-9.6-35.2 0s-9.6 25.6 0 35.2l220 221.6z" fill="" p-id="1119"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

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