9 Commits

Author SHA1 Message Date
JaguarJack
c48607c123 feat: 优化 icons 选择器 2023-05-11 14:21:47 +08:00
JaguarJack
035ba22f52 fix: 重制搜索条件 2023-05-10 16:55:38 +08:00
JaguarJack
403501b214 update package.json 2023-05-10 16:53:52 +08:00
JaguarJack
c56a01df56 chore 2023-05-10 16:53:38 +08:00
JaguarJack
ac5e0957b9 fix: 上传文件路径转换 2023-05-10 16:53:22 +08:00
JaguarJack
948082f4ce fix: 权限组件路径符转换 2023-05-10 16:52:57 +08:00
JaguarJack
35622b164c chore: 优化角色交互 2023-05-10 16:52:17 +08:00
JaguarJack
cbb3c156a6 fix: 用户权限认证 2023-05-10 16:51:25 +08:00
JaguarJack
2d61786ec6 fixed: 转换 windows 路径 2023-05-08 15:38:06 +08:00
11 changed files with 116 additions and 63 deletions

View File

@@ -4,6 +4,7 @@ namespace Modules\Common\Support\Upload\Uses;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class LocalUpload extends Upload
{
@@ -25,7 +26,9 @@ class LocalUpload extends Upload
*/
protected function addUrl($path): mixed
{
$path['path'] = config('app.url') . '/'. $path['path'];
$path['path'] = config('app.url') . '/'.
Str::of($path['path'])->replace('\\', '/')->toString();
return $path;
}

View File

@@ -13,7 +13,6 @@ class {controller} extends Controller
){}
/**
* @param Request $request
* @return mixed
*/
public function index(): mixed

View File

@@ -6,6 +6,7 @@ namespace Modules\Permissions\Http\Controllers;
use Catch\Base\CatchController as Controller;
use Catch\Exceptions\FailedException;
use Illuminate\Http\Request;
use Modules\Permissions\Enums\DataRange;
use Modules\Permissions\Models\Roles;
use Modules\Permissions\Http\Requests\RoleRequest;
@@ -39,13 +40,15 @@ class RolesController extends Controller
*/
public function store(RoleRequest $request)
{
$dataRange = $request->get('data_range');
$data = $request->all();
if ($dataRange && ! DataRange::Personal_Choose->assert($request->get('data_range'))) {
$request['departments'] = [];
if ($request->get('data_range') && ! DataRange::Personal_Choose->assert($data['data_range'])) {
$data['departments'] = [];
} else {
$data['data_range'] = 0;
}
return $this->model->storeBy($request->all());
return $this->model->storeBy($data);
}
/**
@@ -53,11 +56,15 @@ class RolesController extends Controller
* @param $id
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function show($id)
public function show($id, Request $request)
{
$role = $this->model->firstBy($id);
$role->setAttribute('permissions', $role->permissions()->get()->pluck('id'));
if ($request->has('from') && $request->get('from') == 'parent_role') {
$role->setAttribute('permissions', $role->permissions()->get()->toTree());
} else {
$role->setAttribute('permissions', $role->permissions()->get()->pluck('id'));
}
$role->setAttribute('departments', $role->departments()->pluck('id'));
@@ -76,9 +83,11 @@ class RolesController extends Controller
if ($request->get('data_range') && ! DataRange::Personal_Choose->assert($data['data_range'])) {
$data['departments'] = [];
} else {
$data['data_range'] = 0;
}
return $this->model->updateBy($id,$data);
return $this->model->updateBy($id, $data);
}
/**

View File

@@ -10,6 +10,7 @@ use Catch\Enums\Status;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Modules\Permissions\Enums\MenuStatus;
use Modules\Permissions\Enums\MenuType;
@@ -199,6 +200,7 @@ class Permissions extends Model
$data['route'] = '/'.trim($data['route'], '/');
}
$data['component'] = Str::of($data['component'])->replace('\\', '/')->toString();
return parent::storeBy($data);
});
}
@@ -244,6 +246,7 @@ class Permissions extends Model
$data['permission_mark'] = $parentMenu->permission_mark.'@'.$data['permission_mark'];
}
$data['component'] = Str::of($data['component'])->replace('\\', '/')->toString();
return parent::updateBy($id, $data);
}
}

View File

@@ -42,7 +42,14 @@
<Select v-model="formData.permission_mark" allow-create placeholder="请选择" api="controllers" :query="{ module: formData.module }" v-else />
</el-form-item>
<el-form-item label="菜单Icon" prop="icon" v-if="!isAction">
<el-input v-model="formData.icon" name="icon" clearable @click="open" />
<el-popover placement="right" :width="400" trigger="click">
<template #reference>
<el-input v-model="formData.icon" name="icon" clearable />
</template>
<div>
<Icons v-model="formData.icon" @close="closeSelectIcon" />
</div>
</el-popover>
</el-form-item>
<el-form-item label="所属组件" prop="component" v-if="!isAction">
<Select v-model="formData.component" placeholder="请选择" allow-create api="components" :query="{ module: formData.module }" />
@@ -92,10 +99,6 @@
<el-button type="primary" @click="submitForm(form)">{{ $t('system.confirm') }}</el-button>
</div>
</el-form>
<Dialog v-model="visible" title="选择 Icon" width="1000px" destroy-on-close>
<Icons v-model="formData.icon" @close="closeSelectIcon" />
</Dialog>
</template>
<script lang="ts" setup>

View File

@@ -105,7 +105,7 @@ const { formData, form, loading, submitForm, close, beforeCreate, beforeUpdate }
if (props.primary) {
const { afterShow } = useShow(props.api, props.primary, formData)
// 更新角色值
afterShow.value = formData => {
const data = unref(formData)
data.parent_id = data.parent_id ? [data.parent_id] : 0
@@ -115,6 +115,8 @@ if (props.primary) {
}
formData.value = data
// 这里需要获取角色的上级的权限以限制可用权限范围
getPermissions(data.parent_id)
}
}
@@ -127,9 +129,12 @@ const departments = ref()
const showDepartments = ref<boolean>(false)
const permissionLoadingText = ref<string>('加载中...')
// 获取权限
const getPermissions = async (value: number = 0) => {
if (value) {
http.get('permissions/roles/' + getParent(value)).then(r => {
// 获取角色权限
http.get('permissions/roles/' + getParent(value), { from: 'parent_role' }).then(r => {
permissions.value = r.data.data.permissions
setCheckedPermissions()
})
@@ -141,6 +146,7 @@ const getPermissions = async (value: number = 0) => {
}
}
// 设置已选权限
const setCheckedPermissions = () => {
nextTick(() => {
props.hasPermissions.forEach(p => {
@@ -152,6 +158,8 @@ const setCheckedPermissions = () => {
permissionLoadingText.value = '暂无数据'
}
}
// 获取角色信息
const getRoles = () => {
http.get(props.api, { id: props.primary ? props.primary : '' }).then(r => {
roles.value = r.data.data
@@ -163,9 +171,15 @@ const getDepartments = () => {
departments.value = r.data.data
})
}
// 新增默认获取全部权限
if (!props.primary) {
getPermissions()
}
// 页面挂载完成后
onMounted(() => {
getRoles()
getPermissions()
getDepartments()
close(() => emit('close'))
watch(

View File

@@ -63,18 +63,14 @@ trait UserRelations
$permissions = $permissionsModel->get();
} else {
$permissions = Collection::make();
app($this->getRolesModel())->with(['permissions'])->get()
$this->roles()->with('permissions')->get()
->each(function ($role) use (&$permissions) {
$permissions = $permissions->concat($role->permissions);
});
$permissions = $permissions->unique();
}
$this->setAttribute('permissions', $permissions->each(fn ($permission) => $permission->setAttribute('hidden', $permission->isHidden())));
return $this;
}
@@ -103,14 +99,15 @@ trait UserRelations
if ($permission->isAction()) {
[$controller, $action] = explode('@', $permission->permission_mark);
$actions->add(CatchAdmin::getModuleControllerNamespace($permission->module).$controller.'Controller@'.$action);
$actions->add(CatchAdmin::getModuleControllerNamespace($permission->module). ucfirst($controller).'Controller@'.$action);
}
});
// 自定义权限判断
if ($permission) {
[$module, $controller, $action] = explode('@', $permission);
$permission = CatchAdmin::getModuleControllerNamespace($module).$controller.'Controller@'.$action;
$permission = CatchAdmin::getModuleControllerNamespace($module). ucfirst($controller) .'Controller@'.$action;
}
return $actions->contains($permission ?: Route::currentRouteAction());

View File

@@ -73,7 +73,8 @@ class User extends Model implements AuthenticatableContract
protected function DepartmentId(): Attribute
{
return new Attribute(
get: fn($value) => $value ? : null
get: fn($value) => $value ? : null,
set: fn($value) => $value ? : 0
);
}

View File

@@ -8,46 +8,46 @@
"preview": "vite preview"
},
"dependencies": {
"@heroicons/vue": "^2.0.14",
"@tinymce/tinymce-vue": "^5.0.1",
"@vueuse/core": "^9.12.0",
"@heroicons/vue": "^2.0.18",
"@tinymce/tinymce-vue": "^5.1.0",
"@vueuse/core": "^10.1.2",
"autoprefixer": "^10.4.13",
"element-plus": "^2.2.33",
"element-plus": "^2.3.4",
"nprogress": "^0.2.0",
"pinia": "^2.0.32",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.2",
"terser": "^5.16.5",
"pinia": "^2.0.36",
"postcss": "^8.4.23",
"tailwindcss": "^3.3.2",
"terser": "^5.17.3",
"vue": "^3.2.47",
"vue-i18n": "9",
"vue-router": "4.1.6",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@iconify-json/logos": "^1.1.22",
"@rollup/plugin-alias": "^4.0.3",
"@iconify-json/logos": "^1.1.28",
"@rollup/plugin-alias": "^5.0.0",
"@types/mockjs": "^1.0.7",
"@types/node": "^18.14.6",
"@types/node": "^20.1.1",
"@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vitejs/plugin-vue": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^5.59.5",
"@typescript-eslint/parser": "^5.59.5",
"@vitejs/plugin-vue": "^4.2.1",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"axios": "^1.3.4",
"eslint": "^8.35.0",
"axios": "^1.4.0",
"eslint": "^8.40.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-n": "^15.6.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.9.0",
"eslint-plugin-vue": "^9.11.1",
"prettier": "2.8.4",
"sass": "^1.58.0",
"typescript": "^4.9.5",
"sass": "^1.62.1",
"typescript": "^5.0.4",
"unplugin-auto-import": "^0.14.4",
"unplugin-icons": "^0.15.2",
"unplugin-icons": "^0.16.1",
"unplugin-vue-components": "^0.24.0",
"vite": "^4.1.4",
"vite": "^4.3.5",
"vite-plugin-html": "^3.2.0",
"vue-tsc": "^1.2.0"
"vue-tsc": "^1.6.4"
}
}

View File

@@ -1,20 +1,28 @@
<template>
<div :class="`grid ${grid} gap-y-6`">
<div v-for="icon in icons" :key="icon" class="flex justify-center hover:cursor-pointer" @click="selectIcon(icon)">
<div v-if="modelValue === icon">
<div class="flex justify-center w-full text-violet-700"><Icon :name="icon" /></div>
<div class="text-sm text-violet-700">{{ icon }}</div>
</div>
<div class="h-84 pl-2 pr-2">
<div :class="`grid ${grid} gap-y-4 gap-x-4` + ' mt-3 h-72'">
<div v-for="icon in icons" :key="icon" class="flex justify-center hover:cursor-pointer" @click="selectIcon(icon)">
<div v-if="modelValue === icon">
<div class="flex justify-center w-full text-violet-700"><Icon :name="icon" className="w-5 h-5" /></div>
<div class="text-[1px] text-violet-700">{{ icon }}</div>
</div>
<div v-else>
<div class="flex justify-center w-full"><Icon :name="icon" /></div>
<div class="text-sm">{{ icon }}</div>
<div v-else>
<div class="flex justify-center w-full"><Icon :name="icon" className="w-5 h-5" /></div>
<div class="text-[1px]">{{ icon }}</div>
</div>
</div>
</div>
<div class="flex justify-center mt-6">
<el-pagination layout="prev,next" :page-size="limit" :total="total" prev-text="上一页" next-text="下一页" @next-click="handleNext" @prev-click="handlePrev" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
const props = defineProps({
modelValue: {
type: String,
@@ -22,18 +30,38 @@ const props = defineProps({
},
grid: {
type: String,
default: 'grid-cols-5',
default: 'grid-cols-4',
},
})
const emits = defineEmits(['update:modelValue', 'close'])
const limit = ref(16)
const icons = ref([])
const total = ref(0)
function getIcons(page = 1) {
const start = (page - 1) * limit.value
const end = start + limit.value
icons.value = constIcons.slice(start, end)
}
onMounted(() => {
getIcons()
total.value = constIcons.length
})
const handleNext = value => {
getIcons(value)
}
const handlePrev = value => {
getIcons(value)
}
const selectIcon = (icon: string) => {
emits('update:modelValue', icon)
emits('close')
}
// icons
const icons = [
const constIcons = [
'academic-cap',
'adjustments-horizontal',
'adjustments-vertical',

View File

@@ -57,11 +57,7 @@ export function useGetList(path: string, isPaginate: boolean = true) {
// reset
function reset() {
resetPage()
if (isPaginate) {
query.value = Object.assign({ page: page.value, limit: limit.value })
}
query.value = Object.assign(isPaginate ? { page: page.value, limit: limit.value } : {})
getList()
}