mirror of
https://github.com/crmeb/CRMEB.git
synced 2026-10-30 06:20:50 +00:00
Merge branch 'v5.0.0dev' of https://gitee.com/ZhongBangKeJi/CRMEB into v5.0.0dev
This commit is contained in:
commit
8f8415a966
@ -112,7 +112,7 @@ class SystemMenusDao extends BaseDao
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
public function column(array $where, string $field, string $key)
|
||||
public function column(array $where, string $field, string $key = '')
|
||||
{
|
||||
return $this->search($where)->column($field, $key);
|
||||
}
|
||||
|
||||
@ -228,8 +228,11 @@ class SystemMenusServices extends BaseServices
|
||||
*/
|
||||
public function delete(int $id)
|
||||
{
|
||||
if ($this->dao->count(['pid' => $id])) {
|
||||
throw new AdminException(400613);
|
||||
$ids = $this->dao->column(['pid' => $id], 'id');
|
||||
if (count($ids)) {
|
||||
foreach ($ids as $value) {
|
||||
$this->delete($value);
|
||||
}
|
||||
}
|
||||
return $this->dao->delete($id);
|
||||
}
|
||||
|
||||
@ -83,32 +83,33 @@ class SystemRouteServices extends BaseServices
|
||||
*/
|
||||
public function getTreeList(array $where, string $appName = 'adminapi')
|
||||
{
|
||||
$list = app()->make(SystemRouteCateServices::class)
|
||||
->selectList(['app_name' => $appName], '*', 0, 0, 'id asc,sort desc', [
|
||||
'children' => function ($query) use ($where) {
|
||||
$query->where('app_name', $where['app_name'])
|
||||
->when('' !== $where['name_like'], function ($q) use ($where) {
|
||||
$q->where('name|path', 'LIKE', '%' . $where['name_like'] . '%');
|
||||
});
|
||||
}
|
||||
])
|
||||
->toArray();
|
||||
return $this->cacheDriver()->remember('ROUTE_LIST', function () use ($where, $appName) {
|
||||
$list = app()->make(SystemRouteCateServices::class)
|
||||
->selectList(['app_name' => $appName], '*', 0, 0, 'id asc,sort desc', [
|
||||
'children' => function ($query) use ($where) {
|
||||
$query->where('app_name', $where['app_name'])
|
||||
->when('' !== $where['name_like'], function ($q) use ($where) {
|
||||
$q->where('name|path', 'LIKE', '%' . $where['name_like'] . '%');
|
||||
});
|
||||
}
|
||||
])
|
||||
->toArray();
|
||||
|
||||
foreach ($list as $key => $item) {
|
||||
if (!empty($item['children'])) {
|
||||
foreach ($item['children'] as $k => $v) {
|
||||
if (isset($v['cate_id']) && isset($v['method'])) {
|
||||
if ($v['method'] === 'DELETE') {
|
||||
$v['method'] = 'DEL';
|
||||
foreach ($list as $key => $item) {
|
||||
if (!empty($item['children'])) {
|
||||
foreach ($item['children'] as $k => $v) {
|
||||
if (isset($v['cate_id']) && isset($v['method'])) {
|
||||
if ($v['method'] === 'DELETE') {
|
||||
$v['method'] = 'DEL';
|
||||
}
|
||||
$v['pid'] = $v['cate_id'];
|
||||
$list[$key]['children'][$k] = $v;
|
||||
}
|
||||
$v['pid'] = $v['cate_id'];
|
||||
$list[$key]['children'][$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return get_tree_children($list);
|
||||
return get_tree_children($list);
|
||||
}, 600);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,11 +266,14 @@ class SystemRouteServices extends BaseServices
|
||||
foreach ($list as $key => $value) {
|
||||
foreach ($value as $item) {
|
||||
if (!$this->diffRoute($data, $item['rule'], $item['method']) && strstr($item['rule'], '<MISS>') === false) {
|
||||
$pathAndAction = explode('/', $item['route']);
|
||||
$save[] = [
|
||||
'name' => $item['option']['real_name'] ?? $item['name'],
|
||||
'path' => $item['rule'],
|
||||
'cate_id' => $key,
|
||||
'app_name' => $app,
|
||||
'file_path' => 'app/' . $app . '/controller/' . str_replace('.', '/', $pathAndAction[0]) . '.php',
|
||||
'action' => $pathAndAction[1],
|
||||
'type' => isset($item['option']['is_common']) && $item['option']['is_common'] ? 1 : 0,
|
||||
'method' => $item['method'],
|
||||
'add_time' => date('Y-m-d H:i:s'),
|
||||
@ -304,6 +308,7 @@ class SystemRouteServices extends BaseServices
|
||||
app()->make(SystemMenusServices::class)->deleteMenu($item['path'], $item['method']);
|
||||
}
|
||||
}
|
||||
$this->cacheDriver()->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -60,6 +60,7 @@
|
||||
"vue-awesome-swiper": "^4.1.1",
|
||||
"vue-clipboard2": "^0.3.3",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-cropper": "^0.5.11",
|
||||
"vue-happy-scroll": "^2.1.1",
|
||||
"vue-i18n": "^7.8.0",
|
||||
"vue-pickers": "^2.5.3",
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from '@/libs/request';
|
||||
import { getCookies } from '@/libs/util';
|
||||
|
||||
/**
|
||||
* @description 设置 系统设置 应用设置头部
|
||||
@ -1122,3 +1123,17 @@ export function codeCrud(data) {
|
||||
data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description 图片上传
|
||||
*/
|
||||
export function fileUpload(data) {
|
||||
return request({
|
||||
url: `file/upload`,
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Authori-zation': 'Bearer ' + getCookies('token'),
|
||||
'content-type': 'multipart/form-data;' + 'Bearer ' + getCookies('token'),
|
||||
},
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
280
template/admin/src/components/cropperImg/index.vue
Normal file
280
template/admin/src/components/cropperImg/index.vue
Normal file
@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div class="cropper-content">
|
||||
<div class="cropper-box">
|
||||
<div class="cropper">
|
||||
<vue-cropper
|
||||
ref="cropper"
|
||||
:img="option.img"
|
||||
:outputSize="option.outputSize"
|
||||
:outputType="option.outputType"
|
||||
:info="option.info"
|
||||
:canScale="option.canScale"
|
||||
:autoCrop="option.autoCrop"
|
||||
:autoCropWidth="option.autoCropWidth"
|
||||
:autoCropHeight="option.autoCropHeight"
|
||||
:fixed="option.fixed"
|
||||
:fixedNumber="option.fixedNumber"
|
||||
:full="option.full"
|
||||
:fixedBox="option.fixedBox"
|
||||
:canMove="option.canMove"
|
||||
:canMoveBox="option.canMoveBox"
|
||||
:original="option.original"
|
||||
:centerBox="option.centerBox"
|
||||
:height="option.height"
|
||||
:infoTrue="option.infoTrue"
|
||||
:maxImgSize="option.maxImgSize"
|
||||
:enlarge="option.enlarge"
|
||||
:mode="option.mode"
|
||||
@realTime="realTime"
|
||||
@imgLoad="imgLoad"
|
||||
>
|
||||
</vue-cropper>
|
||||
</div>
|
||||
<!--底部操作工具按钮-->
|
||||
<div class="footer-btn">
|
||||
<div class="scope-btn">
|
||||
<input
|
||||
type="file"
|
||||
id="uploads"
|
||||
style="position: absolute; clip: rect(0 0 0 0)"
|
||||
accept="image/png, image/jpeg, image/gif, image/jpg"
|
||||
@change="selectImg($event)"
|
||||
/>
|
||||
<el-button size="mini" type="danger" plain icon="el-icon-zoom-in" @click="changeScale(1)">放大</el-button>
|
||||
<el-button size="mini" type="danger" plain icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</el-button>
|
||||
<el-button size="mini" type="danger" plain @click="rotateLeft">↺ 左旋转</el-button>
|
||||
<el-button size="mini" type="danger" plain @click="rotateRight">↻ 右旋转</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--预览效果图-->
|
||||
<div class="show-preview">
|
||||
<div class="preview">
|
||||
<img :src="previews.url" :style="previews.img" />
|
||||
</div>
|
||||
<div class="upload-btn">
|
||||
<label class="btn" for="uploads">选择图片</label>
|
||||
<el-button size="mini" type="success" @click="uploadImg()">确认上传</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { VueCropper } from 'vue-cropper';
|
||||
// import { updateAvatar } from ''; //这里为文件上传的接口换成自己的文件
|
||||
import { fileUpload } from '@/api/setting';
|
||||
export default {
|
||||
name: 'CropperImage',
|
||||
components: {
|
||||
VueCropper,
|
||||
},
|
||||
props: ['Name'],
|
||||
data() {
|
||||
return {
|
||||
name: this.Name,
|
||||
resImg: '',
|
||||
previews: {},
|
||||
option: {
|
||||
img: this.Name, //裁剪图片的地址
|
||||
outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
|
||||
outputType: 'png', //裁剪生成图片的格式(jpeg || png || webp)
|
||||
info: true, //图片大小信息
|
||||
canScale: true, //图片是否允许滚轮缩放
|
||||
autoCrop: true, //是否默认生成截图框
|
||||
autoCropWidth: 200, //默认生成截图框宽度
|
||||
autoCropHeight: 200, //默认生成截图框高度
|
||||
fixed: false, //是否开启截图框宽高固定比例
|
||||
fixedNumber: [1.53, 1], //截图框的宽高比例
|
||||
full: false, //false按原比例裁切图片,不失真
|
||||
fixedBox: false, //固定截图框大小,不允许改变
|
||||
canMove: true, //上传图片是否可以移动
|
||||
canMoveBox: true, //截图框能否拖动
|
||||
original: false, //上传图片按照原始比例渲染
|
||||
centerBox: true, //截图框是否被限制在图片里面
|
||||
height: false, //是否按照设备的dpr 输出等比例图片
|
||||
infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高
|
||||
maxImgSize: 3000, //限制图片最大宽度和高度
|
||||
enlarge: 1, //图片根据截图框输出比例倍数
|
||||
mode: '300px 300px', //图片默认渲染方式
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
//初始化函数
|
||||
imgLoad(msg) {
|
||||
console.log('工具初始化函数=====' + msg);
|
||||
},
|
||||
//图片缩放
|
||||
changeScale(num) {
|
||||
num = num || 1;
|
||||
this.$refs.cropper.changeScale(num);
|
||||
},
|
||||
//向左旋转
|
||||
rotateLeft() {
|
||||
this.$refs.cropper.rotateLeft();
|
||||
},
|
||||
//向右旋转
|
||||
rotateRight() {
|
||||
this.$refs.cropper.rotateRight();
|
||||
},
|
||||
// //实时预览函数
|
||||
realTime(data) {
|
||||
let that = this;
|
||||
that.previews = data;
|
||||
this.$refs.cropper.getCropBlob((data) => {
|
||||
this.blobToDataURI(data, function (res) {
|
||||
that.previewImg = res;
|
||||
});
|
||||
});
|
||||
},
|
||||
blobToDataURI(blob, callback) {
|
||||
var reader = new FileReader();
|
||||
reader.readAsDataURL(blob);
|
||||
reader.onload = function (e) {
|
||||
callback(e.target.result);
|
||||
};
|
||||
},
|
||||
//选择图片
|
||||
selectImg(e) {
|
||||
let file = e.target.files[0];
|
||||
if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
|
||||
this.$message({
|
||||
message: '图片类型要求:jpeg、jpg、png',
|
||||
type: 'error',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
//转化为blob
|
||||
let reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
let data;
|
||||
if (typeof e.target.result === 'object') {
|
||||
data = window.URL.createObjectURL(new Blob([e.target.result]));
|
||||
} else {
|
||||
data = e.target.result;
|
||||
}
|
||||
this.option.img = data;
|
||||
};
|
||||
//转化为base64
|
||||
reader.readAsDataURL(file);
|
||||
},
|
||||
|
||||
base64ImgtoFile(dataurl, filename = 'file') {
|
||||
//将base64格式分割:['data:image/png;base64','XXXX']
|
||||
const arr = dataurl.split(',');
|
||||
// .*? 表示匹配任意字符到下一个符合条件的字符 刚好匹配到:
|
||||
// image/png
|
||||
const mime = arr[0].match(/:(.*?);/)[1]; //image/png
|
||||
//[image,png] 获取图片类型后缀
|
||||
const suffix = mime.split('/')[1]; //png
|
||||
const bstr = atob(arr[1]); //atob() 方法用于解码使用 base-64 编码的字符串
|
||||
let n = bstr.length;
|
||||
const u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
return new File([u8arr], `${filename}.${suffix}`, {
|
||||
type: mime,
|
||||
});
|
||||
},
|
||||
|
||||
uploadFile(file) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
fileUpload(formData).then((res) => {
|
||||
console.log(res);
|
||||
if (res.status == 200) {
|
||||
this.$emit('uploadImgSuccess', res.data);
|
||||
} else {
|
||||
this.$message({
|
||||
message: '上传失败',
|
||||
type: 'error',
|
||||
duration: 1000,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
//上传图片
|
||||
uploadImg() {
|
||||
this.$refs.cropper.getCropData((data) => {
|
||||
this.resImg = this.base64ImgtoFile(data);
|
||||
this.uploadFile(this.resImg);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.btn {
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
text-align: center;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
outline: 0;
|
||||
-webkit-transition: 0.1s;
|
||||
transition: 0.1s;
|
||||
font-weight: 500;
|
||||
padding: 8px 15px;
|
||||
font-size: 12px;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
background-color: #409eff;
|
||||
border-color: #409eff;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.cropper-content {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
justify-content: flex-end;
|
||||
.cropper-box {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
.cropper {
|
||||
width: auto;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.show-preview {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
.preview {
|
||||
overflow: hidden;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background: #cccccc;
|
||||
transform: scale(0.8);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-btn {
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
justify-content: space-around;
|
||||
.scope-btn {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
justify-content: space-between;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.upload-btn {
|
||||
flex: 1;
|
||||
-webkit-flex: 1;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<el-aside class="layout-aside" :class="setCollapseWidth" v-if="clientWidth > 1000">
|
||||
<Logo v-if="setShowLogo && menuList.length && getThemeConfig.layout !== 'columns'" />
|
||||
<el-divider
|
||||
v-if="menuList.length && !getThemeConfig.isCollapse && getThemeConfig.layout == 'columns'"
|
||||
content-position="center"
|
||||
>{{ catName }}</el-divider
|
||||
>
|
||||
<div v-if="menuList.length && !getThemeConfig.isCollapse && getThemeConfig.layout == 'columns'" class="cat-name">
|
||||
{{ catName }}
|
||||
</div>
|
||||
<el-scrollbar class="flex-auto" ref="layoutAsideRef">
|
||||
<Vertical :menuList="menuList" :class="setCollapseWidth" />
|
||||
</el-scrollbar>
|
||||
@ -132,3 +130,14 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.cat-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid var(--prev-border-color-lighter);
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
@click="onSetLayout('defaults')"
|
||||
>
|
||||
<section class="el-container el-circular">
|
||||
<aside class="el-aside w10 mr5"></aside>
|
||||
<aside class="el-aside w10 mr5" style="width: 17px"></aside>
|
||||
<section class="el-container is-vertical">
|
||||
<header class="el-header mb5" style="height: 10px"></header>
|
||||
<main class="el-main"></main>
|
||||
@ -31,6 +31,26 @@
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- columns 布局 -->
|
||||
<div
|
||||
class="layout-drawer-content-item"
|
||||
:class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }"
|
||||
@click="onSetLayout('columns')"
|
||||
>
|
||||
<section class="el-container el-circular">
|
||||
<aside class="el-aside mr5" style="width: 10px"></aside>
|
||||
<aside class="el-aside-dark mr5" style="width: 17px"></aside>
|
||||
<section class="el-container is-vertical">
|
||||
<!-- <header class="el-header" style="height: 10px"></header> -->
|
||||
<main class="el-main"></main>
|
||||
</section>
|
||||
</section>
|
||||
<!-- <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }">
|
||||
<div class="layout-tips-box">
|
||||
<p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- classic 布局 -->
|
||||
<div
|
||||
class="layout-drawer-content-item"
|
||||
@ -38,7 +58,7 @@
|
||||
@click="onSetLayout('classic')"
|
||||
>
|
||||
<section class="el-container is-vertical el-circular">
|
||||
<header class="el-header mb5" style="height: 10px"></header>
|
||||
<header class="el-aside mb5" style="height: 10px"></header>
|
||||
<section class="el-container">
|
||||
<aside class="el-aside mr5" style="width: 20px"></aside>
|
||||
<section class="el-container is-vertical">
|
||||
@ -52,6 +72,8 @@
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- transverse 布局 -->
|
||||
<div
|
||||
class="layout-drawer-content-item"
|
||||
@ -59,7 +81,7 @@
|
||||
@click="onSetLayout('transverse')"
|
||||
>
|
||||
<section class="el-container is-vertical el-circular">
|
||||
<header class="el-header mb5" style="height: 10px"></header>
|
||||
<header class="el-aside mb5" style="height: 10px"></header>
|
||||
<section class="el-container">
|
||||
<section class="el-container is-vertical">
|
||||
<main class="el-main"></main>
|
||||
@ -75,26 +97,6 @@
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- columns 布局 -->
|
||||
<div
|
||||
class="layout-drawer-content-item"
|
||||
:class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }"
|
||||
@click="onSetLayout('columns')"
|
||||
>
|
||||
<section class="el-container el-circular">
|
||||
<aside class="el-aside-dark mr5" style="width: 10px"></aside>
|
||||
<aside class="el-aside mr5" style="width: 17px"></aside>
|
||||
<section class="el-container is-vertical">
|
||||
<!-- <header class="el-header" style="height: 10px"></header> -->
|
||||
<main class="el-main"></main>
|
||||
</section>
|
||||
</section>
|
||||
<!-- <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }">
|
||||
<div class="layout-tips-box">
|
||||
<p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- 全局主题 -->
|
||||
<!-- <el-divider :content-position="contentPosotion">{{ $t('message.layout.oneTitle') }}</el-divider>
|
||||
|
||||
@ -38,11 +38,11 @@
|
||||
:width="300"
|
||||
popper-class="el-popover-pupop-user-news"
|
||||
>
|
||||
<el-badge :is-dot="true" @click.stop="isShowUserNewsPopover = !isShowUserNewsPopover" slot="reference">
|
||||
<el-badge :is-dot="isDot" @click.stop="openNews" slot="reference">
|
||||
<i class="el-icon-bell" :title="$t('message.user.title4')"></i>
|
||||
</el-badge>
|
||||
<transition name="el-zoom-in-top">
|
||||
<UserNews v-show="isShowUserNewsPopover" />
|
||||
<UserNews v-show="isShowUserNewsPopover" @haveNews="initIsDot" />
|
||||
</transition>
|
||||
</el-popover>
|
||||
</div>
|
||||
@ -54,7 +54,7 @@
|
||||
</div>
|
||||
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onDropdownCommand">
|
||||
<span class="layout-navbars-breadcrumb-user-link">
|
||||
<!-- <img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" /> -->
|
||||
<img :src="getUserInfos.head_pic" class="layout-navbars-breadcrumb-user-link-photo mr5" />
|
||||
{{ getUserInfos.account === '' ? 'test' : getUserInfos.account }}
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</span>
|
||||
@ -93,6 +93,7 @@ export default {
|
||||
disabledI18n: 'zh-cn',
|
||||
disabledSize: '',
|
||||
homePath: `${settings.routePre}/home`,
|
||||
isDot: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -116,6 +117,13 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initIsDot(status) {
|
||||
this.isDot = status;
|
||||
},
|
||||
openNews() {
|
||||
this.isShowUserNewsPopover = !this.isShowUserNewsPopover;
|
||||
this.isDot = false;
|
||||
},
|
||||
// 搜索点击
|
||||
onSearchClick() {
|
||||
this.$refs.searchRef.openSearch();
|
||||
@ -254,8 +262,8 @@ export default {
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
&-photo {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,18 +34,7 @@ export default {
|
||||
name: 'layoutBreadcrumbUserNews',
|
||||
data() {
|
||||
return {
|
||||
newsList: [
|
||||
{
|
||||
label: '关于版本发布的通知',
|
||||
value: '基于 vue2.x + element ui,正式发布时间:2020年11月15日!',
|
||||
time: '2020-11-15',
|
||||
},
|
||||
{
|
||||
label: '关于学习交流的通知',
|
||||
value: 'QQ群号码 665452019,欢迎小伙伴入群学习交流探讨!',
|
||||
time: '2020-11-15',
|
||||
},
|
||||
],
|
||||
newsList: [],
|
||||
newOrderAudioLink: null,
|
||||
};
|
||||
},
|
||||
@ -165,12 +154,12 @@ export default {
|
||||
this.newsList = [];
|
||||
},
|
||||
// 前往通知中心点击
|
||||
onGoToGiteeClick() {
|
||||
},
|
||||
onGoToGiteeClick() {},
|
||||
getNotict() {
|
||||
jnoticeRequest()
|
||||
.then((res) => {
|
||||
this.newsList = res.data || [];
|
||||
this.$emit('haveNews', !!this.newsList.length);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
|
||||
@ -19,11 +19,11 @@
|
||||
v-if="v.path !== tagsRoutePath && getThemeConfig.isTagsviewIcon"
|
||||
></i>
|
||||
<span>{{ $t(v.meta.title) }}</span>
|
||||
<i
|
||||
<!-- <i
|
||||
class="el-icon-refresh-right layout-navbars-tagsview-ul-li-icon ml5"
|
||||
v-if="v.path === tagsRoutePath"
|
||||
@click.stop="refreshCurrentTagsView(v.path)"
|
||||
></i>
|
||||
></i> -->
|
||||
<i
|
||||
class="el-icon-close layout-navbars-tagsview-ul-li-icon ml5"
|
||||
v-if="!v.isAffix"
|
||||
|
||||
@ -204,6 +204,15 @@ new Vue({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (to.name == 'product_productAdd') {
|
||||
let route = to.matched[1].path.split(':')[0];
|
||||
this.$store.state.menus.oneLvRoutes.map((e) => {
|
||||
if (route.indexOf(e.path) != -1) {
|
||||
to.meta.title = `${e.title} ${to.params.id ? 'ID:' + to.params.id : ''}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -1832,6 +1832,10 @@ export default {
|
||||
return this.isMobile ? undefined : 15;
|
||||
},
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
this.bus.$emit('onTagsViewRefreshRouterView', this.$route.path);
|
||||
next();
|
||||
},
|
||||
created() {
|
||||
this.columns = this.columns2.slice(0, 8);
|
||||
this.getToken();
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<Cascader :data="menuList" change-on-select v-model="formValidate.path" filterable></Cascader>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col v-bind="grid" v-if="!authType">
|
||||
<!-- <Col v-bind="grid" v-if="!authType">
|
||||
<FormItem label="请求方式:" prop="methods">
|
||||
<Select v-model="formValidate.methods">
|
||||
<Option value="">请求</Option>
|
||||
@ -49,15 +49,15 @@
|
||||
<Option value="DELETE">DELETE</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col v-bind="grid" v-if="!authType">
|
||||
</Col> -->
|
||||
<!-- <Col v-bind="grid" v-if="!authType">
|
||||
<FormItem label="接口地址:">
|
||||
<Input v-model="formValidate.api_url" placeholder="请输入接口地址" prop="api_url"></Input>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Col> -->
|
||||
<Col v-bind="grid" v-show="authType">
|
||||
<FormItem label="路由地址:" prop="menu_path">
|
||||
<Input v-model="formValidate.menu_path" placeholder="请输入路由地址">
|
||||
<Input v-model="formValidate.menu_path" placeholder="请输入路由地址" @on-change="changeUnique">
|
||||
<template #prepend>
|
||||
<span>{{ $routeProStr }}</span>
|
||||
</template>
|
||||
@ -69,7 +69,7 @@
|
||||
<Input v-model="formValidate.unique_auth" placeholder="请输入权限标识"></Input>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col v-bind="grid" v-show="authType">
|
||||
<Col v-bind="grid" v-if="authType">
|
||||
<FormItem label="图标:">
|
||||
<Input
|
||||
v-model="formValidate.icon"
|
||||
@ -80,12 +80,12 @@
|
||||
</FormItem>
|
||||
</Col>
|
||||
|
||||
<Col v-bind="grid">
|
||||
<Col v-bind="grid" v-if="authType">
|
||||
<FormItem label="排序:">
|
||||
<Input type="number" v-model="formValidate.sort" placeholder="请输入排序" number></Input>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col v-bind="grid" v-show="authType">
|
||||
<!-- <Col v-bind="grid" v-show="authType">
|
||||
<FormItem label="隐藏菜单:">
|
||||
<RadioGroup v-model="formValidate.is_show_path">
|
||||
<Radio :label="item.value" v-for="(item, i) in isShowPathRadio" :key="i">
|
||||
@ -94,7 +94,7 @@
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Col> -->
|
||||
<Col v-bind="grid">
|
||||
<FormItem label="状态:">
|
||||
<RadioGroup v-model="formValidate.is_show">
|
||||
@ -306,6 +306,12 @@ export default {
|
||||
this.ruleModal = false;
|
||||
}
|
||||
},
|
||||
changeUnique(val) {
|
||||
console.log(val.target.value);
|
||||
let value = this.$routeProStr + val.target.value;
|
||||
if (value.slice(0, 1) === '/') value = value.replace('/', '');
|
||||
this.formValidate.unique_auth = value.replaceAll('/', '-');
|
||||
},
|
||||
visible(type) {
|
||||
if (!type) {
|
||||
this.authType = true;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
</Row>
|
||||
<Row type="flex">
|
||||
<Col v-bind="grid">
|
||||
<Button v-auth="['setting-system_menus-add']" type="primary" @click="menusAdd('添加规则')" icon="md-add"
|
||||
<Button type="primary" @click="menusAdd('添加规则')" icon="md-add"
|
||||
>添加规则
|
||||
</Button>
|
||||
</Col>
|
||||
@ -43,10 +43,14 @@
|
||||
:data="tableData"
|
||||
row-id="id"
|
||||
>
|
||||
<vxe-table-column field="id" title="ID" tooltip min-width="70"></vxe-table-column>
|
||||
<vxe-table-column field="menu_name" tree-node title="按钮名称" min-width="100"></vxe-table-column>
|
||||
<vxe-table-column field="unique_auth" title="前端权限" min-width="200"></vxe-table-column>
|
||||
<vxe-table-column field="menu_path" title="页面路由" min-width="240" tooltip="true"></vxe-table-column>
|
||||
<vxe-table-column field="menu_path" title="路由" min-width="240" tooltip="true">
|
||||
<template v-slot="{ row }">
|
||||
<span v-if="row.auth_type == 1">页面:{{row.menu_path}}</span>
|
||||
<span v-if="row.auth_type == 2">接口:[{{row.methods}}]{{row.api_url}}</span>
|
||||
</template>
|
||||
</vxe-table-column>
|
||||
<vxe-table-column field="flag" title="规则状态" min-width="120">
|
||||
<template v-slot="{ row }">
|
||||
<i-switch
|
||||
@ -57,14 +61,14 @@
|
||||
@on-change="onchangeIsShow(row)"
|
||||
size="large"
|
||||
>
|
||||
<span slot="open">显示</span>
|
||||
<span slot="close">隐藏</span>
|
||||
<span slot="open">开启</span>
|
||||
<span slot="close">关闭</span>
|
||||
</i-switch>
|
||||
</template>
|
||||
</vxe-table-column>
|
||||
<vxe-table-column field="date" title="操作" align="center" width="250" fixed="right">
|
||||
<vxe-table-column field="date" title="操作" align="right" width="250" fixed="right">
|
||||
<template v-slot="{ row }">
|
||||
<span v-auth="['setting-system_menus-add']">
|
||||
<span>
|
||||
<a @click="addRoute(row)" v-if="row.auth_type === 1">添加权限</a>
|
||||
<Divider type="vertical" v-if="row.auth_type === 1" />
|
||||
<a @click="addE(row, '添加子菜单')" v-if="row.auth_type === 1">添加子菜单</a>
|
||||
@ -554,6 +558,9 @@ export default {
|
||||
width: 200px;
|
||||
overflow-y: scroll;
|
||||
max-height: 600px;
|
||||
/deep/ .el-tree-node__children .el-tree-node .el-tree-node__content {
|
||||
padding-left: 14px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,6 +2,12 @@
|
||||
<div>
|
||||
<Card :bordered="false" dis-hover class="ivu-mt">
|
||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="160" label-position="right">
|
||||
<FormItem label="头像">
|
||||
<div class="avatar" @click="avatarMoadl = true">
|
||||
<img v-if="formValidate.head_pic" :src="formValidate.head_pic" alt="" />
|
||||
<img v-else src="../../../assets/images/f.png" alt="" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="账号" prop="">
|
||||
<Input type="text" v-model="account" :disabled="true" class="input"></Input>
|
||||
</FormItem>
|
||||
@ -22,14 +28,19 @@
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
<Modal v-model="avatarMoadl" title="头像上传" width="700">
|
||||
<CropperImg v-if="avatarMoadl" @uploadImgSuccess="uploadImgSuccess"></CropperImg>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { updtaeAdmin } from '@/api/user';
|
||||
import { mapState } from 'vuex';
|
||||
import CropperImg from '@/components/cropperImg';
|
||||
export default {
|
||||
name: 'setting_user',
|
||||
components: { CropperImg },
|
||||
computed: {
|
||||
...mapState('media', ['isMobile']),
|
||||
...mapState('userLevel', ['categoryId']),
|
||||
@ -43,7 +54,9 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
account: '',
|
||||
avatarMoadl: false,
|
||||
formValidate: {
|
||||
avatar: '',
|
||||
real_name: '',
|
||||
pwd: '',
|
||||
new_pwd: '',
|
||||
@ -59,15 +72,21 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.account = this.$store.state.userInfo.userInfo.account;
|
||||
this.formValidate.head_pic = this.$store.state.userInfo.userInfo.head_pic;
|
||||
this.formValidate.real_name = this.$store.state.userInfo.userInfo.real_name;
|
||||
},
|
||||
methods: {
|
||||
uploadImgSuccess(data) {
|
||||
this.avatarMoadl = false;
|
||||
this.formValidate.head_pic = data.src;
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
updtaeAdmin(this.formValidate)
|
||||
.then((res) => {
|
||||
this.$store.commit('userInfo/userRealName', this.formValidate.real_name);
|
||||
this.$store.commit('userInfo/userRealHeadPic', this.formValidate.head_pic);
|
||||
this.$Message.success(res.msg);
|
||||
})
|
||||
.catch((res) => {
|
||||
@ -84,8 +103,18 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
.input {
|
||||
width: 400px;
|
||||
}
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #f2f2f2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -31,10 +31,10 @@
|
||||
<div></div>
|
||||
<div
|
||||
class="tree-node"
|
||||
:class="{ node: slotProps.model.method, open: formValidate.id == slotProps.model.id }"
|
||||
:class="{ node: slotProps.model.method, open: formValidate.path == slotProps.model.path && formValidate.method == slotProps.model.method }"
|
||||
@click.stop="onClick(slotProps.model)"
|
||||
>
|
||||
<span class="" :class="{ open: formValidate.id == slotProps.model.id }">{{
|
||||
<span class="" :class="{ open: formValidate.path == slotProps.model.path && formValidate.method == slotProps.model.method }">{{
|
||||
slotProps.model.name
|
||||
}}</span>
|
||||
<Dropdown
|
||||
@ -76,9 +76,9 @@
|
||||
class="req-method"
|
||||
:style="{
|
||||
color: methodsColor(slotProps.model.method),
|
||||
'font-weight': slotProps.model.id == formValidate.id ? '500' : '500',
|
||||
'font-weight': slotProps.model.pid == formValidate.pid ? '500' : '500',
|
||||
}"
|
||||
>{{ slotProps.model.method == 'delete' ? 'DEL' : slotProps.model.method || '' }}</span
|
||||
>{{ slotProps.model.method }}</span
|
||||
>
|
||||
|
||||
<!-- <span v-if="slotProps.model.method"></span> -->
|
||||
@ -172,15 +172,13 @@
|
||||
<Col span="24">
|
||||
<div class="title">调用方式</div>
|
||||
<FormItem label="路由地址:" prop="path">
|
||||
<Input
|
||||
v-if="isEdit"
|
||||
class="perW20"
|
||||
type="text"
|
||||
:rows="4"
|
||||
v-model.trim="formValidate.path"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
<span v-else>{{ formValidate.path || '' }}</span>
|
||||
<span>{{ formValidate.path || '' }}</span>
|
||||
</FormItem>
|
||||
<FormItem label="文件地址:" prop="path">
|
||||
<span>{{ formValidate.file_path || '' }}</span>
|
||||
</FormItem>
|
||||
<FormItem label="方法名:" prop="path">
|
||||
<span>{{ formValidate.action || '' }}</span>
|
||||
</FormItem>
|
||||
<FormItem label="请求参数:">
|
||||
<vxe-table
|
||||
@ -241,7 +239,7 @@
|
||||
<template #default="{ row }">
|
||||
<vxe-button
|
||||
type="text"
|
||||
v-if="row.type === 'array'"
|
||||
v-if="row.type === 'array' || row.type === 'object'"
|
||||
status="primary"
|
||||
@click="insertRow(row, 'xTable')"
|
||||
>插入</vxe-button
|
||||
@ -302,7 +300,7 @@
|
||||
<template #default="{ row }">
|
||||
<vxe-button
|
||||
type="text"
|
||||
v-if="row.type === 'array'"
|
||||
v-if="row.type === 'array' || row.type === 'object'"
|
||||
status="primary"
|
||||
@click="insertRow(row, 'resTable')"
|
||||
>插入</vxe-button
|
||||
@ -347,10 +345,11 @@
|
||||
keep-source
|
||||
ref="codeTable"
|
||||
row-id="id"
|
||||
is-tree-view
|
||||
:print-config="{}"
|
||||
:export-config="{}"
|
||||
:loading="loading"
|
||||
:tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
|
||||
:tree-config="{ rowField: 'id', parentField: 'parentId' }"
|
||||
:data="formValidate.error_code"
|
||||
>
|
||||
<!-- <vxe-column type="checkbox" width="60"></vxe-column> -->
|
||||
@ -625,10 +624,17 @@ export default {
|
||||
res.data[0].expand = false;
|
||||
this.treeData = new Tree(res.data);
|
||||
this.$nextTick((e) => {
|
||||
if (disk_type) document.querySelectorAll('.vtl-icon-caret-right')[0].click();
|
||||
if (disk_type) {
|
||||
if (res.data[0].children[0].children.length) {
|
||||
document.querySelectorAll('.vtl-icon-caret-right')[0].click();
|
||||
document.querySelectorAll('.vtl-icon-caret-right')[1].click();
|
||||
} else {
|
||||
document.querySelectorAll('.vtl-icon-caret-right')[0].click();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (res.data[0].children && res.data[0].children.length) {
|
||||
this.onClick(res.data[0].children[0]);
|
||||
this.onClick(res.data[0]?.children[0]?.children[0]);
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -668,6 +674,7 @@ export default {
|
||||
} else if (!this.formValidate.path) {
|
||||
return this.$Message.warning('请输入路由地址');
|
||||
}
|
||||
console.log(await this.$refs.xTable.getTableData());
|
||||
this.formValidate.request = await this.$refs.xTable.getTableData().tableData;
|
||||
this.formValidate.response = await this.$refs.resTable.getTableData().tableData;
|
||||
this.formValidate.error_code = await this.$refs.codeTable.getTableData().tableData;
|
||||
@ -1007,7 +1014,7 @@ export default {
|
||||
.tree-list{
|
||||
margin-left:10px;
|
||||
padding: 0 15px;
|
||||
|
||||
margin-top: 10px;
|
||||
}
|
||||
.vtl-caret{
|
||||
padding-right: 2px;
|
||||
@ -1015,7 +1022,8 @@ export default {
|
||||
.req-method {
|
||||
display:block;
|
||||
padding: 0px 2px;
|
||||
font-size: 12px;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
margin-right: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
@ -1031,7 +1039,7 @@ export default {
|
||||
padding: 3px 7px 3px 0;
|
||||
}
|
||||
.node{
|
||||
padding:7px 2px 7px 0px;
|
||||
padding:3px 2px 3px 0px;
|
||||
}
|
||||
.open {
|
||||
// background-color: #fff1ef;
|
||||
@ -1064,8 +1072,8 @@ export default {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
>>> .vtl-node-content:hover .add:hover {
|
||||
@ -1134,12 +1142,17 @@ export default {
|
||||
width: 100% !important;
|
||||
}
|
||||
>>> .vtl-tree-margin{
|
||||
margin-left: 5px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
>>> .ivu-btn-icon-only.ivu-btn-small {
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
>>> .tree-node > span{
|
||||
font-size: 14px
|
||||
}
|
||||
>>> .tree-node.node > span{
|
||||
font-size: 13px
|
||||
}
|
||||
.nothing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
<div v-else>--</div>
|
||||
</template>
|
||||
<template slot-scope="{ row, index }" slot="action">
|
||||
<a v-if="!foundation.primaryKey" @click="del(row, index)">删除</a>
|
||||
<a v-if="!tableField[index].primaryKey" @click="del(row, index)">删除</a>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</Table>
|
||||
|
||||
@ -59,6 +59,9 @@ export default {
|
||||
userRealName(state, realName) {
|
||||
state.userInfo.real_name = realName;
|
||||
},
|
||||
userRealHeadPic(state, headPic) {
|
||||
state.userInfo.head_pic = headPic;
|
||||
},
|
||||
uniqueAuth(state, uniqueAuth) {
|
||||
state.uniqueAuth = uniqueAuth;
|
||||
},
|
||||
|
||||
@ -38,15 +38,15 @@
|
||||
------------------------------- */
|
||||
.breadcrumb-enter-active,
|
||||
.breadcrumb-leave-active {
|
||||
transition: all 0.3s;
|
||||
// transition: all 0.3s;
|
||||
}
|
||||
.breadcrumb-enter,
|
||||
.breadcrumb-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
// transform: translateX(20px);
|
||||
}
|
||||
.breadcrumb-move {
|
||||
transition: all 0.3s;
|
||||
// transition: all 0.3s;
|
||||
}
|
||||
.breadcrumb-leave-active {
|
||||
position: absolute;
|
||||
|
||||
@ -338,7 +338,7 @@
|
||||
}
|
||||
|
||||
],
|
||||
virtual_type: 0,
|
||||
virtual_type: 0,
|
||||
allPrice: 0,
|
||||
formContent: '',
|
||||
payType: '', //支付方式
|
||||
@ -946,6 +946,7 @@
|
||||
onAddress: function() {
|
||||
let that = this;
|
||||
if (this.addressInfo.real_name) {
|
||||
this.$refs.addressWindow.getAddressList();
|
||||
that.textareaStatus = false;
|
||||
that.address.address = true;
|
||||
that.pagesUrl = '/pages/users/user_address_list/index?news=' + this.news + '&cartId=' + this
|
||||
@ -954,6 +955,7 @@
|
||||
this.pinkId +
|
||||
'&couponId=' +
|
||||
this.couponId;
|
||||
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/users/user_address/index?cartId=' + this.cartId + '&pinkId=' + this
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user