release(custom): i

This commit is contained in:
2023-10-10 15:01:00 +08:00
parent a9707c6d94
commit 5b33290de6
78 changed files with 13003 additions and 5230 deletions

View File

@@ -0,0 +1,805 @@
{
"name": "Ant Design Icons",
"total": 789,
"version": "4.3.1",
"license": {
"title": "MIT",
"spdx": "MIT"
},
"samples": ["pushpin-filled", "pie-chart-outlined", "shopping-twotone"],
"height": 16,
"category": "General",
"palette": false,
"id": "ant-design",
"icons": [
"account-book-filled",
"account-book-outlined",
"account-book-twotone",
"aim-outlined",
"alert-filled",
"alert-outlined",
"alert-twotone",
"alibaba-outlined",
"align-center-outlined",
"align-left-outlined",
"align-right-outlined",
"alipay-circle-filled",
"alipay-circle-outlined",
"alipay-outlined",
"alipay-square-filled",
"aliwangwang-filled",
"aliwangwang-outlined",
"aliyun-outlined",
"amazon-circle-filled",
"amazon-outlined",
"amazon-square-filled",
"android-filled",
"android-outlined",
"ant-cloud-outlined",
"ant-design-outlined",
"apartment-outlined",
"api-filled",
"api-outlined",
"api-twotone",
"apple-filled",
"apple-outlined",
"appstore-add-outlined",
"appstore-filled",
"appstore-outlined",
"appstore-twotone",
"area-chart-outlined",
"arrow-down-outlined",
"arrow-left-outlined",
"arrow-right-outlined",
"arrow-up-outlined",
"arrows-alt-outlined",
"audio-filled",
"audio-muted-outlined",
"audio-outlined",
"audio-twotone",
"audit-outlined",
"backward-filled",
"backward-outlined",
"bank-filled",
"bank-outlined",
"bank-twotone",
"bar-chart-outlined",
"barcode-outlined",
"bars-outlined",
"behance-circle-filled",
"behance-outlined",
"behance-square-filled",
"behance-square-outlined",
"bell-filled",
"bell-outlined",
"bell-twotone",
"bg-colors-outlined",
"block-outlined",
"bold-outlined",
"book-filled",
"book-outlined",
"book-twotone",
"border-bottom-outlined",
"border-horizontal-outlined",
"border-inner-outlined",
"border-left-outlined",
"border-outer-outlined",
"border-outlined",
"border-right-outlined",
"border-top-outlined",
"border-verticle-outlined",
"borderless-table-outlined",
"box-plot-filled",
"box-plot-outlined",
"box-plot-twotone",
"branches-outlined",
"bug-filled",
"bug-outlined",
"bug-twotone",
"build-filled",
"build-outlined",
"build-twotone",
"bulb-filled",
"bulb-outlined",
"bulb-twotone",
"calculator-filled",
"calculator-outlined",
"calculator-twotone",
"calendar-filled",
"calendar-outlined",
"calendar-twotone",
"camera-filled",
"camera-outlined",
"camera-twotone",
"car-filled",
"car-outlined",
"car-twotone",
"caret-down-filled",
"caret-down-outlined",
"caret-left-filled",
"caret-left-outlined",
"caret-right-filled",
"caret-right-outlined",
"caret-up-filled",
"caret-up-outlined",
"carry-out-filled",
"carry-out-outlined",
"carry-out-twotone",
"check-circle-filled",
"check-circle-outlined",
"check-circle-twotone",
"check-outlined",
"check-square-filled",
"check-square-outlined",
"check-square-twotone",
"chrome-filled",
"chrome-outlined",
"ci-circle-filled",
"ci-circle-outlined",
"ci-circle-twotone",
"ci-outlined",
"ci-twotone",
"clear-outlined",
"clock-circle-filled",
"clock-circle-outlined",
"clock-circle-twotone",
"close-circle-filled",
"close-circle-outlined",
"close-circle-twotone",
"close-outlined",
"close-square-filled",
"close-square-outlined",
"close-square-twotone",
"cloud-download-outlined",
"cloud-filled",
"cloud-outlined",
"cloud-server-outlined",
"cloud-sync-outlined",
"cloud-twotone",
"cloud-upload-outlined",
"cluster-outlined",
"code-filled",
"code-outlined",
"code-sandbox-circle-filled",
"code-sandbox-outlined",
"code-sandbox-square-filled",
"code-twotone",
"codepen-circle-filled",
"codepen-circle-outlined",
"codepen-outlined",
"codepen-square-filled",
"coffee-outlined",
"column-height-outlined",
"column-width-outlined",
"comment-outlined",
"compass-filled",
"compass-outlined",
"compass-twotone",
"compress-outlined",
"console-sql-outlined",
"contacts-filled",
"contacts-outlined",
"contacts-twotone",
"container-filled",
"container-outlined",
"container-twotone",
"control-filled",
"control-outlined",
"control-twotone",
"copy-filled",
"copy-outlined",
"copy-twotone",
"copyright-circle-filled",
"copyright-circle-outlined",
"copyright-circle-twotone",
"copyright-outlined",
"copyright-twotone",
"credit-card-filled",
"credit-card-outlined",
"credit-card-twotone",
"crown-filled",
"crown-outlined",
"crown-twotone",
"customer-service-filled",
"customer-service-outlined",
"customer-service-twotone",
"dash-outlined",
"dashboard-filled",
"dashboard-outlined",
"dashboard-twotone",
"database-filled",
"database-outlined",
"database-twotone",
"delete-column-outlined",
"delete-filled",
"delete-outlined",
"delete-row-outlined",
"delete-twotone",
"delivered-procedure-outlined",
"deployment-unit-outlined",
"desktop-outlined",
"diff-filled",
"diff-outlined",
"diff-twotone",
"dingding-outlined",
"dingtalk-circle-filled",
"dingtalk-outlined",
"dingtalk-square-filled",
"disconnect-outlined",
"dislike-filled",
"dislike-outlined",
"dislike-twotone",
"dollar-circle-filled",
"dollar-circle-outlined",
"dollar-circle-twotone",
"dollar-outlined",
"dollar-twotone",
"dot-chart-outlined",
"double-left-outlined",
"double-right-outlined",
"down-circle-filled",
"down-circle-outlined",
"down-circle-twotone",
"down-outlined",
"down-square-filled",
"down-square-outlined",
"down-square-twotone",
"download-outlined",
"drag-outlined",
"dribbble-circle-filled",
"dribbble-outlined",
"dribbble-square-filled",
"dribbble-square-outlined",
"dropbox-circle-filled",
"dropbox-outlined",
"dropbox-square-filled",
"edit-filled",
"edit-outlined",
"edit-twotone",
"ellipsis-outlined",
"enter-outlined",
"environment-filled",
"environment-outlined",
"environment-twotone",
"euro-circle-filled",
"euro-circle-outlined",
"euro-circle-twotone",
"euro-outlined",
"euro-twotone",
"exception-outlined",
"exclamation-circle-filled",
"exclamation-circle-outlined",
"exclamation-circle-twotone",
"exclamation-outlined",
"expand-alt-outlined",
"expand-outlined",
"experiment-filled",
"experiment-outlined",
"experiment-twotone",
"export-outlined",
"eye-filled",
"eye-invisible-filled",
"eye-invisible-outlined",
"eye-invisible-twotone",
"eye-outlined",
"eye-twotone",
"facebook-filled",
"facebook-outlined",
"fall-outlined",
"fast-backward-filled",
"fast-backward-outlined",
"fast-forward-filled",
"fast-forward-outlined",
"field-binary-outlined",
"field-number-outlined",
"field-string-outlined",
"field-time-outlined",
"file-add-filled",
"file-add-outlined",
"file-add-twotone",
"file-done-outlined",
"file-excel-filled",
"file-excel-outlined",
"file-excel-twotone",
"file-exclamation-filled",
"file-exclamation-outlined",
"file-exclamation-twotone",
"file-filled",
"file-gif-outlined",
"file-image-filled",
"file-image-outlined",
"file-image-twotone",
"file-jpg-outlined",
"file-markdown-filled",
"file-markdown-outlined",
"file-markdown-twotone",
"file-outlined",
"file-pdf-filled",
"file-pdf-outlined",
"file-pdf-twotone",
"file-ppt-filled",
"file-ppt-outlined",
"file-ppt-twotone",
"file-protect-outlined",
"file-search-outlined",
"file-sync-outlined",
"file-text-filled",
"file-text-outlined",
"file-text-twotone",
"file-twotone",
"file-unknown-filled",
"file-unknown-outlined",
"file-unknown-twotone",
"file-word-filled",
"file-word-outlined",
"file-word-twotone",
"file-zip-filled",
"file-zip-outlined",
"file-zip-twotone",
"filter-filled",
"filter-outlined",
"filter-twotone",
"fire-filled",
"fire-outlined",
"fire-twotone",
"flag-filled",
"flag-outlined",
"flag-twotone",
"folder-add-filled",
"folder-add-outlined",
"folder-add-twotone",
"folder-filled",
"folder-open-filled",
"folder-open-outlined",
"folder-open-twotone",
"folder-outlined",
"folder-twotone",
"folder-view-outlined",
"font-colors-outlined",
"font-size-outlined",
"fork-outlined",
"form-outlined",
"format-painter-filled",
"format-painter-outlined",
"forward-filled",
"forward-outlined",
"frown-filled",
"frown-outlined",
"frown-twotone",
"fullscreen-exit-outlined",
"fullscreen-outlined",
"function-outlined",
"fund-filled",
"fund-outlined",
"fund-projection-screen-outlined",
"fund-twotone",
"fund-view-outlined",
"funnel-plot-filled",
"funnel-plot-outlined",
"funnel-plot-twotone",
"gateway-outlined",
"gif-outlined",
"gift-filled",
"gift-outlined",
"gift-twotone",
"github-filled",
"github-outlined",
"gitlab-filled",
"gitlab-outlined",
"global-outlined",
"gold-filled",
"gold-outlined",
"gold-twotone",
"golden-filled",
"google-circle-filled",
"google-outlined",
"google-plus-circle-filled",
"google-plus-outlined",
"google-plus-square-filled",
"google-square-filled",
"group-outlined",
"hdd-filled",
"hdd-outlined",
"hdd-twotone",
"heart-filled",
"heart-outlined",
"heart-twotone",
"heat-map-outlined",
"highlight-filled",
"highlight-outlined",
"highlight-twotone",
"history-outlined",
"holder-outlined",
"home-filled",
"home-outlined",
"home-twotone",
"hourglass-filled",
"hourglass-outlined",
"hourglass-twotone",
"html5-filled",
"html5-outlined",
"html5-twotone",
"idcard-filled",
"idcard-outlined",
"idcard-twotone",
"ie-circle-filled",
"ie-outlined",
"ie-square-filled",
"import-outlined",
"inbox-outlined",
"info-circle-filled",
"info-circle-outlined",
"info-circle-twotone",
"info-outlined",
"insert-row-above-outlined",
"insert-row-below-outlined",
"insert-row-left-outlined",
"insert-row-right-outlined",
"instagram-filled",
"instagram-outlined",
"insurance-filled",
"insurance-outlined",
"insurance-twotone",
"interaction-filled",
"interaction-outlined",
"interaction-twotone",
"issues-close-outlined",
"italic-outlined",
"key-outlined",
"laptop-outlined",
"layout-filled",
"layout-outlined",
"layout-twotone",
"left-circle-filled",
"left-circle-outlined",
"left-circle-twotone",
"left-outlined",
"left-square-filled",
"left-square-outlined",
"left-square-twotone",
"like-filled",
"like-outlined",
"like-twotone",
"line-chart-outlined",
"line-height-outlined",
"line-outlined",
"link-outlined",
"linkedin-filled",
"linkedin-outlined",
"loading-3-quarters-outlined",
"loading-outlined",
"lock-filled",
"lock-outlined",
"lock-twotone",
"login-outlined",
"logout-outlined",
"mac-command-filled",
"mac-command-outlined",
"mail-filled",
"mail-outlined",
"mail-twotone",
"man-outlined",
"medicine-box-filled",
"medicine-box-outlined",
"medicine-box-twotone",
"medium-circle-filled",
"medium-outlined",
"medium-square-filled",
"medium-workmark-outlined",
"meh-filled",
"meh-outlined",
"meh-twotone",
"menu-fold-outlined",
"menu-outlined",
"menu-unfold-outlined",
"merge-cells-outlined",
"message-filled",
"message-outlined",
"message-twotone",
"minus-circle-filled",
"minus-circle-outlined",
"minus-circle-twotone",
"minus-outlined",
"minus-square-filled",
"minus-square-outlined",
"minus-square-twotone",
"mobile-filled",
"mobile-outlined",
"mobile-twotone",
"money-collect-filled",
"money-collect-outlined",
"money-collect-twotone",
"monitor-outlined",
"more-outlined",
"node-collapse-outlined",
"node-expand-outlined",
"node-index-outlined",
"notification-filled",
"notification-outlined",
"notification-twotone",
"number-outlined",
"one-to-one-outlined",
"ordered-list-outlined",
"paper-clip-outlined",
"partition-outlined",
"pause-circle-filled",
"pause-circle-outlined",
"pause-circle-twotone",
"pause-outlined",
"pay-circle-filled",
"pay-circle-outlined",
"percentage-outlined",
"phone-filled",
"phone-outlined",
"phone-twotone",
"pic-center-outlined",
"pic-left-outlined",
"pic-right-outlined",
"picture-filled",
"picture-outlined",
"picture-twotone",
"pie-chart-filled",
"pie-chart-outlined",
"pie-chart-twotone",
"play-circle-filled",
"play-circle-outlined",
"play-circle-twotone",
"play-square-filled",
"play-square-outlined",
"play-square-twotone",
"plus-circle-filled",
"plus-circle-outlined",
"plus-circle-twotone",
"plus-outlined",
"plus-square-filled",
"plus-square-outlined",
"plus-square-twotone",
"pound-circle-filled",
"pound-circle-outlined",
"pound-circle-twotone",
"pound-outlined",
"poweroff-outlined",
"printer-filled",
"printer-outlined",
"printer-twotone",
"profile-filled",
"profile-outlined",
"profile-twotone",
"project-filled",
"project-outlined",
"project-twotone",
"property-safety-filled",
"property-safety-outlined",
"property-safety-twotone",
"pull-request-outlined",
"pushpin-filled",
"pushpin-outlined",
"pushpin-twotone",
"qq-circle-filled",
"qq-outlined",
"qq-square-filled",
"qrcode-outlined",
"question-circle-filled",
"question-circle-outlined",
"question-circle-twotone",
"question-outlined",
"radar-chart-outlined",
"radius-bottomleft-outlined",
"radius-bottomright-outlined",
"radius-setting-outlined",
"radius-upleft-outlined",
"radius-upright-outlined",
"read-filled",
"read-outlined",
"reconciliation-filled",
"reconciliation-outlined",
"reconciliation-twotone",
"red-envelope-filled",
"red-envelope-outlined",
"red-envelope-twotone",
"reddit-circle-filled",
"reddit-outlined",
"reddit-square-filled",
"redo-outlined",
"reload-outlined",
"rest-filled",
"rest-outlined",
"rest-twotone",
"retweet-outlined",
"right-circle-filled",
"right-circle-outlined",
"right-circle-twotone",
"right-outlined",
"right-square-filled",
"right-square-outlined",
"right-square-twotone",
"rise-outlined",
"robot-filled",
"robot-outlined",
"rocket-filled",
"rocket-outlined",
"rocket-twotone",
"rollback-outlined",
"rotate-left-outlined",
"rotate-right-outlined",
"safety-certificate-filled",
"safety-certificate-outlined",
"safety-certificate-twotone",
"safety-outlined",
"save-filled",
"save-outlined",
"save-twotone",
"scan-outlined",
"schedule-filled",
"schedule-outlined",
"schedule-twotone",
"scissor-outlined",
"search-outlined",
"security-scan-filled",
"security-scan-outlined",
"security-scan-twotone",
"select-outlined",
"send-outlined",
"setting-filled",
"setting-outlined",
"setting-twotone",
"shake-outlined",
"share-alt-outlined",
"shop-filled",
"shop-outlined",
"shop-twotone",
"shopping-cart-outlined",
"shopping-filled",
"shopping-outlined",
"shopping-twotone",
"shrink-outlined",
"signal-filled",
"sisternode-outlined",
"sketch-circle-filled",
"sketch-outlined",
"sketch-square-filled",
"skin-filled",
"skin-outlined",
"skin-twotone",
"skype-filled",
"skype-outlined",
"slack-circle-filled",
"slack-outlined",
"slack-square-filled",
"slack-square-outlined",
"sliders-filled",
"sliders-outlined",
"sliders-twotone",
"small-dash-outlined",
"smile-filled",
"smile-outlined",
"smile-twotone",
"snippets-filled",
"snippets-outlined",
"snippets-twotone",
"solution-outlined",
"sort-ascending-outlined",
"sort-descending-outlined",
"sound-filled",
"sound-outlined",
"sound-twotone",
"split-cells-outlined",
"star-filled",
"star-outlined",
"star-twotone",
"step-backward-filled",
"step-backward-outlined",
"step-forward-filled",
"step-forward-outlined",
"stock-outlined",
"stop-filled",
"stop-outlined",
"stop-twotone",
"strikethrough-outlined",
"subnode-outlined",
"swap-left-outlined",
"swap-outlined",
"swap-right-outlined",
"switcher-filled",
"switcher-outlined",
"switcher-twotone",
"sync-outlined",
"table-outlined",
"tablet-filled",
"tablet-outlined",
"tablet-twotone",
"tag-filled",
"tag-outlined",
"tag-twotone",
"tags-filled",
"tags-outlined",
"tags-twotone",
"taobao-circle-filled",
"taobao-circle-outlined",
"taobao-outlined",
"taobao-square-filled",
"team-outlined",
"thunderbolt-filled",
"thunderbolt-outlined",
"thunderbolt-twotone",
"to-top-outlined",
"tool-filled",
"tool-outlined",
"tool-twotone",
"trademark-circle-filled",
"trademark-circle-outlined",
"trademark-circle-twotone",
"trademark-outlined",
"transaction-outlined",
"translation-outlined",
"trophy-filled",
"trophy-outlined",
"trophy-twotone",
"twitter-circle-filled",
"twitter-outlined",
"twitter-square-filled",
"underline-outlined",
"undo-outlined",
"ungroup-outlined",
"unlock-filled",
"unlock-outlined",
"unlock-twotone",
"unordered-list-outlined",
"up-circle-filled",
"up-circle-outlined",
"up-circle-twotone",
"up-outlined",
"up-square-filled",
"up-square-outlined",
"up-square-twotone",
"upload-outlined",
"usb-filled",
"usb-outlined",
"usb-twotone",
"user-add-outlined",
"user-delete-outlined",
"user-outlined",
"user-switch-outlined",
"usergroup-add-outlined",
"usergroup-delete-outlined",
"verified-outlined",
"vertical-align-bottom-outlined",
"vertical-align-middle-outlined",
"vertical-align-top-outlined",
"vertical-left-outlined",
"vertical-right-outlined",
"video-camera-add-outlined",
"video-camera-filled",
"video-camera-outlined",
"video-camera-twotone",
"wallet-filled",
"wallet-outlined",
"wallet-twotone",
"warning-filled",
"warning-outlined",
"warning-twotone",
"wechat-filled",
"wechat-outlined",
"weibo-circle-filled",
"weibo-circle-outlined",
"weibo-outlined",
"weibo-square-filled",
"weibo-square-outlined",
"whats-app-outlined",
"wifi-outlined",
"windows-filled",
"windows-outlined",
"woman-outlined",
"yahoo-filled",
"yahoo-outlined",
"youtube-filled",
"youtube-outlined",
"yuque-filled",
"yuque-outlined",
"zhihu-circle-filled",
"zhihu-outlined",
"zhihu-square-filled",
"zoom-in-outlined",
"zoom-out-outlined"
]
}

View File

@@ -0,0 +1,431 @@
<template>
<CommonPage show-footer :title="'(非技术人员勿动)'">
<n-button v-perms="['/admin/auth/menu/set']" type="primary" @click="openModal(1)">
添加菜单
</n-button>
<n-data-table
class="mt-5"
:loading="loading"
:columns="columns"
:data="data"
:pagination="false"
:bordered="false"
remote
:row-key="rowKey"
children-key="subMenu"
/>
<!-- 添加菜单 -->
<n-modal v-model:show="showModal">
<n-card
style="width: 500px"
title="添加/编辑菜单"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<!-- {{ model }} -->
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
<n-grid :cols="24" :x-gap="24">
<n-form-item-gi :span="16" label="父级分类:" path="pid">
<n-cascader
v-model:value="model.pid"
placeholder="请选择菜单目录"
expand-trigger="click"
:options="[
{
ID: 0,
name: '顶层菜单',
pid: 0,
},
...data,
]"
check-strategy="all"
show-path
label-field="name"
value-field="ID"
children-field="subMenu"
separator="->"
/>
</n-form-item-gi>
<n-form-item-gi :span="16" label="权限类型:" path="type">
<n-select
v-model:value="model.type"
placeholder="请选择菜单类型"
:options="[
{
label: '目录',
value: 1,
},
{
label: '菜单',
value: 2,
},
{
label: '按钮',
value: 3,
},
]"
/>
</n-form-item-gi>
<n-form-item-gi v-if="model.type !== 3" :span="24" label="菜单图标:" path="icon">
<div>
<n-input-group flex items-center>
<TheIcon :icon="model.icon" :size="30" />
<n-input
v-model:value="model.icon"
placeholder="请选择菜单图标"
:style="{ width: '100%' }"
/>
<n-button type="primary" ghost @click="iconModal = true">+</n-button>
</n-input-group>
</div>
</n-form-item-gi>
<n-form-item-gi v-if="model.type !== 3" :span="10" label="是否开启:" path="status">
<n-switch v-model:value="model.status" :checked-value="1" :unchecked-value="2" />
</n-form-item-gi>
<n-form-item-gi v-if="model.type !== 3" :span="10" label="是否显示:" path="isShow">
<n-switch v-model:value="model.isShow" :checked-value="1" :unchecked-value="2" />
</n-form-item-gi>
<n-form-item-gi :span="16" label="菜单名称:" path="name">
<n-input v-model:value="model.name" placeholder="请填写菜单名称" />
</n-form-item-gi>
<n-form-item-gi
v-if="model.type === 2 || model.type === 1"
:span="16"
label="菜单路径:"
path="route"
>
<n-input v-model:value="model.route" placeholder="请填写菜单路径" />
</n-form-item-gi>
<n-form-item-gi
v-if="model.type === 3 || model.type === 2"
:span="16"
label="权限标识:"
path="api_route"
>
<n-input v-model:value="model.api_route" placeholder="请填写权限标识" />
</n-form-item-gi>
<n-form-item-gi v-if="model.type === 2" :span="16" label="组件路径:" path="components">
<n-input v-model:value="model.components" placeholder="请填写组件路径" />
</n-form-item-gi>
<n-form-item-gi v-if="model.type === 2" :span="16" label="菜单参数:" path="params">
<n-input v-model:value="model.params" placeholder="请填写菜单参数" />
</n-form-item-gi>
<n-form-item-gi :span="16" label="菜单排序:" path="sort">
<n-input-number v-model:value="model.sort" :min="0" placeholder="越低越靠前" />
</n-form-item-gi>
<n-form-item-gi :span="18">
<div m-auto>
<n-button type="primary" @click="handleValidateClick">保存</n-button>
<n-button ml-10 @click="clear">取消</n-button>
</div>
</n-form-item-gi>
</n-grid>
</n-form>
</n-card>
</n-modal>
<!-- 图标 -->
<n-modal v-model:show="iconModal">
<n-card
style="width: 600px"
title="选择菜单图标"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<div h-500 w-full flex flex-wrap overflow-auto>
<div
v-for="(item, index) in antIconList.icons"
:key="index"
@click="clickIcon(`ant-design:${item}`)"
>
<TheIcon :icon="`ant-design:${item}`" :size="40" />
</div>
</div>
</n-card>
</n-modal>
</CommonPage>
</template>
<script setup>
import { h, withDirectives, resolveDirective } from 'vue'
import api from '../api'
import TheIcon from '@/components/icon/TheIcon.vue'
import { NTag, NButton } from 'naive-ui'
import antIconList from './ant-design-meta.json'
const vPerms = resolveDirective('perms')
const loading = ref(false)
const showModal = ref(false)
const iconModal = ref(false)
const rowKey = (row) => {
return row.subMenu || []
}
const columns = ref([
{
title: '菜单名称',
key: 'name',
align: 'center',
},
{
title: '菜单图标',
slot: 'icon',
align: 'center',
render: (row) => {
return [
h(TheIcon, {
icon: row.icon,
size: 20,
}),
]
},
},
{
title: '类型',
slot: 'type',
align: 'center',
render: (row) => {
return [
h(
'span',
{},
{
default: () => (row.type === 1 ? '目录' : row.type === 2 ? '菜单' : '按钮'),
}
),
]
},
},
{
title: '路径',
key: 'route',
align: 'center',
},
{
title: '权限标识',
key: 'api_route',
align: 'center',
},
{
title: '路由参数',
key: 'params',
align: 'center',
},
{
title: '组件路径',
key: 'components',
align: 'center',
},
{
title: '排序',
key: 'sort',
align: 'center',
},
{
title: '是否启用',
solt: 'status',
align: 'center',
render: (row) => {
return [
h(
NTag,
{
type: row.status === 1 ? 'success' : 'warning',
},
{
default: () => (row.status === 1 ? '启用' : '禁用'),
}
),
]
},
},
{
title: '是否显示',
solt: 'status',
align: 'center',
render: (row) => {
return [
h(
NTag,
{
type: row.is_show === 1 ? 'success' : 'warning',
},
{
default: () => (row.is_show === 1 ? '显示' : '隐藏'),
}
),
]
},
},
{
title: '操作',
slot: 'action',
align: 'center',
render: (row) => {
return [
withDirectives(
h(
NButton,
{
text: true,
onClick: () => {
openModal(2, row)
},
},
{
default: () => '编辑',
}
),
[[vPerms, ['/admin/auth/menu/set']]]
),
]
},
},
])
const data = ref([])
onMounted(() => {
getList()
})
const getList = async () => {
loading.value = true
const res = await api.getMenuList()
data.value = res.data.data || []
loading.value = false
}
const model = ref({
id: null,
pid: null,
type: null,
icon: '',
status: 1,
isShow: 1,
name: '',
route: '',
params: '',
sort: 0,
components: '',
api_route: '',
})
const formRef = ref(null)
const rules = {
pid: {
required: true,
type: 'number',
message: '请选择菜单目录',
trigger: 'change',
},
type: {
required: true,
type: 'number',
message: '请选择菜单类型',
trigger: 'change',
},
name: {
required: true,
type: 'string',
message: '请填写菜单名称',
trigger: 'blur',
},
route: {
required: true,
type: 'string',
message: '请填写菜单路径',
trigger: 'blur',
},
components: {
required: true,
message: '请填写组件路径',
trigger: 'blur',
},
}
const openModal = (type, row = {}) => {
// get_dir_list()
if (type === 2) {
model.value = {
id: row.ID,
type: row.type,
icon: row.icon,
status: row.status,
isShow: row.isShow,
name: row.name,
route: row.route,
params: row.params,
sort: row.sort,
pid: row.pid,
components: row.components,
api_route: row.api_route,
}
}
showModal.value = true
}
const clickIcon = (icon) => {
model.value.icon = icon
iconModal.value = false
}
const handleValidateClick = () => {
formRef.value?.validate(async (errors) => {
if (!errors) {
try {
const dataObj = {
ID: model.value.id || '',
Icon: model.value.icon,
Type: model.value.type,
Status: model.value.status,
IsShow: model.value.isShow,
Name: model.value.name,
Route: model.value.route,
Params: model.value.params,
Sort: model.value.sort,
Pid: model.value.pid || '',
Components: model.value.components || '',
ApiRoute: model.value.api_route || '',
}
const res = await api.addMenu(dataObj)
$message.success(res.msg)
clear()
} catch (error) {
$message.error(error.msg)
throw error
}
}
})
}
const clear = () => {
formRef.value?.restoreValidation()
model.value = {
pid: null,
type: null,
icon: '',
status: 1,
isShow: 1,
name: '',
route: '',
params: '',
components: '',
sort: 0,
}
showModal.value = false
getList()
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,221 @@
<template>
<CommonPage show-footer :title="$route.title">
<n-button v-perms="['/admin/auth/set']" type="primary" @click="openModal(1)">添加角色</n-button>
<n-data-table
class="mt-5"
:loading="loading"
:columns="columns"
:data="data"
:pagination="pagination"
:bordered="false"
remote
/>
<n-modal v-model:show="showModal">
<n-card
style="width: 600px"
title="添加/编辑角色"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<!-- {{ model.AuthId }} -->
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
<n-grid :cols="24" :x-gap="24">
<n-form-item-gi :span="16" label="角色名称:" path="Name">
<n-input v-model:value="model.Name" placeholder="请输入角色名称" />
</n-form-item-gi>
<n-form-item-gi :span="16" label="角色权限:" path="AuthId">
<n-tree
:data="menus"
:default-checked-keys="model.AuthId"
label-field="name"
value-field="ID"
key-field="ID"
children-field="subMenu"
checkable
cascade
virtual-scroll
@update:checked-keys="updateCheckedKeys"
@update:indeterminate-keys="updateIndeterminateKeys"
/>
</n-form-item-gi>
<n-form-item-gi :span="16" label="角色状态:" path="Status">
<n-switch v-model:value="model.Status" :unchecked-value="2" :checked-value="1" />
</n-form-item-gi>
<n-form-item-gi :span="18">
<div m-auto>
<n-button type="primary" @click="handleValidateClick">保存</n-button>
<n-button ml-10 @click="clear">取消</n-button>
</div>
</n-form-item-gi>
</n-grid>
</n-form>
</n-card>
</n-modal>
</CommonPage>
</template>
<script setup>
import api from '../api'
import { NTag, NButton } from 'naive-ui'
import { h, withDirectives, resolveDirective } from 'vue'
const vPerms = resolveDirective('perms')
const loading = ref(false)
const columns = ref([
{
title: '角色名称',
key: 'name',
align: 'center',
},
{
title: '角色状态',
slot: 'status',
align: 'center',
render: (row) => {
return h(
NTag,
{
type: row.status === 1 ? 'success' : 'warning',
},
{
default: () => (row.status === 1 ? '启用' : '禁用'),
}
)
},
},
{
title: '操作',
slot: 'action',
align: 'center',
render: (row) => {
return [
withDirectives(
h(
NButton,
{
text: true,
onClick: () => {
openModal(2, row)
},
},
{
default: () => '编辑',
}
),
[[vPerms, ['/admin/auth/set']]]
),
]
},
},
])
const data = ref([])
const showModal = ref(false)
const model = ref({
Name: '',
AuthId: [],
Status: 2,
})
const rules = {
Name: {
required: true,
message: '请输入角色名称',
trigger: 'blur',
},
AuthId: {
required: true,
type: 'array',
message: '请选择角色权限',
trigger: ['blur', 'input'],
},
}
const pagination = ref({
page: 1,
pageSize: 10,
itemCount: 0,
onChange: (page) => {
pagination.value.page = page
getList()
},
})
onMounted(() => {
getList()
get_menu_list()
})
const getList = async () => {
loading.value = true
try {
const res = await api.getRoleList({
pageNum: 1,
pageSize: 10,
})
data.value = res.data.data || []
pagination.value.itemCount = res.data.total
} catch (error) {
$message.error(error.msg)
throw error
}
loading.value = false
}
const menus = ref([])
const get_menu_list = async () => {
const res = await api.getMenuList()
menus.value = res.data.data
}
const openModal = (type, row = {}) => {
if (type === 2) {
model.value = {
ID: row.ID,
Name: row.name,
AuthId: JSON.parse(row.auth_id),
Status: row.status,
}
}
showModal.value = true
}
const clear = () => {
formRef.value?.restoreValidation()
model.value = {
Name: '',
AuthId: [],
Status: 2,
}
showModal.value = false
getList()
}
const formRef = ref(null)
const handleValidateClick = () => {
formRef.value?.validate(async (valid) => {
if (!valid) {
const res = await api.addRole(model.value)
$message.success(res.msg)
clear()
}
})
}
const updateCheckedKeys = (value) => {
model.value.AuthId = value
}
const updateIndeterminateKeys = (value) => {
model.value.AuthId = [...model.value.AuthId, ...value]
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,297 @@
<template>
<CommonPage show-footer :title="$route.title">
<n-button v-perms="['/admin/manage/set']" type="primary" @click="openModal(1)">
添加管理员
</n-button>
<n-data-table
class="mt-5"
:loading="loading"
:columns="columns"
:data="data"
:pagination="pagination"
:bordered="false"
remote
/>
<n-modal v-model:show="showModal">
<n-card
style="width: 600px"
title="添加/编辑角色"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<n-form ref="formRef" :model="model" :rules="rules" label-placement="left">
<n-grid :cols="24" :x-gap="24">
<n-form-item-gi :span="16" label="名称:" path="Name">
<n-input v-model:value="model.Name" placeholder="请输入管理员名称" />
</n-form-item-gi>
<n-form-item-gi :span="16" label="账号:" path="Phone">
<n-input v-model:value="model.Phone" placeholder="请输入管理员账号(手机号码)" />
</n-form-item-gi>
<n-form-item-gi v-if="nowType === 1" :span="16" label="密码:" path="Password">
<n-input v-model:value="model.Password" placeholder="请输入管理员密码" />
</n-form-item-gi>
<n-form-item-gi v-else :span="16" label="新密码:">
<n-input v-model:value="model.Password" placeholder="不修改请留空" />
</n-form-item-gi>
<n-form-item-gi :span="16" label="角色:" path="AuthId">
<n-select
v-model:value="model.AuthId"
multiple
:options="roles"
label-field="name"
value-field="ID"
/>
</n-form-item-gi>
<n-form-item-gi :span="16" label="角色状态:" path="Status">
<n-switch v-model:value="model.Status" :unchecked-value="2" :checked-value="1" />
</n-form-item-gi>
<n-form-item-gi :span="18">
<div m-auto>
<n-button type="primary" @click="handleValidateClick">保存</n-button>
<n-button ml-10 @click="clear">取消</n-button>
</div>
</n-form-item-gi>
</n-grid>
</n-form>
</n-card>
</n-modal>
</CommonPage>
</template>
<script setup>
import { h, withDirectives, resolveDirective } from 'vue'
import api from '../api'
import { NTag, NButton } from 'naive-ui'
const vPerms = resolveDirective('perms')
const loading = ref(false)
const columns = ref([
{
title: '管理员名称',
key: 'name',
align: 'center',
},
{
title: '账号',
key: 'phone',
align: 'center',
},
{
title: '角色',
slot: 'auth_id',
align: 'center',
render: (row) => {
const nowRow = { ...row, auth_id: JSON.parse(row.auth_id) }
const roleName = []
roles.value.forEach((item) => {
nowRow.auth_id.forEach((itm) => {
if (item.ID === itm) {
roleName.push(item.name)
}
})
})
return h(
'span',
{},
{
default: () => roleName.join(' | '),
}
)
},
},
{
title: '角色状态',
slot: 'status',
align: 'center',
render: (row) => {
return h(
NTag,
{
type: row.status === 1 ? 'success' : 'warning',
},
{
default: () => (row.status === 1 ? '启用' : '禁用'),
}
)
},
},
{
title: '操作',
slot: 'action',
align: 'center',
render: (row) => {
return [
withDirectives(
h(
NButton,
{
text: true,
onClick: () => {
openModal(2, row)
},
},
{
default: () => '编辑',
}
),
[[vPerms, ['/admin/manage/set']]]
),
withDirectives(
h(
NButton,
{
class: 'ml-10',
type: 'error',
text: true,
onClick: () => {
delVerifyUser(row)
},
},
{
default: () => '删除',
}
),
[[vPerms, ['/admin/manage/delete']]]
),
]
},
},
])
const data = ref([])
const showModal = ref(false)
const model = ref({
Name: '',
AuthId: null,
Phone: '',
Password: '',
Status: 2,
})
const rules = {
Name: {
required: true,
message: '请输入角色名称',
trigger: 'blur',
},
AuthId: {
required: true,
type: 'array',
message: '请选择分配权限',
trigger: ['blur'],
},
Phone: {
required: true,
message: '请输入管理员账号(手机号码)',
trigger: 'blur',
},
Password: {
required: true,
message: '请输入管理员密码',
trigger: 'blur',
},
}
const pagination = ref({
page: 1,
pageSize: 10,
itemCount: 0,
onChange: (page) => {
pagination.value.page = page
getList()
},
})
onMounted(() => {
getList()
get_role_list()
})
const getList = async () => {
loading.value = true
try {
const res = await api.getAdminList({
pageNum: 1,
pageSize: 10,
})
data.value = res.data.data || []
pagination.value.itemCount = res.data.total
} catch (error) {
$message.error(error.msg)
throw error
}
loading.value = false
}
const roles = ref([])
const get_role_list = async () => {
const res = await api.getRoleList()
roles.value = res.data.data || []
}
const nowType = ref(1)
const openModal = (type, row = {}) => {
nowType.value = type
get_role_list()
if (type === 2) {
model.value = {
ID: row.ID,
Name: row.name,
AuthId: JSON.parse(row.auth_id),
Status: row.status,
Phone: row.phone,
}
}
showModal.value = true
}
const clear = () => {
formRef.value?.restoreValidation()
model.value = {
Name: '',
AuthId: null,
Phone: '',
Password: '',
Status: 2,
}
showModal.value = false
getList()
}
const formRef = ref(null)
const handleValidateClick = () => {
formRef.value?.validate(async (valid) => {
if (!valid) {
const res = await api.addAdmin(model.value)
$message.success(res.msg)
clear()
}
})
}
const delVerifyUser = async (row) => {
$dialog.error({
title: '提示',
content: '删除无法撤销,请谨慎!',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: async () => {
const res = await api.delVerifyUser({
uid: row.uid,
})
$message.success(res.msg)
getList()
},
})
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,24 @@
import { request } from '@/utils'
export default {
// 获取权限列表
getMenuList: () => request.post('/auth/menu'),
// 获取菜单目录
getDirList: (data) => request.post('/auth/menu/parent', data),
// 添加/修改菜单
addMenu: (data) => request.post('/auth/menu/set', data),
// 获取角色列表
getRoleList: (data) => request.post('/auth', data),
// 添加/修改角色
addRole: (data) => request.post('/auth/set', data),
// 获取管理员列表
getAdminList: (data) => request.post('/manage', data),
// 添加/修改管理员
addAdmin: (data) => request.post('/manage/set', data),
// 删除核销人员
delVerifyUser: (data) => request.post('/manage/delete', data),
}

View File

@@ -1,12 +1,15 @@
<template>
<CommonPage show-footer :title="$route.title">
<n-button type="primary" @click="handleAdd(1)">新增幻灯片</n-button>
<n-button v-perms="['/admin/rotation/edit']" type="primary" @click="handleAdd(1)">
新增幻灯片
</n-button>
<n-data-table
:loading="loading"
:columns="columns"
:data="data"
:pagination="pagination"
:bordered="false"
remote
/>
<n-modal v-model:show="showModal">
<n-card
@@ -44,10 +47,11 @@
</template>
<script setup>
import { onMounted, h } from 'vue'
import { onMounted, h, withDirectives, resolveDirective } from 'vue'
import api from './api'
import { NButton } from 'naive-ui'
import { NButton, NImage } from 'naive-ui'
import Upload from '@/components/Upload.vue'
const vPerms = resolveDirective('perms')
const loading = ref(false)
@@ -62,12 +66,9 @@ const columns = ref([
align: 'center',
slot: 'url',
render(row) {
return h('img', {
return h(NImage, {
width: '50',
src: row.url[0]?.url || '',
style: {
width: '30px',
height: '30px',
},
})
},
},
@@ -85,17 +86,20 @@ const columns = ref([
slot: 'action',
render(row) {
return [
h(
NButton,
{
type: 'primary',
size: 'small',
onClick: () => {
formValue.value = row
handleAdd(2)
withDirectives(
h(
NButton,
{
type: 'primary',
size: 'small',
onClick: () => {
formValue.value = row
handleAdd(2)
},
},
},
() => '编辑'
() => '编辑'
),
[[vPerms, ['/admin/rotation/edit']]]
),
]
},

View File

@@ -5,6 +5,11 @@ export default {
path: '/sys',
component: Layout,
redirect: '/sys_banner',
meta: {
title: '系统管理',
icon: 'mdi:account-multiple',
order: 10,
},
children: [
{
name: 'Sysbanner',
@@ -26,5 +31,47 @@ export default {
order: 10,
},
},
{
name: 'SysAcc',
path: 'sys_acc',
redirect: '/sys_acc_user',
meta: {
title: '权限管理',
icon: 'mdi:account-multiple',
order: 10,
},
children: [
{
name: 'SysAccUser',
path: 'sys_acc_user',
component: () => import('./acc/acc_user/index.vue'),
meta: {
title: '账号管理',
icon: 'mdi:account-multiple',
order: 10,
},
},
{
name: 'SysAccRole',
path: 'sys_acc_role',
component: () => import('./acc/acc_role/index.vue'),
meta: {
title: '角色管理',
icon: 'mdi:account-multiple',
order: 10,
},
},
{
name: 'SysAccMenu',
path: 'sys_acc_menu',
component: () => import('./acc/acc_menu/index.vue'),
meta: {
title: '菜单权限',
icon: 'mdi:account-multiple',
order: 10,
},
},
],
},
],
}

View File

@@ -15,7 +15,14 @@
/>
</n-form-item>
<n-form-item>
<n-button attr-type="button" @click="handleValidateClick">保存</n-button>
<n-button
v-perms="['/admin/userConfig/edit']"
attr-type="button"
type="primary"
@click="handleValidateClick"
>
保存
</n-button>
</n-form-item>
</n-form>
</CommonPage>