В нескольких недавних проектах руководители просили нас сделать функцию управления разрешениями для проекта.Из-за тестирования проектов у меня есть некоторые идеи по добавлению функции управления разрешениями проекта, что также является шагом в моем понимании. Шаги улучшаются (конечно, из-за отсутствия видения и опыта будет много недостатков в глазах большого парня, добро пожаловать, чтобы дать указатели, если вам не хватает 0 ^ 0)
Здание города-побратима, привлекающее огневую мощь
Мое понимание
На мой взгляд, основная цель управления полномочиями заключается в следующем: клиентская часть сначала реализует проект с полными функциями, а затем устанавливает условие оценки доступа для внешнего пакета модуля, который необходимо контролировать, и это условие оценки является полномочиями. параметр управления функции, управление полномочиями Это управляемая обработка этого параметра управления.
Начальная операция
В первом проекте управления разрешениями я так глубоко не думал, и реализация была реализована только до разрешений на уровне страницы, и многоролевые платформы не влияли друг на друга, и функции были независимы, так что это было Относительно легко сделать. Нет специального модуля управления разрешениями, но статический файл конфигурации считывается через серверную часть, а затем информация о разрешениях страницы возвращается во внешний интерфейс через интерфейс. Внешний интерфейс передает этот список разрешений. параметр в возвращаемом значении успешного входа и интерфейс для получения личной информации.(ps. Почему вы хотите вернуть этот параметр в этих двух интерфейсах? Это потому что....лень! Мне лень заново открывать интерфейс. После успешного входа в систему будет получен список разрешений, и эта информация будет храниться в vuex.Каждый раз, когда страница обновляется, будет интерфейс для запроса личной информации и обновления информации о разрешениях в vuex, поэтому нет необходимости открыть отдельный запрос интерфейса)
Затем проект делится на конец управления и конец пользователя.Хотя код написан в одном и том же проекте, два конца используют разные входы в систему, и страницы перехода после успеха также разные.Каждый конец имеет свою домашнюю страницу. , а разрешения этой домашней страницы не нужно контролировать, они должны быть там постоянно, по таким требованиям это узнать очень просто, а именно:
- Согласовано с серверной частью для управления списком разрешений. удобно получить значение при оценке разрешения)
- Добавлять во время определения маршрута каждой доступной страницыmetaсвойства и установить
requireAuth: true(В то же время вы также можете передать некоторую другую необходимую вам информацию о конфигурации, доступ к которой можно получить на странице)
{
path: '/home',
name: 'home',
component: home,
meta: {
requireAuth: true
}
}
- Боковая панель меню (или вверху, в противном случае это меню) написана в интерфейсе, и каждый конечный узел должен иметь соответствующую страницу, по которой можно щелкнуть, чтобы перейти, поэтому при рендеринге меню необходимо судить о соответствующем страница для каждого узла меню Есть ли разрешение, если нет листового узла, он не будет отображаться
- Добавьте слушателя к функции ловушки маршрутизатора beforeEach, потому что функция ловушки будет запускаться каждый раз, когда страница инициирует изменение маршрута, а затем определите, должна ли страница, на которую вы хотите перейти (параметр для), определять, является ли разрешение требованиемAuth поле в мете, если нужно, то Просто прочитайте список разрешений от vuex, а потом рассудите, есть ли разрешение у страницы, на которую нужно перейти, если нет, то прыгайте на неавторизованную страницу (если в проекте нет этой страницы, это не будет прыгать), в противном случае он будет нормально переключать страницы.
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// 表示要前往的页面需要权限
// 添加自己的判断条件
if (xxx) {
next({path: '/xxx'})
} else {
// 跳转无权限页面
next({path: '/forbidden'})
}
} else {
next() // 确保一定要调用 next()
}
})
Кроме того, вы можете обратиться к официальной документации оэлемент маршрутизацииобъяснение
Достигается такое простое управление разрешениями, не правда ли, очень низко?
Резюмируем преимущества и недостатки:
Преимущества: простая реализация кода
недостаток:
- Детализация управления разрешениями может быть только на уровне страницы
- Передняя и задняя части не полностью разделены, и имя недавно добавленной страницы разрешений необходимо вручную синхронизировать с задней частью во время разработки.
- Неудобно поддерживать временные требования, и нужно вручную изменять файл конфигурации прав
снова фехтовать
Позже есть еще один проект, который нужно контролировать полномочиями.На этот раз лидер должен контролировать полномочия до уровня кнопок.Поскольку это небольшой проект (также нет независимого модуля управления полномочиями), он не займет много времени, поэтому я не стал углубляться Я просто подумал об этом и подумал, что разрешения на уровне кнопок не простые, просто нужно расширить первый метод.
Я изменил эти места:
- Каждое поле в списке разрешений по-прежнему является страницей, соответствующей маршрутизатору, но значение больше не логического типа, а расширено до типа объекта.Например, страница списка пользователей UserList имеет кнопку добавления, кнопку удаления, кнопку редактирования. кнопку и кнопку просмотра сведений.Четыре функции, то выражение в списке разрешений:
permissionList = {
UserList: {
show: true, // 页面查看权限(默认拥有获取列表数据权限)
add: true, // 创建用户权限
edit: true, // 编辑用户权限
delete: true, // 删除用户权限
detail: true, // 查看用户详情权限
},
pageB: {},
......
}
- Решение в router.beforeEach должно принять поле show, чтобы определить, есть ли у вас разрешение на страницу, на которую вы хотите перейти.
- После входа на целевую страницу, когда страница инициализируется, ей необходимо получить разрешения соответствующих функциональных кнопок из разрешенияList.UserList.Например, создание пользовательской кнопки для рендеринга зависит от того, имеет ли значение permissionList.UserList.add значение true для определить, отображается ли кнопка.
Изменений не так много, и это легко понять.Основной принцип заключается в том, чтобы определить все видимые и работающие кнопки на странице, а затем получить информацию о разрешениях во время рендеринга для управления кнопками, но есть проблема, что управление слишком самостоятельна. , например учетная запись имеет права доступа к странице со списком пользователей, и кнопка создать на странице тоже имеет права, но нажатие на страницу создания пользователя не имеет прав доступа, в этот раз на самом деле больше смущает, потому что четко отображается, что есть кнопка создания, но нажата и перейти на неавторизованную страницу, взаимодействие очень недружественное
Резюмируем преимущества и недостатки:
Преимущества: Ха-ха-ха, код по-прежнему прост в реализации. . А разрешения каждой страницы независимы и не мешают друг другу
Недостатки: ремонтопригодность не очень высока, конфигурация сложна и требует тщательного рассмотрения, и необходимо учитывать взаимосвязь между разрешениями.Легко иметь кнопки, но нет разрешений на страницы.
Последняя глава
Лей лей, грядет главное событие, кстати выложу простенькую, которую написал на GitHubдемонстрация управления разрешениями, вкуснее смотреть со статьей (данный проект - управление разрешениями, которое я добавил на демо-основе прошлой статьи о табличном компоненте. При добавлении разрешений мне кажется все более и более удобным для инкапсуляции компонентов)
Во-первых, у этого проекта есть свой независимый модуль разрешений, в котором вы можете создать все разрешения, которые хотите.Во-вторых, хотя этот проект разделен на три больших модуля, функции не сильно связаны с ролями, и не соответствуют Платформа Роль, или нет строгого понятия роли, когда платформе необходимо создать новую учетную запись (платформа в основном зарабатывает деньги, продавая учетные записи для предоставления услуг), вам необходимо выполнять следующие действия.
- Все контролируемые разрешения платформы предустановлены
- Создаем роль (строго говоря, не роль, а ту, которой назначены разрешения... не знаю, как это описать, назовем ее ролью)
- Назначение разрешений «ролям» («роль» может иметь разрешения для нескольких платформ)
- Завести аккаунт
- Назначение ролей учетным записям (у одной учетной записи может быть несколько «ролей»)
- Продам аккаунт!
Нет никаких сложностей в назначении разрешений и ролей, поэтому сложность этого проекта заключается в контроле разрешений.Как сделать хорошую работу в гибком управлении разрешениями является ключевым элементом для снижения затрат на обслуживание на более позднем этапе, поэтому шаг пошагово:
1. Разделение платформы и определение маршрутизации
В соответствии с требованиями проект имеет три платформы, примерно соответствующие стороне ученика, стороне управления учителем и стороне общего управления.Согласно вышеуказанным требованиям, учетная запись может иметь доступ и права работы на нескольких платформах, но интерфейс стиль каждой платформы отличается.Различия, невозможно разместить их на одном дисплее страницы в соответствии с решением властей.Три платформы "разделены" на дисплее, поэтому будет функция переключения модулей.
Я устанавливаю разрешение на доступ к модулю самостоятельно как отдельное разрешение, поэтому очень просто временно удалить разрешение платформы из учетной записи во время назначения разрешения, достаточно просто установить разрешение платформы на False, но на самом деле эта конструкция не хорошо (тут только лениться, всем не учиться),Наличие у модуля разрешения на доступ должно определяться наличием у него разрешения на доступ к содержимому модуля, а не индивидуальными разрешениями., в оформлении разрешений не должно быть жесткой родительско-дочерней взаимосвязи, чтобы при изменении модуля в последующих проектах логика разрешений не рухнула (не спрашивайте меня, откуда я знаю, знаете ли вы, что этот проект проектировался разделить на две платформы в начале?Я слишком много плачу...)
Здесь я вставлю предложение, лично я рекомендую максимально использовать его при выполнении маршрутных переходовименованный маршрут, не спрашивайте почему, это тоже слезы... Иначе baseUrl более позднего проекта вдруг изменится, и роутинг джампы во всех модулях придется менять, так вы понимаете 0^0
Сказав это, я добавлю еще одно предложение: если кто-то хочет попросить о переходе на одну страницу, можно использовать название «прыжок» для прямого перехода.this.$router.push({ name: 'balabala' }), но что, если требуется открыть страницу в новом окне? vue-router не поддерживает его, его можно использовать толькоwindow.open('/aa/bb', '_blank')Как ты делаешь это? Позвольте мне рассказать вам небольшую хитрость: здесь используется router.resolve, вы можете написать:
let routerUrl = this.$router.resolve({ name: 'balabala' })
window.open(routerUrl.href, '_blank')
Возвращаясь к теме, на уровне маршрутизации, помимо общедоступных страниц (404, 500, страницы входа и т. д.), есть три маршрута модуля. Маршруты каждого модуля и страницы задаются согласно настройкам.Планируется определить в дочерних элементах этих трех баз, а затем я разработал спецификацию именования маршрутов, то есть все имена маршрутов именуются с использованием символов подчеркивания.имя_платформы_модуль_содержание, страница, непосредственно соответствующая пункту меню, то есть непосредственно начальная страница входа модуляимя_платформы_модуль, требует, чтобы другие front-end разработчики называли имя маршрута в соответствии с этой спецификацией, иначе возникнут проблемы при выделении меню, о которых речь пойдет позже.
2. Реализация меню и навигации
Так как студенческая сторона имеет меньше функций, дизайн не проектировал для нее боковое меню, а сосредоточил функции на панели навигации, в то время как два других терминала управления имеют все более сложные функции, и панель навигации не может быть размещена, поэтому используется боковое меню.Меню в проекте используется element-ui, поэтому панель навигации и боковое меню используют el-menu, а модификация пользовательского стиля производится в el-menu.Для удобства обслуживания и последующего добавления новых столбцы, я буду использовать строку меню Абстракция рендеринга — это рендеринг данных вместо прямой записи каждого подменю в файл боковой панели, то есть я создал новый файл menuConfig в каталоге config проекта, а затем файл определяет три списка меню внутри, соответствующие трем модулям и выбрасывая их, общие правила, которые я определил, следующие:
export const adminPlatformMenu = [
{
name: 'admin_main', // 菜单项的index
desc: '首页', // 菜单项展示的内容
icon: 'balabala...' // 菜单项的图标(如果需要的话)
}, {
name: 'admin_account', // 这一项有子菜单,所以这项index并不需要进行页面定向,其实可以随意写,但是是必填项
desc: '账号管理',
icon: 'balabala...',
children: [
{
name: 'admin_user',
desc: '用户管理'
}, {
name: 'admin_department',
desc: '部门管理'
}, {
name: 'admin_role',
desc: '角色管理'
}, {
name: 'admin_auth',
desc: '权限管理'
}
]
}, {
name: 'admin_resource', // 通样这项可以随意写,但是必填
desc: '资源管理',
icon: 'balabala...',
children: [
{
name: 'admin_tool',
desc: '工具库管理'
}, {
name: 'admin_knowledge',
desc: '知识库管理',
children: [
{
name: 'admin_loophole', // 三级菜单
desc: '漏洞库管理'
}, {
name: 'admin_plan',
desc: '应急预案库管理'
}
]
}
]
}
]
Затем укажите его в файле ввода и сгенерируйте желаемое дерево меню, прокручивая данные (мне это не нужно делать).Вот несколько моментов, на которые следует обратить внимание:
Во-первых, полный список меню получается в файле menuConfig, но мы не хотим отображать их все, поэтому нам нужно сначала получить список разрешений, а затем методом обхода отфильтровать авторизованный список меню. написано следующее:
// 接收两个入参,分别是菜单列表和权限列表
export const toFilterHavePermissionMenu = function (menuList = [], authList= {}) {
let newMenu = []
menuList.forEach(item => {
if (item.hasOwnProperty('children')) {
let returnArr = toFilterHavePermissionMenu(item.children, authList)
returnArr.length > 0 && newMenu.push({ ...item, children: returnArr })
} else authList[item.name] && newMenu.push(item)
})
return newMenu
}
Во-вторых, пункты меню показывают скрытые проблемы в соответствии с разрешениями.Например, есть меню под названием комплексное управление, а затем в комплексном управлении есть подменю, такие как управление объявлениями, управление учетными записями, управление журналом и т. д., и есть управление отделом, управление пользователями, управление ролями, управление полномочиями и другие подменю - это как раз такое трехуровневое меню.Для меню комплексного управления и управления учетными записями нужно ли создавать ему разрешение на управление? Как я сказал выше,Наличие у модуля разрешения на доступ должно определяться наличием у него разрешения на доступ к содержимому модуля, а не индивидуальными разрешениями., поэтому при циклическом просмотре авторизованного списка меню для создания дерева меню вам нужно только оценить, равно ли количество подменю с правами доступа, то есть значение children.length равно 0.
Затем, поскольку el-menu должен иметь индекс атрибута, определение индекса должно соответствовать route.name страницы, на которую нужно перейти, нажав на текущее меню, и тогда меню не должно использовать режим маршрутизатора, потому что наш индекс не использовать маршрут.путь - имя_маршрута.Если используется режим маршрутизатора, страница не будет найдена.Здесь я определяю метод перехода в обратном вызове щелчка.
@select="handleSelect"
handleSelect (key, keyPath) {
this.$router.push({ name: key })
}
Затем вы столкнетесь с проблемой при написании других целевых страниц перехода без меню.Например, поскольку имя страницы управления пользователями совпадает с индексом панели навигации, пункт меню выделяется, но создание страницы пользователя также необходимо выделить пункт меню пользователя Управление, но он не был выделен из-за другого названия Поэтому я ранее говорил, что я сформулировал набор спецификаций для именования имен маршрутизации, и страница должна быть названа в соответствии с этот набор спецификаций, чтобы решить эту проблему, а затем мы изменим метод выделения по умолчанию следующим образом:
defaultActive () {
let currentName = this.$route.currentName
let nameArr = currentName.split('_')
if (nameArr.length > 2) return nameArr[0] + '_' + nameArr[1]
else return currentName
}
После отображения меню будет обнаружена проблема, поскольку все модули контролируются разрешениями, поэтому, когда домашняя страница по умолчанию не имеет разрешений, куда пользователь переходит после входа в систему? Таким образом, переход после успешного входа в систему должен быть не жестко запрограммирован, а получен динамически, поэтому я написал метод перенаправления маршрутизации, который можно увидеть в демо.
// 接收一个参数:经过筛选后有权限的菜单列表
export const toFindNextRedirectRouter = function (hasPermissionMenu = []) {
if (hasPermissionMenu.length > 0) {
for (let item of hasPermissionMenu) {
if (item.hasOwnProperty('children')) return toFindNextRedirectRouter(item.children)
else return item
}
}
}
Это автоматически перенаправит вас на первую авторизованную страницу меню.
3. Страница и разделение разрешений внутри страницы
Разделение разрешений является наиболее интуитивно понятным разрешением на уровне страницы, независимо от того, щелкаете ли вы по содержимому страницы, чтобы перейти к маршруту обычного процесса, или вручную меняете маршрут для перехода, определение разрешения очень четкое -> соответствие один к одному с маршрутом, а это Что должны включать разрешения? Это просто доступ к странице? Страница со списком пользователей, если я сделаю функцию получения списка пользователей отдельным разрешением, если у посетителя нет разрешения на получение списка, будет ли это пустой страницей при входе?
Второе — разрешения «кнопочного уровня», которые многие хотят сделать Решение, описанное в предыдущем случае, очень жесткое, но на самом деле
- Мы действительно делаем разрешения кнопки?
- Что такое разрешения на уровне кнопок? Кнопка «Показать» отображается или на нее можно нажать? Или разрешения, которые включают ряд непосредственно связанных действий, которые необходимо выполнить после нажатия кнопки?
- Что делать, если вы хотите контролировать разрешения выбранного элемента фильтра?
- Точно так же внутренний интерфейс также имеет контроль разрешений.Смущает ли это, если внешний интерфейс страницы имеет разрешение, а внутренний интерфейс не возвращает разрешения?
После волны душевной пытки чувствуете, что что-то не так? Таким образом, использование разрешений «на уровне кнопок» не очень уместно, я думаю, что использованиеуровень функционального модуляБолее уместно описать разрешения, так что же такое разделение разрешений «на уровне функционального модуля»?
Таким образом, я опишу такую страницу:
- Пункт меню владеет подменю управления пользователями
- Щелкните подменю управления пользователями, чтобы перейти на страницу управления пользователями.
- Основная часть страницы управления пользователями представляет собой таблицу с разбивкой на страницы, в которой отображается информация о пользователе. Вверху есть кнопки «Создать пользователя» и «Пакетное удаление». Элементы фильтра выбираются отделом. В каждой строке таблицы есть элементы операций для один пользователь: изменить, удалить
- Нажмите кнопку «Создать пользователя», чтобы перейти к созданию страницы пользователя.Основной частью страницы создания пользователя является форма, которая требует от пользователя ввода информации, включая имя (ввод), отдел (выбрать) и т. д., и имеет кнопку отправки. кнопка и кнопка отмены
- Нажмите кнопку «Отправить», чтобы отправить информацию формы, в случае успеха вернитесь на страницу управления пользователями, нажмите «Отмена», чтобы напрямую вернуться на страницу управления пользователями.
- Нажмите кнопку встроенного редактирования, чтобы перейти на страницу редактирования с идентификатором пользователя, получить информацию о пользователе через идентификатор пользователя и инициализировать форму, а другие функции такие же, как и функция создания.
- Нажмите кнопку удаления в строке, чтобы запросить подтверждение удаления пользователя.После подтверждения выполните операцию удаления, а затем обновите список.
- Нажмите кнопку пакетного удаления, и всплывающее окно предложит вам подтвердить, следует ли удалять пользователей пакетами.После подтверждения выполните операцию пакетного удаления, а затем обновите список.
- Выберите отдел фильтрации, затем выполните список с параметрами фильтра и обновите список.
На этой странице соответствующие внутренние интерфейсы: получить интерфейс со списком пользователей, получить интерфейс выбора отдела с раскрывающимся списком данных, получить интерфейс с информацией о пользователе на основе идентификатора пользователя, создать пользовательский интерфейс, отредактировать пользовательский интерфейс, удалить интерфейс с информацией о пользователе, удалить пользователя. информационный интерфейс в пакетах (Вы также можете использовать интерфейс с удалением, см. свой собственный дизайн бэкэнда)
Как вести разрешительный контроль, чтобы быть более разумным и «очеловеченным»?
- Нажмите на пункт меню «Управление пользователями» в зависимости от того, есть ли у него
admin_userРазрешения (см. определение меню разрешений выше) при переходе на страницу управления пользователями, неуместно отображать пустое пространство после перехода на страницу управления пользователями, поэтому ему должно быть предоставлено разрешение на вызов интерфейса списка пользователей, и такой же бэкэнд нужно дать пользователю Права доступа интерфейса списка, чтобы инициализация не была неудобной, поэтомуadmin_userРазрешения должны включать: разрешение на доступ к странице + разрешение на вызов интерфейса списка пользователей + разрешение на доступ к интерфейсу списка пользователей (бэкенд) - В списке есть данные и его нужно отфильтровать.Поскольку он отфильтрован, необходимо получить данные выпадающего списка отдела, поэтому функция фильтрации
admin_user_department_filterРазрешения должны включать: отображается ли поле фильтра + разрешение на вызов интерфейса для получения выпадающего списка отделов + разрешение на вызов интерфейса для получения списка пользователей (список необходимо обновить после фильтрации) + разрешение на получить интерфейс выпадающего списка отделов (разрешение) + интерфейс получить список пользователей Полномочия доступа (бэкэнд) (пс. Эти полномочия на самом деле не обязательно должны быть независимыми, объединены вadmin_userОн самый подходящий, но ради демки вынужден быть самостоятельным ха-ха) - Точно так же разрешения на создание пользовательских функций
admin_user_addНеобходимо включить: отображать ли кнопку «Создать» + права доступа для создания страниц + раскрывающиеся данные отдела для получения прав вызова интерфейса + раскрывающиеся данные отдела для получения прав доступа интерфейса (бэкэнд) + отправлять права вызова для создания пользовательских интерфейсов + отправить права доступа для создания пользовательских интерфейсов (задняя часть) - Изменить разрешение
admin_user_editЭто почти то же самое, что создать дополнительное разрешение на вызов для получения интерфейса информации о пользователе + разрешение на доступ для получения интерфейса с информацией о пользователе (бэкэнд) (как управлять разрешениями кнопок, отображаемых в соответствии с циклом в этой строке? Сотрудничайте с этим один я написалкомпонент формыЛучше есть, демка про разрешения тоже делается на этой таблице, а адрес проекта демки будет позже) - удалить разрешение
admin_user_deleteОн должен включать: отображается ли кнопка удаления + отображается ли всплывающее окно удаления + удаляется разрешение на вызов пользовательского информационного интерфейса + удаляется разрешение на доступ к пользовательскому информационному интерфейсу (бэкэнд) - пакетное удаление
admin_user_multidelПодобно удалению, может быть дополнительная функция отображения флажка (но этот флажок часто контролируется на основе данных внутреннего списка возврата, отображать или нет)
Таким образом, по согласованию с back-end разработчиками, мы подразделяем функциональные модули, и тогда каждому модулю соответствует поле управления полномочиями, а поле управления полномочиями соответствует одной или нескольким функциям front-end и back-end интерфейсам. , Это намного понятнее, а также очень понятно при назначении разрешений.
После завершения разделения модуля и определения полей разрешений следующим шагом является создание и назначение разрешений.Как упоминалось ранее, между разрешениями не должно быть иерархической связи.Родителю не обязательно определять отдельные разрешения.В противном случае, когда модуль изменится, будет Если родитель и дочерний элемент вдруг окажутся на одном уровне, управление разрешениями легко рухнет.Если вы только посмотрите, есть ли у него дочерние разрешения, чтобы определить, должно ли отображаться родительское меню или нет, это проблемы не возникнет.Поэтому при создании разрешения не может быть родительской и дочерней связи,возьмемсгладить, но будет проблема, что при распределении разрешений нет иерархического отображения разрешений, людям очень сложно проверить распределение, что очень противоречиво
Поскольку руководитель проекта, которым я сейчас занимаюсь, часто меняет модули или сильно меняется, поэтому я все равно не могу иметь родительско-дочернее управление между своими разрешениями, поэтому мне интересно, возможно ли создать новый модуль и создать новую таблицу в базы данных.Используется для установки и хранения разрешений междутекущая визуальная иерархияДа, но это используется только для хранения структуры данных и последующего отображения ее для отображения. На самом деле это не связывает разрешения. Между данными о разрешениях в таблице разрешений в базе данных по-прежнему нет связи, поэтому, если разрешения изменяются, модуля разрешений и проекта не будет При назначении разрешений вы просто чувствуете, что модули не соответствуют реальным проектам, но это не влияет на назначение разрешений.При необходимости вам нужно только заново создать иерархическую взаимосвязь модули, определяющие «взаимоотношения» разрешений ( ps. Я просто думаю об этой идее, и я на самом деле не работал над ней, но я думаю, что осуществимость должна быть в порядке. Мой текущий график проекта очень плотный, и лидер не дает мне времени сделать новый модуль, и нет будущего.Разработчики терминала сотрудничали, поэтому он умер преждевременно.В настоящее время он также написан насмерть.Визуальная иерархия разрешенийJSON, используемый для рендеринга отображения для пользователя)
Вы можете двигаться вперед и сравнить код, чтобы понять это управление разрешениями.Поскольку нет фоновой службы, я поместил конфигурацию разрешений в статический файл anthConfig.js, а также удобно изменить проверку напрямую.Конфигурация может вступить в силу на странице
На этом все.Все коды этой статьи можно найти в моей.Из-за ограниченности опыта работы может быть много мест не до конца учтенных или даже неверных.Также надеюсь,что большие ребята,которые это увидят,могут сделать больше поправок Я буду серьезно пересматривать, просто соус, прощай