master
parent
c9d02287e4
commit
0e18fd3c33
|
|
@ -1,13 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import Utils from '@/common/utils'
|
import Utils from '@/common/utils'
|
||||||
import { elIcons } from '@/common/element/element.ts'
|
import { elIcons } from '@/common/element/element.ts'
|
||||||
|
import Colls from '@/common/utils/colls.ts'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue?: string | string[] | null,
|
modelValue?: string | string[] | null,
|
||||||
multiple?: boolean,
|
multiple?: boolean,
|
||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
displayField: string,
|
displayField: string,
|
||||||
columns: {
|
columns?: {
|
||||||
label: string
|
label: string
|
||||||
prop: string
|
prop: string
|
||||||
}[]
|
}[]
|
||||||
|
|
@ -63,7 +64,10 @@ function onOpen() {
|
||||||
paging()
|
paging()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(onOpen)
|
||||||
|
|
||||||
function onClose() {
|
function onClose() {
|
||||||
|
searchForm.$reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClear() {
|
function onClear() {
|
||||||
|
|
@ -131,11 +135,13 @@ const displayData = computed(() => {
|
||||||
if (props.multiple) {
|
if (props.multiple) {
|
||||||
return `已选 ${selectRows.length} 条`
|
return `已选 ${selectRows.length} 条`
|
||||||
}
|
}
|
||||||
return tableDataList.value
|
let data = tableDataList.value
|
||||||
.filter(it => selectRows.includes(it.id))
|
.filter(it => selectRows.includes(it.id))
|
||||||
.map(it => ((it as Record<string, any>) [props.displayField] as any) ?? '')
|
.map(it => ((it as Record<string, any>) [props.displayField] as any) ?? '')
|
||||||
.join(' ')
|
if (Colls.isEmpty(data)) {
|
||||||
|
data = selectRows as string[]
|
||||||
|
}
|
||||||
|
return data.join('')
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -145,13 +151,19 @@ const displayData = computed(() => {
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@visible-change="visibleChangeHandler">
|
@visible-change="visibleChangeHandler">
|
||||||
<ElInput :model-value="displayData" :placeholder="placeholder" readonly>
|
<template #default>
|
||||||
<template #suffix>
|
<div>
|
||||||
<ElIcon class="clear-btn" @click.stop="onClear">
|
<slot :displayData="displayData" name="displayArea">
|
||||||
<ElIconCircleClose/>
|
<ElInput :model-value="displayData" :placeholder="placeholder" readonly>
|
||||||
</ElIcon>
|
<template #suffix>
|
||||||
</template>
|
<ElIcon class="clear-btn" @click.stop="onClear">
|
||||||
</ElInput>
|
<ElIconCircleClose/>
|
||||||
|
</ElIcon>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<div class="drop-table-content">
|
<div class="drop-table-content">
|
||||||
<ElForm inline @submit.prevent="paging">
|
<ElForm inline @submit.prevent="paging">
|
||||||
|
|
@ -187,11 +199,13 @@ const displayData = computed(() => {
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="#" type="index"/>
|
<ElTableColumn label="#" type="index"/>
|
||||||
<ElTableColumn
|
<slot name="columns">
|
||||||
v-for="(item, i) in columns"
|
<ElTableColumn
|
||||||
:key="'a-drop-table-'+i"
|
v-for="(item, i) in columns"
|
||||||
:label="item.label"
|
:key="'a-drop-table-'+i"
|
||||||
:prop="item.prop"/>
|
:label="item.label"
|
||||||
|
:prop="item.prop"/>
|
||||||
|
</slot>
|
||||||
</ElTable>
|
</ElTable>
|
||||||
<ElDivider class="drop-table-content-divider"/>
|
<ElDivider class="drop-table-content-divider"/>
|
||||||
<ElPagination
|
<ElPagination
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import ADropTable from '@/components/a-drop-table/ADropTable.vue'
|
||||||
|
import {
|
||||||
|
type IconName,
|
||||||
|
icons,
|
||||||
|
} from '@/components/a-icon/iconfont.ts'
|
||||||
|
import AIcon from '@/components/a-icon/AIcon.vue'
|
||||||
|
import Strings from '@/common/utils/strings.ts'
|
||||||
|
|
||||||
|
const model = defineModel<string | undefined | null>()
|
||||||
|
const dropTableLoader = (param: { keywords: string } & G.PageParam) => {
|
||||||
|
const dataList = icons.glyphs
|
||||||
|
.filter(it => it.name.toLowerCase().includes(param.keywords.toLowerCase()) || it.font_class.toLowerCase().includes(param.keywords.toLowerCase()))
|
||||||
|
.sort((a, b) => a.unicode_decimal - b.unicode_decimal)
|
||||||
|
return Promise.resolve({
|
||||||
|
current: param.current!,
|
||||||
|
size: param.size,
|
||||||
|
pages: Math.ceil(dataList.length / param.size!),
|
||||||
|
total: dataList.length,
|
||||||
|
records: dataList
|
||||||
|
.filter((_, i) => {
|
||||||
|
return i >= (param.current! - 1) * param.size! && i < param.current! * param.size!
|
||||||
|
})
|
||||||
|
.map(it => ({
|
||||||
|
id: it.font_class,
|
||||||
|
...it,
|
||||||
|
})),
|
||||||
|
} as G.PageResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ADropTable v-model="model"
|
||||||
|
:loader="dropTableLoader"
|
||||||
|
display-field="font_class">
|
||||||
|
<template #displayArea="{displayData}">
|
||||||
|
<div v-if=" Strings.isBlank(displayData)" class="display-area">请选择</div>
|
||||||
|
<AIcon v-else :name="displayData as IconName" class="display-area"/>
|
||||||
|
</template>
|
||||||
|
<template #columns>
|
||||||
|
<ElTableColumn label="图标" prop="font_class">
|
||||||
|
<template #default="{row}">
|
||||||
|
<AIcon :name="row.font_class as IconName"/>
|
||||||
|
<span style="margin-left: 10px;display: inline-block">{{ row.font_class }}</span>
|
||||||
|
</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="名称" prop="name"/>
|
||||||
|
</template>
|
||||||
|
</ADropTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.display-area {
|
||||||
|
cursor pointer
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* 项目名称 再昇云 */
|
font-family: "iconfont"; /* 项目名称 再昇云 */
|
||||||
src: url('@/components/a-icon/iconfont.woff2?t=1771989909326') format('woff2'),
|
src: url('@/components/a-icon/iconfont.woff2?t=1772264126793') format('woff2'),
|
||||||
url('@/components/a-icon/iconfont.woff?t=1771989909326') format('woff'),
|
url('@/components/a-icon/iconfont.woff?t=1772264126793') format('woff'),
|
||||||
url('@/components/a-icon/iconfont.ttf?t=1771989909326') format('truetype');
|
url('@/components/a-icon/iconfont.ttf?t=1772264126793') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
|
@ -13,6 +13,38 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-yulan:before {
|
||||||
|
content: "\e668";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-putongzhihang:before {
|
||||||
|
content: "\e663";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-zhihangjilu:before {
|
||||||
|
content: "\e892";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xitongguanli1:before {
|
||||||
|
content: "\e6ae";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-API:before {
|
||||||
|
content: "\e740";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-bianma:before {
|
||||||
|
content: "\e772";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-caidan:before {
|
||||||
|
content: "\e662";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-gongnengquanxian:before {
|
||||||
|
content: "\e661";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-zhongzhimima:before {
|
.icon-zhongzhimima:before {
|
||||||
content: "\e660";
|
content: "\e660";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,62 @@
|
||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "7450656",
|
||||||
|
"name": "预览",
|
||||||
|
"font_class": "yulan",
|
||||||
|
"unicode": "e668",
|
||||||
|
"unicode_decimal": 58984
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "11493961",
|
||||||
|
"name": "普通执行",
|
||||||
|
"font_class": "putongzhihang",
|
||||||
|
"unicode": "e663",
|
||||||
|
"unicode_decimal": 58979
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "44782561",
|
||||||
|
"name": "执行记录",
|
||||||
|
"font_class": "zhihangjilu",
|
||||||
|
"unicode": "e892",
|
||||||
|
"unicode_decimal": 59538
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "12884221",
|
||||||
|
"name": "系统管理",
|
||||||
|
"font_class": "xitongguanli1",
|
||||||
|
"unicode": "e6ae",
|
||||||
|
"unicode_decimal": 59054
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3351180",
|
||||||
|
"name": "API",
|
||||||
|
"font_class": "API",
|
||||||
|
"unicode": "e740",
|
||||||
|
"unicode_decimal": 59200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "19105727",
|
||||||
|
"name": "编码",
|
||||||
|
"font_class": "bianma",
|
||||||
|
"unicode": "e772",
|
||||||
|
"unicode_decimal": 59250
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7155218",
|
||||||
|
"name": "菜单",
|
||||||
|
"font_class": "caidan",
|
||||||
|
"unicode": "e662",
|
||||||
|
"unicode_decimal": 58978
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "12820163",
|
||||||
|
"name": "功能权限",
|
||||||
|
"font_class": "gongnengquanxian",
|
||||||
|
"unicode": "e661",
|
||||||
|
"unicode_decimal": 58977
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "524416",
|
"icon_id": "524416",
|
||||||
"name": "重置密码",
|
"name": "重置密码",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,62 @@ export const icons = {
|
||||||
'css_prefix_text': 'icon-',
|
'css_prefix_text': 'icon-',
|
||||||
'description': '',
|
'description': '',
|
||||||
'glyphs': [
|
'glyphs': [
|
||||||
|
{
|
||||||
|
'icon_id': '7450656',
|
||||||
|
'name': '预览',
|
||||||
|
'font_class': 'yulan',
|
||||||
|
'unicode': 'e668',
|
||||||
|
'unicode_decimal': 58984,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '11493961',
|
||||||
|
'name': '普通执行',
|
||||||
|
'font_class': 'putongzhihang',
|
||||||
|
'unicode': 'e663',
|
||||||
|
'unicode_decimal': 58979,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '44782561',
|
||||||
|
'name': '执行记录',
|
||||||
|
'font_class': 'zhihangjilu',
|
||||||
|
'unicode': 'e892',
|
||||||
|
'unicode_decimal': 59538,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '12884221',
|
||||||
|
'name': '系统管理',
|
||||||
|
'font_class': 'xitongguanli1',
|
||||||
|
'unicode': 'e6ae',
|
||||||
|
'unicode_decimal': 59054,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '3351180',
|
||||||
|
'name': 'API',
|
||||||
|
'font_class': 'API',
|
||||||
|
'unicode': 'e740',
|
||||||
|
'unicode_decimal': 59200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '19105727',
|
||||||
|
'name': '编码',
|
||||||
|
'font_class': 'bianma',
|
||||||
|
'unicode': 'e772',
|
||||||
|
'unicode_decimal': 59250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '7155218',
|
||||||
|
'name': '菜单',
|
||||||
|
'font_class': 'caidan',
|
||||||
|
'unicode': 'e662',
|
||||||
|
'unicode_decimal': 58978,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'icon_id': '12820163',
|
||||||
|
'name': '功能权限',
|
||||||
|
'font_class': 'gongnengquanxian',
|
||||||
|
'unicode': 'e661',
|
||||||
|
'unicode_decimal': 58977,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'icon_id': '524416',
|
'icon_id': '524416',
|
||||||
'name': '重置密码',
|
'name': '重置密码',
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -102,6 +102,7 @@ interface FormPropsType<P, T extends DefaultRow> {
|
||||||
* @param param 查询条件
|
* @param param 查询条件
|
||||||
*/
|
*/
|
||||||
paging: (param: P) => Promise<R<G.PageResult<T>>>
|
paging: (param: P) => Promise<R<G.PageResult<T>>>
|
||||||
|
list?: (param: P) => Promise<R<T[]>>
|
||||||
/**
|
/**
|
||||||
* 导出函数
|
* 导出函数
|
||||||
* @param param 查询条件
|
* @param param 查询条件
|
||||||
|
|
@ -329,9 +330,19 @@ const component = defineComponent(
|
||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
} else if (props.searchForm.list != null) {
|
||||||
|
props.searchForm.list(formData.$clone() as P)
|
||||||
|
.then(res => {
|
||||||
|
const records = res.data ?? ([] as T[])
|
||||||
|
tableData.$reset(records)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expose({doSearch})
|
expose({doSearch, tableData})
|
||||||
const showHighFormHandle = () => {
|
const showHighFormHandle = () => {
|
||||||
showHighForm.value = !showHighForm.value
|
showHighForm.value = !showHighForm.value
|
||||||
formData.$reset()
|
formData.$reset()
|
||||||
|
|
@ -634,7 +645,7 @@ const component = defineComponent(
|
||||||
}
|
}
|
||||||
</ElTable>, [ [ ElLoading.directive, loading.value ] ])
|
</ElTable>, [ [ ElLoading.directive, loading.value ] ])
|
||||||
}
|
}
|
||||||
<ElPagination
|
{props.searchForm.paging != null ? <ElPagination
|
||||||
current-page={(formData as G.PageParam).current}
|
current-page={(formData as G.PageParam).current}
|
||||||
page-size={(formData as G.PageParam).size}
|
page-size={(formData as G.PageParam).size}
|
||||||
onUpdate:current-page={(val) => (formData as G.PageParam).current = val}
|
onUpdate:current-page={(val) => (formData as G.PageParam).current = val}
|
||||||
|
|
@ -645,7 +656,7 @@ const component = defineComponent(
|
||||||
total={totalCount.value}
|
total={totalCount.value}
|
||||||
background={true}
|
background={true}
|
||||||
layout="total, prev, pager, next, sizes, jumper"
|
layout="total, prev, pager, next, sizes, jumper"
|
||||||
onChange={doSearch}/>
|
onChange={doSearch}/> : <></>}
|
||||||
{
|
{
|
||||||
slots?.default?.()
|
slots?.default?.()
|
||||||
}
|
}
|
||||||
|
|
@ -658,8 +669,9 @@ const component = defineComponent(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
export interface ATablePageInstance extends InstanceType<typeof component> {
|
export interface ATablePageInstance<T extends DefaultRow = DefaultRow> extends InstanceType<typeof component> {
|
||||||
doSearch: () => void
|
doSearch: () => void
|
||||||
|
tableData: T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default component
|
export default component
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ declare module 'vue' {
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElIconArrowRight: typeof import('@element-plus/icons-vue')['ArrowRight']
|
||||||
ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
|
ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
|
||||||
ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
|
ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
|
||||||
ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
|
ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
|
||||||
|
|
@ -91,6 +92,7 @@ declare global {
|
||||||
const ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
const ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
const ElHeader: typeof import('element-plus/es')['ElHeader']
|
const ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
const ElIcon: typeof import('element-plus/es')['ElIcon']
|
const ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
const ElIconArrowRight: typeof import('@element-plus/icons-vue')['ArrowRight']
|
||||||
const ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
|
const ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
|
||||||
const ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
|
const ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
|
||||||
const ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
|
const ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<ElInput v-model="formData.categoryName" placeholder="分类名称"/>
|
<ElInput v-model="formData.categoryName" placeholder="分类名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="排序" prop="sort">
|
<ElFormItem label="排序" prop="sort">
|
||||||
<ElInputNumber v-model="formData.sort" :min="0" placeholder="排序"/>
|
<ElInputNumber v-model="formData.sort" :min="0" controls-position="right" placeholder="排序"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="备注" prop="memo">
|
<ElFormItem label="备注" prop="memo">
|
||||||
<ElInput v-model="formData.memo" placeholder="备注"/>
|
<ElInput v-model="formData.memo" placeholder="备注"/>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,6 @@ const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
|
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
|
||||||
const status = ref<'add' | 'modify'>('add')
|
const status = ref<'add' | 'modify'>('add')
|
||||||
const formPanelProps = buildFormPanelProps<GoodsTypes.GoodsForm>({
|
const formPanelProps = buildFormPanelProps<GoodsTypes.GoodsForm>({
|
||||||
// title: status.value === 'add' ? '新建产品' : '修改产品',
|
|
||||||
detailsLoader(id?: string) {
|
detailsLoader(id?: string) {
|
||||||
if (Strings.isBlank(id)) {
|
if (Strings.isBlank(id)) {
|
||||||
status.value = 'add'
|
status.value = 'add'
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:left-tools="leftTools"
|
<template #simpleFormItem="formData">
|
||||||
:paging="paging">
|
<ElFormItem>
|
||||||
<template #searchFormItem="{ searchForm }">
|
|
||||||
<ElFormItem label="端点地址">
|
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.endpointPath"
|
v-model="formData.endpointPath"
|
||||||
placeholder="端点地址"/>
|
placeholder="端点地址"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -18,128 +16,75 @@
|
||||||
<ElTableColumn label="访问模式" prop="accessModelTxt"/>
|
<ElTableColumn label="访问模式" prop="accessModelTxt"/>
|
||||||
<ElTableColumn label="备注" prop="memo"/>
|
<ElTableColumn label="备注" prop="memo"/>
|
||||||
</template>
|
</template>
|
||||||
<EndpointForm ref="endpointForm" @edit-succ="research"/>
|
<EndpointForm ref="endpointForm" :research="research"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import EndpointApi from '@/pages/sys/endpoint/endpoint-api.ts'
|
import EndpointApi from '@/pages/sys/endpoint/endpoint-api.ts'
|
||||||
import EndpointForm from '@/pages/sys/endpoint/EndpointForm.vue'
|
import EndpointForm from '@/pages/sys/endpoint/EndpointForm.vue'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
const endpointFormIns = useTemplateRef<InstanceType<typeof EndpointForm>>('endpointForm')
|
const endpointFormIns = useTemplateRef<InstanceType<typeof EndpointForm>>('endpointForm')
|
||||||
|
|
||||||
function research() {
|
const tablePageProps = buildTablePageProps<EndpointTypes.SearchEndpointParam, EndpointTypes.SearchEndpointResult>({
|
||||||
formPageIns.value?.doSearch()
|
pageLayout: {
|
||||||
}
|
enableHighForm: false,
|
||||||
|
},
|
||||||
const leftTools: ToolType[] = [
|
searchForm: {
|
||||||
{
|
paging: EndpointApi.paging,
|
||||||
icon: 'Plus',
|
},
|
||||||
label: '新建',
|
toolBar: {
|
||||||
action() {
|
leftTools: [
|
||||||
endpointFormIns.value?.open()
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
endpointFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '编辑',
|
||||||
|
icon: 'Edit',
|
||||||
|
type: 'success',
|
||||||
|
action({row}) {
|
||||||
|
endpointFormIns.value?.open(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'Delete',
|
||||||
|
loading: false,
|
||||||
|
type: 'danger',
|
||||||
|
tooltip: '删除',
|
||||||
|
confirm: {
|
||||||
|
title: '是否删除当前数据',
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
return EndpointApi.del([ row.id! ])
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
|
||||||
const actionColumn = reactive<ActionColumnType<EndpointTypes.SearchEndpointResult>>({
|
|
||||||
tableActions: [
|
|
||||||
{
|
|
||||||
tooltip: '编辑',
|
|
||||||
icon: 'Edit',
|
|
||||||
type: 'success',
|
|
||||||
action({row}) {
|
|
||||||
endpointFormIns.value?.open(row)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'Delete',
|
|
||||||
loading: false,
|
|
||||||
type: 'danger',
|
|
||||||
tooltip: '删除',
|
|
||||||
confirm: {
|
|
||||||
title: '是否删除当前数据',
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
return EndpointApi.del([ row.id! ])
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function research() {
|
||||||
function paging(param: EndpointTypes.SearchEndpointParam) {
|
tablePageIns.value?.doSearch()
|
||||||
return EndpointApi.paging(param)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.table-list {
|
|
||||||
flex 1;
|
|
||||||
margin 0 0 20px 0
|
|
||||||
width 100%
|
|
||||||
|
|
||||||
:deep(.table-header) {
|
|
||||||
color #454C59
|
|
||||||
|
|
||||||
th {
|
|
||||||
background-color #EDF1F7
|
|
||||||
font-weight 500
|
|
||||||
position relative
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
display flex
|
|
||||||
gap 5px
|
|
||||||
align-items center
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-child) > div::before {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 1px;
|
|
||||||
width: 1px;
|
|
||||||
background-color: #D3D7DE;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
content: "";
|
|
||||||
height 50%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.table-cell) {
|
|
||||||
color #2F3540
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn {
|
|
||||||
width 100%
|
|
||||||
display flex
|
|
||||||
flex-wrap wrap
|
|
||||||
|
|
||||||
& > button {
|
|
||||||
margin 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tool-bar {
|
|
||||||
display flex
|
|
||||||
justify-content space-between
|
|
||||||
margin 0 0 20px 0
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination {
|
|
||||||
justify-content: end;
|
|
||||||
margin: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,163 +1,139 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog
|
<AFormPanel
|
||||||
v-model="showDialog"
|
ref="formPanel"
|
||||||
:close-on-click-modal="false"
|
v-bind="formPanelProps">
|
||||||
destroy-on-close
|
<template #default="formData">
|
||||||
width="fit-content"
|
<div class="form-items">
|
||||||
@close="dialogCloseHandler">
|
<ElFormItem label="请求方式" prop="requestMethod">
|
||||||
<ElForm :model="formData"
|
<ElSelect
|
||||||
ref="endpointForm"
|
v-model="formData.requestMethod"
|
||||||
:rules="rules"
|
placeholder="请求方式">
|
||||||
class="form-panel"
|
<ElOption label="GET 请求" value="GET"/>
|
||||||
>
|
<ElOption label="POST 请求" value="POST"/>
|
||||||
|
<ElOption label="PUT 请求" value="PUT"/>
|
||||||
<ElFormItem label="请求方式" prop="requestMethod">
|
<ElOption label="DELETE 请求" value="DELETE"/>
|
||||||
<ElSelect
|
</ElSelect>
|
||||||
v-model="formData.requestMethod"
|
</ElFormItem>
|
||||||
|
<ElFormItem label="路由前缀" prop="routingPath">
|
||||||
placeholder="请求方式">
|
<ElInput
|
||||||
<ElOption label="GET 请求" value="GET"/>
|
v-model="formData.routingPath"
|
||||||
<ElOption label="POST 请求" value="POST"/>
|
placeholder="以 / 开头 或 为空"/>
|
||||||
<ElOption label="PUT 请求" value="PUT"/>
|
</ElFormItem>
|
||||||
<ElOption label="DELETE 请求" value="DELETE"/>
|
<ElFormItem label="端点地址" prop="endpointPath">
|
||||||
</ElSelect>
|
<ElInput
|
||||||
</ElFormItem>
|
v-model="formData.endpointPath"
|
||||||
<ElFormItem label="路由前缀" prop="routingPath">
|
placeholder="以 / 开头"/>
|
||||||
<ElInput
|
</ElFormItem>
|
||||||
v-model="formData.routingPath"
|
<ElFormItem label="访问模式" prop="accessModel">
|
||||||
|
<ElSelect
|
||||||
placeholder="以 / 开头 或 为空"/>
|
v-model="formData.accessModel"
|
||||||
</ElFormItem>
|
placeholder="访问模式">
|
||||||
<ElFormItem label="端点地址" prop="endpointPath">
|
<ElOption label="允许匿名访问" value="Anonymous"/>
|
||||||
<ElInput
|
<ElOption label="允许已登录用户访问" value="Logined"/>
|
||||||
v-model="formData.endpointPath"
|
<ElOption label="仅拥有权限的用户访问" value="Authenticated"/>
|
||||||
|
<ElOption label="禁止访问" value="Forbidden"/>
|
||||||
placeholder="以 / 开头"/>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="访问模式" prop="accessModel">
|
<ElFormItem label="备注" prop="memo">
|
||||||
<ElSelect
|
<ElInput
|
||||||
v-model="formData.accessModel"
|
v-model="formData.memo"
|
||||||
|
placeholder="备注"/>
|
||||||
placeholder="访问模式">
|
</ElFormItem>
|
||||||
<ElOption label="允许匿名访问" value="Anonymous"/>
|
</div>
|
||||||
<ElOption label="允许已登录用户访问" value="Logined"/>
|
|
||||||
<ElOption label="仅拥有权限的用户访问" value="Authenticated"/>
|
|
||||||
<ElOption label="禁止访问" value="Forbidden"/>
|
|
||||||
</ElSelect>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="备注" prop="memo">
|
|
||||||
<ElInput
|
|
||||||
v-model="formData.memo"
|
|
||||||
|
|
||||||
placeholder="备注"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
<template #footer>
|
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</AFormPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import EndpointApi from '@/pages/sys/endpoint/endpoint-api.ts'
|
import EndpointApi from '@/pages/sys/endpoint/endpoint-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import FormUtil from '@/common/utils/formUtil.ts'
|
|
||||||
import {
|
|
||||||
ElMessage,
|
|
||||||
type FormInstance,
|
|
||||||
type FormRules,
|
|
||||||
} from 'element-plus'
|
|
||||||
import type { InternalRuleItem } from 'async-validator/dist-types/interface'
|
import type { InternalRuleItem } from 'async-validator/dist-types/interface'
|
||||||
|
import AFormPanel, {
|
||||||
|
type AFormPanelInstance,
|
||||||
|
buildFormPanelProps,
|
||||||
|
} from '@/components/a-form-panel/AFormPanel.tsx'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const props = withDefaults(defineProps<{
|
||||||
const showDialog = ref(false)
|
research?: () => void
|
||||||
const submiting = ref(false)
|
}>(), {
|
||||||
const status = ref<'add' | 'view' | 'modify'>('add')
|
research: () => {
|
||||||
|
},
|
||||||
const endpointFormIns = useTemplateRef<FormInstance>('endpointForm')
|
})
|
||||||
|
const status = ref<'add' | 'modify'>('add')
|
||||||
const formData = ref<EndpointTypes.SearchEndpointResult>({})
|
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
const rules = reactive<FormRules<EndpointTypes.SearchEndpointResult>>({
|
const formPanelProps = buildFormPanelProps<GoodsTypes.GoodsForm>({
|
||||||
requestMethod: [ {required: true, message: '请选择请求方式', trigger: 'blur'} ],
|
detailsLoader(id?: string) {
|
||||||
routingPath: [ {
|
if (Strings.isBlank(id)) {
|
||||||
validator(_: InternalRuleItem, value: string, callback: (error?: string | Error) => void) {
|
status.value = 'add'
|
||||||
if (!Strings.isEmpty(value)) {
|
return Promise.resolve()
|
||||||
if (!value.startsWith('/')) {
|
} else {
|
||||||
callback('必须以“/”开头')
|
status.value = 'modify'
|
||||||
|
return EndpointApi.detail(id!)
|
||||||
|
.then((res) => {
|
||||||
|
return res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doSubmit(data) {
|
||||||
|
if (status.value === 'add') {
|
||||||
|
return EndpointApi.add(data)
|
||||||
|
.then(props.research)
|
||||||
|
} else {
|
||||||
|
return EndpointApi.modify(data)
|
||||||
|
.then(props.research)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
requestMethod: [ {required: true, message: '请选择请求方式', trigger: 'blur'} ],
|
||||||
|
routingPath: [ {
|
||||||
|
validator(_: InternalRuleItem, value: string, callback: (error?: string | Error) => void) {
|
||||||
|
if (!Strings.isEmpty(value)) {
|
||||||
|
if (!value.startsWith('/')) {
|
||||||
|
callback('必须以“/”开头')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
}, message: '请填写路由前缀', trigger: 'blur',
|
||||||
|
} ],
|
||||||
|
endpointPath: [ {
|
||||||
|
required: true, validator(_: InternalRuleItem, value: string, callback: (error?: string | Error) => void) {
|
||||||
|
if (Strings.isBlank(value)) {
|
||||||
|
callback(new Error('请填写端点地址'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
if (!Strings.isEmpty(value)) {
|
||||||
callback()
|
if (!value.startsWith('/')) {
|
||||||
}, message: '请填写路由前缀', trigger: 'blur',
|
callback(new Error('必须以“/”开头'))
|
||||||
} ],
|
return
|
||||||
endpointPath: [ {
|
}
|
||||||
required: true, validator(_: InternalRuleItem, value: string, callback: (error?: string | Error) => void) {
|
|
||||||
if (Strings.isBlank(value)) {
|
|
||||||
callback(new Error('请填写端点地址'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!Strings.isEmpty(value)) {
|
|
||||||
if (!value.startsWith('/')) {
|
|
||||||
callback(new Error('必须以“/”开头'))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
callback()
|
||||||
callback()
|
}, trigger: 'blur',
|
||||||
}, trigger: 'blur',
|
} ],
|
||||||
} ],
|
accessModel: [ {required: true, message: '请选择访问模式', trigger: 'blur'} ],
|
||||||
accessModel: [ {required: true, message: '请选择访问模式', trigger: 'blur'} ],
|
},
|
||||||
|
})
|
||||||
|
watchEffect(() => {
|
||||||
|
formPanelProps.title = status.value === 'add' ? '新建产品' : '修改产品'
|
||||||
})
|
})
|
||||||
|
|
||||||
function dialogCloseHandler() {
|
|
||||||
formData.value = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitHandler() {
|
|
||||||
if (status.value === 'view') return
|
|
||||||
submiting.value = true
|
|
||||||
if (formData.value.id != null) {
|
|
||||||
FormUtil.submit(endpointFormIns, () => EndpointApi.modify(formData.value))
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
FormUtil.submit(endpointFormIns, () => EndpointApi.add(formData.value))
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open(data: EndpointTypes.SearchEndpointResult = {}) {
|
open(data?: EndpointTypes.SearchEndpointResult) {
|
||||||
showDialog.value = true
|
formPanelIns.value?.open(data?.id)
|
||||||
if (!Strings.isBlank(data.id)) {
|
|
||||||
status.value = 'modify'
|
|
||||||
EndpointApi.detail(data.id!)
|
|
||||||
.then(res => {
|
|
||||||
formData.value = res.data
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
status.value = 'add'
|
|
||||||
formData.value = data
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.form-panel {
|
.form-items {
|
||||||
padding 20px
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
&:last-child {
|
||||||
|
grid-column: span 2;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
:closed="dialogCloseHandler"
|
||||||
destroy-on-close
|
title="预览"
|
||||||
width="fit-content"
|
|
||||||
@close="dialogCloseHandler"
|
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<ElForm :model="formData"
|
<ElForm :model="formData"
|
||||||
|
|
@ -79,7 +77,7 @@
|
||||||
<ElButton :loading="previewing" type="primary" @click="previewHandler">预览</ElButton>
|
<ElButton :loading="previewing" type="primary" @click="previewHandler">预览</ElButton>
|
||||||
<ElButton :loading="downloading" type="primary" @click="downloadHandler">下载</ElButton>
|
<ElButton :loading="downloading" type="primary" @click="downloadHandler">下载</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import {
|
||||||
|
|
@ -90,6 +88,7 @@ import {
|
||||||
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import FormUtil from '@/common/utils/formUtil.ts'
|
import FormUtil from '@/common/utils/formUtil.ts'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const activeName = ref('')
|
const activeName = ref('')
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
|
|
@ -256,7 +255,7 @@ defineExpose({
|
||||||
}
|
}
|
||||||
|
|
||||||
& > div:nth-child(3) {
|
& > div:nth-child(3) {
|
||||||
width: calc(800px - 272px);
|
width: calc(800px - 288px);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
:action-column="actionColumn"
|
ref="tablePage"
|
||||||
:paging="paging">
|
v-bind="tablePageProps">
|
||||||
<template #searchFormItem="{searchForm}">
|
<template #simpleFormItem="formData">
|
||||||
<ElFormItem label="表名称">
|
<ElFormItem>
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.tableName"
|
v-model="formData.tableName"
|
||||||
placeholder="表名称"/>
|
placeholder="表名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -15,30 +15,35 @@
|
||||||
<ElTableColumn label="备注" prop="tableComment"/>
|
<ElTableColumn label="备注" prop="tableComment"/>
|
||||||
</template>
|
</template>
|
||||||
<CodePreview ref="codePreview"/>
|
<CodePreview ref="codePreview"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import CodePreview from '@/pages/sys/gen/db-table/CodePreview.vue'
|
import CodePreview from '@/pages/sys/gen/db-table/CodePreview.vue'
|
||||||
import DbTableApi from '@/pages/sys/gen/db-table/db-table-api.ts'
|
import DbTableApi from '@/pages/sys/gen/db-table/db-table-api.ts'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, { buildTablePageProps } from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
import type { ActionColumnType } from '@/components/page/a-page-type.ts'
|
|
||||||
|
|
||||||
const codePreviewIns = useTemplateRef<InstanceType<typeof CodePreview>>('codePreview')
|
const codePreviewIns = useTemplateRef<InstanceType<typeof CodePreview>>('codePreview')
|
||||||
|
|
||||||
const actionColumn = reactive<ActionColumnType<DbTableTypes.TableInfo>>({
|
const tablePageProps = buildTablePageProps<DbTableTypes.SearchTplParam, DbTableTypes.TableInfo>({
|
||||||
tableActions: [
|
pageLayout: {
|
||||||
{
|
enableHighForm: false,
|
||||||
tooltip: '预览',
|
},
|
||||||
icon: 'Edit',
|
searchForm: {
|
||||||
action({row}: { row: DbTableTypes.TableInfo }) {
|
paging: DbTableApi.tablePaing,
|
||||||
codePreviewIns.value?.open(row)
|
},
|
||||||
},
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '预览',
|
||||||
|
icon: 'yulan',
|
||||||
|
action({row}: { row: DbTableTypes.TableInfo }) {
|
||||||
|
codePreviewIns.value?.open(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function paging(param: DbTableTypes.SearchTplParam) {
|
|
||||||
return DbTableApi.tablePaing(param)
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:default-search-form="defaultSearchForm"
|
<template #simpleFormItem="formData">
|
||||||
:left-tools="leftTools"
|
<ElFormItem>
|
||||||
:paging="paging">
|
|
||||||
<template #searchFormItem="{searchForm}">
|
|
||||||
<ElFormItem label="模板名称">
|
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.tplName"
|
v-model="formData.tplName"
|
||||||
placeholder="模板名称"/>
|
placeholder="模板名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="前端/后端">
|
<ElFormItem>
|
||||||
<ElSelect
|
<ElSelect
|
||||||
v-model="searchForm.lang"
|
v-model="formData.lang"
|
||||||
placeholder="前端/后端"
|
placeholder="前端/后端"
|
||||||
>
|
>
|
||||||
<ElOption
|
<ElOption
|
||||||
|
|
@ -40,69 +37,81 @@
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
</template>
|
</template>
|
||||||
<TplForm ref="tplForm" @edit-succ="research"/>
|
<TplForm ref="tplForm" :research="research"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
||||||
import TplForm from '@/pages/sys/gen/tpl/TplForm.vue'
|
import TplForm from '@/pages/sys/gen/tpl/TplForm.vue'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const defaultSearchForm: TplTypes.SearchTplParam = {
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
orders: 'lang,tpl_name',
|
|
||||||
tpl: {},
|
|
||||||
}
|
|
||||||
const tplFormIns = useTemplateRef<InstanceType<typeof TplForm>>('tplForm')
|
const tplFormIns = useTemplateRef<InstanceType<typeof TplForm>>('tplForm')
|
||||||
|
const tablePageProps = buildTablePageProps<TplTypes.SearchTplParam, TplTypes.SearchTplResult>({
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
pageLayout: {
|
||||||
const leftTools: ToolType[] = [
|
enableHighForm: false,
|
||||||
{
|
},
|
||||||
icon: 'Plus',
|
searchForm: {
|
||||||
label: '新建',
|
defaultData: {
|
||||||
action() {
|
orders: 'lang,tpl_name',
|
||||||
tplFormIns.value?.open()
|
tpl: {},
|
||||||
|
},
|
||||||
|
highForm: {
|
||||||
|
contentWidth: 320,
|
||||||
|
},
|
||||||
|
simpleForm: {
|
||||||
|
colCount: 2,
|
||||||
|
},
|
||||||
|
paging: TplApi.paging,
|
||||||
|
},
|
||||||
|
toolBar: {
|
||||||
|
leftTools: [
|
||||||
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
tplFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '编辑',
|
||||||
|
icon: 'Edit',
|
||||||
|
type: 'success',
|
||||||
|
action({row}) {
|
||||||
|
tplFormIns.value?.open(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'Delete',
|
||||||
|
loading: false,
|
||||||
|
type: 'danger',
|
||||||
|
tooltip: '删除',
|
||||||
|
confirm: {
|
||||||
|
title: '是否删除当前数据',
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
return TplApi.del([ row.id! ])
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
|
||||||
const actionColumn = reactive<ActionColumnType<TplTypes.SearchTplResult>>({
|
|
||||||
tableActions: [
|
|
||||||
{
|
|
||||||
tooltip: '编辑',
|
|
||||||
icon: 'Edit',
|
|
||||||
type: 'success',
|
|
||||||
action({row}) {
|
|
||||||
tplFormIns.value?.open(row)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'Delete',
|
|
||||||
loading: false,
|
|
||||||
type: 'danger',
|
|
||||||
tooltip: '删除',
|
|
||||||
confirm: {
|
|
||||||
title: '是否删除当前数据',
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
return TplApi.del([ row.id! ])
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function research() {
|
function research() {
|
||||||
formPageIns.value?.doSearch()
|
tablePageIns.value?.doSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
function paging(param: TplTypes.SearchTplParam) {
|
|
||||||
return TplApi.paging(param)
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
:title="status==='add'?'新增模板':'修改模板'"
|
||||||
destroy-on-close
|
|
||||||
width="25vw"
|
width="25vw"
|
||||||
@close="dialogCloseHandler">
|
@close="dialogCloseHandler">
|
||||||
<ElForm :model="tplFormData"
|
<ElForm :model="tplFormData"
|
||||||
|
|
@ -10,13 +9,11 @@
|
||||||
<ElFormItem label="模板名称">
|
<ElFormItem label="模板名称">
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="tplFormData.tplName"
|
v-model="tplFormData.tplName"
|
||||||
|
|
||||||
placeholder="模板名称"/>
|
placeholder="模板名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="前端/后端">
|
<ElFormItem label="前端/后端">
|
||||||
<ElSelect
|
<ElSelect
|
||||||
v-model="tplFormData.lang"
|
v-model="tplFormData.lang"
|
||||||
|
|
||||||
placeholder="前端/后端"
|
placeholder="前端/后端"
|
||||||
>
|
>
|
||||||
<ElOption
|
<ElOption
|
||||||
|
|
@ -31,7 +28,6 @@
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="tplFormData.tpl.content"
|
v-model="tplFormData.tpl.content"
|
||||||
:spellcheck="false"
|
:spellcheck="false"
|
||||||
|
|
||||||
placeholder="模板内容"
|
placeholder="模板内容"
|
||||||
resize="none"
|
resize="none"
|
||||||
type="textarea"/>
|
type="textarea"/>
|
||||||
|
|
@ -41,7 +37,6 @@
|
||||||
<ElInput
|
<ElInput
|
||||||
:spellcheck="false"
|
:spellcheck="false"
|
||||||
v-model="tplFormData.tpl.dir"
|
v-model="tplFormData.tpl.dir"
|
||||||
|
|
||||||
placeholder="文件路径"
|
placeholder="文件路径"
|
||||||
resize="none"
|
resize="none"
|
||||||
type="textarea"/>
|
type="textarea"/>
|
||||||
|
|
@ -51,7 +46,6 @@
|
||||||
<ElInput
|
<ElInput
|
||||||
:spellcheck="false"
|
:spellcheck="false"
|
||||||
v-model="tplFormData.tpl.filename"
|
v-model="tplFormData.tpl.filename"
|
||||||
|
|
||||||
placeholder="文件名称"
|
placeholder="文件名称"
|
||||||
resize="none"
|
resize="none"
|
||||||
type="textarea"/>
|
type="textarea"/>
|
||||||
|
|
@ -61,12 +55,13 @@
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
import TplApi from '@/pages/sys/gen/tpl/tpl-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const emits = defineEmits([ 'editSucc' ])
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,48 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<AFormPanel
|
||||||
:close-on-click-modal="false"
|
ref="formPanel"
|
||||||
destroy-on-close width="25vw" @close="dialogCloseHandler">
|
v-bind="formPanelProps">
|
||||||
<ElForm :model="menuForm" class="menu-form">
|
<template #default="formData">
|
||||||
<ElFormItem label="上级">
|
<div class="form-items">
|
||||||
<ElTreeSelect v-model="menuForm.pid" :data="menuTreeDataSource" :default-expanded-keys="['0']" :render-after-expand="false" check-strictly placeholder="选择上级菜单"/>
|
<ElFormItem label="上级">
|
||||||
</ElFormItem>
|
<ElTreeSelect v-model="formData.pid" v-loading="loadingMenus" :data="menuTreeDataSource" :default-expanded-keys="['0']" :render-after-expand="false" check-strictly placeholder="选择上级菜单"/>
|
||||||
<ElFormItem label="客户端" prop="clients">
|
</ElFormItem>
|
||||||
<ElCheckboxGroup v-model="menuForm.clients">
|
<ElFormItem label="客户端" prop="clients">
|
||||||
<ElCheckbox v-for="client in ClientUtil.clients" :key="client.val" :label="client.txt" :value="client.val"/>
|
<ElCheckboxGroup v-model="formData.clients">
|
||||||
</ElCheckboxGroup>
|
<ElCheckbox v-for="client in ClientUtil.clients" :key="client.val" :label="client.txt" :value="client.val"/>
|
||||||
</ElFormItem>
|
</ElCheckboxGroup>
|
||||||
<ElFormItem label="类型">
|
</ElFormItem>
|
||||||
<ElSelect v-model="menuForm.menuCategory" :data="menuCategoryData" placeholder="选择类型">
|
<ElFormItem label="类型">
|
||||||
<ElOption v-for="menuCategory in menuCategoryData" :key="menuCategory.key" :label="menuCategory.label" :value="menuCategory.key"/>
|
<ElSelect v-model="formData.menuCategory" :data="menuCategoryData" placeholder="选择类型">
|
||||||
</ElSelect>
|
<ElOption v-for="menuCategory in menuCategoryData" :key="menuCategory.key" :label="menuCategory.label" :value="menuCategory.key"/>
|
||||||
</ElFormItem>
|
</ElSelect>
|
||||||
|
</ElFormItem>
|
||||||
|
|
||||||
<ElFormItem label="名称">
|
<ElFormItem label="名称">
|
||||||
<ElInput v-model="menuForm.title" placeholder="名称"/>
|
<ElInput v-model="formData.title" placeholder="名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
|
|
||||||
<ElFormItem v-if="menuForm.menuCategory === MenuCategory.Page || menuForm.menuCategory === MenuCategory.SubPage" label="路由名称">
|
<ElFormItem v-if="formData.menuCategory === MenuCategory.Page || formData.menuCategory === MenuCategory.SubPage" label="路由名称">
|
||||||
<ElInput v-model="menuForm.routeName" :min="0" placeholder="路由名称"/>
|
<ElInput v-model="formData.routeName" :min="0" placeholder="路由名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem v-if="menuForm.menuCategory === MenuCategory.Page || menuForm.menuCategory === MenuCategory.SubPage" label="路由地址">
|
<ElFormItem v-if="formData.menuCategory === MenuCategory.Page || formData.menuCategory === MenuCategory.SubPage" label="路由地址">
|
||||||
<ElInput v-model="menuForm.routePath" :min="0" placeholder="路由地址"/>
|
<ElInput v-model="formData.routePath" :min="0" placeholder="路由地址"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="编码">
|
<ElFormItem label="编码">
|
||||||
<ElInput v-model="menuForm.sn" :min="0" placeholder="编码"/>
|
<ElInput v-model="formData.sn" :min="0" placeholder="编码"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="图标">
|
<ElFormItem label="图标">
|
||||||
<ElDropdown closable header="图标列表" placement="bottom" style="width: 100%" trigger="click">
|
<AIconDropTable v-model="formData.icon"/>
|
||||||
<ElInput v-model="menuForm.iconName" placeholder="选择图标" readonly>
|
</ElFormItem>
|
||||||
<template #suffix>
|
<ElFormItem label="排序">
|
||||||
<AIcon :name="menuForm.icon!"/>
|
<ElInputNumber v-model="formData.sort" :min="0" controls-position="right" placeholder="排序"/>
|
||||||
</template>
|
</ElFormItem>
|
||||||
</ElInput>
|
</div>
|
||||||
<template #dropdown>
|
|
||||||
<div class="dropdown-table-wrapper">
|
|
||||||
<ElTable
|
|
||||||
ref="dropdownTable"
|
|
||||||
:data="iconTableDataSource"
|
|
||||||
cell-class-name="table-cell"
|
|
||||||
class="table-list"
|
|
||||||
empty-text="暂无数据"
|
|
||||||
header-row-class-name="table-header"
|
|
||||||
row-key="id"
|
|
||||||
width="324"
|
|
||||||
@current-change="currentChangeHandler">
|
|
||||||
<ElTableColumn label="#" type="index"/>
|
|
||||||
<ElTableColumn label="图标" prop="font_class">
|
|
||||||
<template #default="scope">
|
|
||||||
<AIcon :name="scope?.row?.font_class"/>
|
|
||||||
</template>
|
|
||||||
</ElTableColumn>
|
|
||||||
<ElTableColumn label="名称" prop="name"/>
|
|
||||||
</ElTable>
|
|
||||||
<ElPagination :page-size="pagination.size" :total="pagination.total" layout="total, prev, pager, next" @change="pageChangeHandler"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ElDropdown>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="排序">
|
|
||||||
<ElInputNumber v-model="menuForm.sort" :min="0" placeholder="排序" style="width: 100%"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
<template #footer>
|
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</AFormPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
MenuCategory,
|
MenuCategory,
|
||||||
MenuCategoryDict,
|
MenuCategoryDict,
|
||||||
|
|
@ -82,62 +50,23 @@ import {
|
||||||
import MenuApi from '@/pages/sys/menus/menu-api.ts'
|
import MenuApi from '@/pages/sys/menus/menu-api.ts'
|
||||||
import Colls from '@/common/utils/colls.ts'
|
import Colls from '@/common/utils/colls.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import {
|
|
||||||
ElMessage,
|
|
||||||
type TableInstance,
|
|
||||||
} from 'element-plus'
|
|
||||||
import {
|
|
||||||
type IconGlyphs,
|
|
||||||
icons,
|
|
||||||
} from '@/components/a-icon/iconfont.ts'
|
|
||||||
import AIcon from '@/components/a-icon/AIcon.vue'
|
|
||||||
import ClientUtil from '@/common/utils/client-util.ts'
|
import ClientUtil from '@/common/utils/client-util.ts'
|
||||||
import Utils from '@/common/utils'
|
import AFormPanel, {
|
||||||
|
type AFormPanelInstance,
|
||||||
|
buildFormPanelProps,
|
||||||
|
} from '@/components/a-form-panel/AFormPanel.tsx'
|
||||||
|
import AIconDropTable from '@/components/a-icon/AIconDropTable.vue'
|
||||||
|
import { nanoid } from 'nanoid'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const props = withDefaults(defineProps<{
|
||||||
|
research?: () => void
|
||||||
const pagination = reactive<G.Pagination>({
|
}>(), {
|
||||||
total: icons.glyphs.length,
|
research: () => {
|
||||||
pages: Math.ceil(icons.glyphs.length / 5),
|
},
|
||||||
current: 1,
|
|
||||||
size: 5,
|
|
||||||
})
|
})
|
||||||
|
const status = ref<'add' | 'modify'>('add')
|
||||||
function dialogCloseHandler() {
|
const loadingMenus = ref<boolean>(false)
|
||||||
menuForm.value = {
|
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
icon: 'dianzixiaopiao',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pageChangeHandler(currentPage: number, pageSize: number) {
|
|
||||||
pagination.current = currentPage
|
|
||||||
pagination.size = pageSize
|
|
||||||
iconTableDataSource.value = icons.glyphs.filter((_, i) => {
|
|
||||||
return i >= (currentPage - 1) * pageSize && i < currentPage * pageSize
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const dropdownTableIns = useTemplateRef<TableInstance>('dropdownTable')
|
|
||||||
|
|
||||||
let menuForm = ref<MenuTypes.MenuForm>({
|
|
||||||
icon: 'dianzixiaopiao',
|
|
||||||
})
|
|
||||||
|
|
||||||
const iconTableDataSource = ref<IconGlyphs[]>(
|
|
||||||
icons.glyphs.filter((_, i) => {
|
|
||||||
return i >= 0 && i < 5
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
function currentChangeHandler(val?: IconGlyphs) {
|
|
||||||
if (val == null) return
|
|
||||||
menuForm.value.icon = val.font_class
|
|
||||||
menuForm.value.iconName = val.name
|
|
||||||
}
|
|
||||||
|
|
||||||
const showDialog = ref(false)
|
|
||||||
const submiting = ref(false)
|
|
||||||
const status = ref<'add' | 'view' | 'modify'>('add')
|
|
||||||
|
|
||||||
const menuCategoryData = computed(() => {
|
const menuCategoryData = computed(() => {
|
||||||
const data: { key: string; label: string }[] = []
|
const data: { key: string; label: string }[] = []
|
||||||
|
|
@ -151,66 +80,61 @@ const menuCategoryData = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const menuTreeDataSource = ref<MenuTypes.SysMenu[]>()
|
const menuTreeDataSource = ref<MenuTypes.SysMenu[]>()
|
||||||
|
const formPanelProps = buildFormPanelProps<MenuTypes.MenuForm>({
|
||||||
|
detailsLoader(id?: string) {
|
||||||
function submitHandler() {
|
if (Strings.isBlank(id)) {
|
||||||
if (status.value === 'view') return
|
status.value = 'add'
|
||||||
submiting.value = true
|
return Promise.resolve({
|
||||||
|
|
||||||
menuForm.value.clientCode = ClientUtil.getClientCode(menuForm.value.clients!)
|
|
||||||
if (menuForm.value.id != null) {
|
|
||||||
MenuApi.modify(menuForm.value)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
showDialog.value = false
|
|
||||||
emits(('editSucc'))
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
MenuApi.add(menuForm.value)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
showDialog.value = false
|
|
||||||
emits(('editSucc'))
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open(data: MenuTypes.MenuForm = {
|
|
||||||
icon: 'dianzixiaopiao',
|
|
||||||
}) {
|
|
||||||
if (!Strings.isBlank(data.id)) {
|
|
||||||
status.value = 'modify'
|
|
||||||
data = Utils.clone(data)
|
|
||||||
data.clients = ClientUtil.getClients(data.clientCode!).map(it => it.val)
|
|
||||||
menuForm.value = data
|
|
||||||
} else {
|
|
||||||
menuForm.value = {
|
|
||||||
icon: 'dianzixiaopiao',
|
icon: 'dianzixiaopiao',
|
||||||
}
|
pid: '0',
|
||||||
|
clients: [ 1 ],
|
||||||
|
menuCategory: MenuCategory.Catalog,
|
||||||
|
sn: nanoid(10),
|
||||||
|
} as MenuTypes.MenuForm)
|
||||||
|
} else {
|
||||||
|
status.value = 'modify'
|
||||||
|
return MenuApi
|
||||||
|
.detail(id!)
|
||||||
|
.then((res) => {
|
||||||
|
return {
|
||||||
|
...res.data,
|
||||||
|
clients: ClientUtil.getClients(res.data.clientCode!).map(it => it.val),
|
||||||
|
} as MenuTypes.MenuForm
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doSubmit(data) {
|
||||||
|
if (status.value === 'add') {
|
||||||
|
return MenuApi.add(data)
|
||||||
|
.then(props.research)
|
||||||
|
} else {
|
||||||
|
return MenuApi.modify(data)
|
||||||
|
.then(props.research)
|
||||||
}
|
}
|
||||||
showDialog.value = true
|
|
||||||
dropdownTableIns.value?.setCurrentRow(icons.glyphs.find((it) => it.font_class === data.icon))
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
watchEffect(() => {
|
||||||
onMounted(() => {
|
formPanelProps.title = status.value === 'add' ? '新建菜单' : '修改菜单'
|
||||||
MenuApi.list().then(({data}) => {
|
})
|
||||||
const nodes = Colls.toTree(data.map((it) => ({value: it.id, label: it.title, ...it})))
|
defineExpose({
|
||||||
menuTreeDataSource.value = [ {value: '0', label: '顶级菜单', id: '0', pid: '0', children: nodes} ]
|
open(data?: MenuTypes.MenuForm) {
|
||||||
})
|
loadingMenus.value = true
|
||||||
|
MenuApi.list()
|
||||||
|
.then(({data}) => {
|
||||||
|
const nodes = Colls.toTree(data.map((it) => ({value: it.id, label: it.title, ...it})))
|
||||||
|
menuTreeDataSource.value = [ {value: '0', label: '顶级菜单', id: '0', pid: '0', children: nodes} ]
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loadingMenus.value = false
|
||||||
|
})
|
||||||
|
formPanelIns.value?.open(data?.id)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.menu-form {
|
.form-items {
|
||||||
padding 20px
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-table-wrapper {
|
.dropdown-table-wrapper {
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:left-tools="leftTools"
|
<template #simpleFormItem="formData">
|
||||||
:list="listAll"
|
|
||||||
:table-props="{
|
|
||||||
treeProps: { children: 'children', hasChildren: 'hasChildren' },
|
|
||||||
treeLoad: treeLoad,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #searchFormItem="{ searchForm }">
|
|
||||||
<ElFormItem label="菜单名称">
|
|
||||||
<ElInput v-model="searchForm.title" placeholder="菜单名称"/>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="路由名称">
|
|
||||||
<ElInput v-model="searchForm.routeName" placeholder="路由名称"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</template>
|
|
||||||
<template #simpleSearchFormItem="{ searchForm }">
|
|
||||||
<ElFormItem>
|
<ElFormItem>
|
||||||
<ElInput v-model="searchForm.title" placeholder="菜单名称"/>
|
<ElInput v-model="formData.title" placeholder="菜单名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem>
|
<ElFormItem>
|
||||||
<ElInput v-model="searchForm.routeName" placeholder="路由名称"/>
|
<ElInput v-model="formData.routeName" placeholder="路由名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
|
|
@ -48,12 +33,9 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
<MenuForm ref="menuForm" :research="research"/>
|
||||||
<MenuForm ref="menuForm" @editSucc="research"/>
|
</ATablePage>
|
||||||
|
|
||||||
</FormPage>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
@ -61,89 +43,94 @@ import MenuApi from '@/pages/sys/menus/menu-api.ts'
|
||||||
import MenuForm from '@/pages/sys/menus/MenuForm.vue'
|
import MenuForm from '@/pages/sys/menus/MenuForm.vue'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import AIcon from '@/components/a-icon/AIcon.vue'
|
import AIcon from '@/components/a-icon/AIcon.vue'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
import Colls from '@/common/utils/colls.ts'
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const menuFormIns = useTemplateRef<InstanceType<typeof MenuForm>>('menuForm')
|
const menuFormIns = useTemplateRef<InstanceType<typeof MenuForm>>('menuForm')
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
|
|
||||||
const actionColumn = reactive<ActionColumnType<MenuTypes.SysMenu>>({
|
const tablePageProps = buildTablePageProps<MenuTypes.SearchForm, MenuTypes.SysMenu>({
|
||||||
tableActions: [
|
pageLayout: {
|
||||||
{
|
enableHighForm: false,
|
||||||
tooltip: '编辑',
|
},
|
||||||
icon: 'Edit',
|
searchForm: {
|
||||||
type: 'success',
|
simpleForm: {
|
||||||
action({row}) {
|
colCount: 2,
|
||||||
menuFormIns.value?.open(row as MenuTypes.MenuForm)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
list() {
|
||||||
icon: 'Delete',
|
return MenuApi.listAll()
|
||||||
loading: false,
|
.then(res => {
|
||||||
type: 'danger',
|
res.data = Colls.toTree(res.data ?? [])
|
||||||
tooltip: '删除',
|
.map(it => {
|
||||||
confirm: {
|
return {
|
||||||
title: '是否删除当前数据',
|
...it,
|
||||||
},
|
hasChildren: !Colls.isEmpty(it.children),
|
||||||
action({row}) {
|
}
|
||||||
return MenuApi.del([ row.id! ])
|
})
|
||||||
.then(() => {
|
return res
|
||||||
ElMessage.success('删除成功')
|
})
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
const leftTools: ToolType[] = [
|
|
||||||
{
|
|
||||||
icon: 'Plus',
|
|
||||||
label: '新建',
|
|
||||||
action() {
|
|
||||||
menuFormIns.value?.open()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
toolBar: {
|
||||||
|
leftTools: [
|
||||||
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
menuFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '编辑',
|
||||||
|
icon: 'Edit',
|
||||||
|
type: 'success',
|
||||||
|
action({row}) {
|
||||||
|
menuFormIns.value?.open(row as MenuTypes.MenuForm)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'Delete',
|
||||||
|
loading: false,
|
||||||
|
type: 'danger',
|
||||||
|
tooltip: '删除',
|
||||||
|
confirm: {
|
||||||
|
title: '是否删除当前数据',
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
return MenuApi.del([ row.id! ])
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
function research() {
|
function research() {
|
||||||
formPageIns.value?.doSearch()
|
tablePageIns.value?.doSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
function listAll(param: MenuTypes.SearchForm) {
|
|
||||||
return MenuApi.listAll({...param, pid: '0'})
|
|
||||||
.then(res => {
|
|
||||||
const data = res.data ?? []
|
|
||||||
for (let it of data) {
|
|
||||||
it.hasChildren = true
|
|
||||||
it.children = []
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function treeLoad(param: MenuTypes.SearchForm, row: MenuTypes.SysMenu, expanded: any, resolve?: (data: MenuTypes.SysMenu[]) => void) {
|
|
||||||
if (resolve == null && !expanded) return
|
|
||||||
MenuApi.listAll({...param, pid: row.id})
|
|
||||||
.then(res => {
|
|
||||||
if (resolve != null) {
|
|
||||||
resolve(res.data?.map(it => {
|
|
||||||
it.hasChildren = true
|
|
||||||
return it
|
|
||||||
}) ?? [])
|
|
||||||
} else {
|
|
||||||
formPageIns.value?.dataTableIns?.updateKeyChildren(row.id, res.data?.map(it => {
|
|
||||||
it.hasChildren = true
|
|
||||||
it.children = []
|
|
||||||
return it
|
|
||||||
}) ?? [])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.expand-btn {
|
||||||
|
margin-right 5px
|
||||||
|
cursor pointer
|
||||||
|
transition transform .3s ease-in-out
|
||||||
|
margin-left calc(var(--expand-indent) * 16px)
|
||||||
|
|
||||||
|
&.expand-btn-expanded {
|
||||||
|
transform rotateZ(90deg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export default {
|
||||||
return get<G.PageResult<MenuTypes.SysMenu>>('/menu/page_list', data)
|
return get<G.PageResult<MenuTypes.SysMenu>>('/menu/page_list', data)
|
||||||
},
|
},
|
||||||
paging(data: MenuTypes.SearchForm & G.PageParam) {
|
paging(data: MenuTypes.SearchForm & G.PageParam) {
|
||||||
return get<G.PageResult<MenuTypes.SysMenu>>('/menu/page_list', data)
|
return get<G.PageResult<MenuTypes.SysMenu>>('/menu/paging', data)
|
||||||
},
|
},
|
||||||
list(data?: MenuTypes.SearchForm | null) {
|
list(data?: MenuTypes.SearchForm | null) {
|
||||||
return get<MenuTypes.SysMenu[]>('/menu/list_all', data)
|
return get<MenuTypes.SysMenu[]>('/menu/list_all', data)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ declare global {
|
||||||
// 面包路径
|
// 面包路径
|
||||||
breadcrumb?: string[]
|
breadcrumb?: string[]
|
||||||
menuCategory?: MenuCategory
|
menuCategory?: MenuCategory
|
||||||
|
hasChildren?: boolean
|
||||||
children?: SysMenu[]
|
children?: SysMenu[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
title="分配资源"
|
||||||
destroy-on-close
|
|
||||||
width="900">
|
width="900">
|
||||||
<ElTransfer
|
<ElTransfer
|
||||||
v-model="rightValue"
|
v-model="rightValue"
|
||||||
|
|
@ -53,7 +52,7 @@
|
||||||
<ElButton @click="showDialog = false">取消</ElButton>
|
<ElButton @click="showDialog = false">取消</ElButton>
|
||||||
<ElButton :disabled="rightValue.length <= 0" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
<ElButton :disabled="rightValue.length <= 0" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RoleApi from '@/pages/sys/role/role-api.ts'
|
import RoleApi from '@/pages/sys/role/role-api.ts'
|
||||||
|
|
@ -63,6 +62,7 @@ import {
|
||||||
type TransferDataItem,
|
type TransferDataItem,
|
||||||
} from 'element-plus'
|
} from 'element-plus'
|
||||||
import ResourceApi from '@/pages/sys/resource/resource-api.ts'
|
import ResourceApi from '@/pages/sys/resource/resource-api.ts'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
const submiting = ref(false)
|
const submiting = ref(false)
|
||||||
|
|
|
||||||
|
|
@ -1,112 +1,116 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:left-tools="leftTools"
|
<template #simpleFormItem="formData">
|
||||||
:paging="paging">
|
<ElFormItem>
|
||||||
<template #searchFormItem="{ searchForm }">
|
|
||||||
<ElFormItem label="角色代码">
|
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.roleCode"
|
v-model="formData.roleCode"
|
||||||
placeholder="角色代码"/>
|
placeholder="角色代码"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="角色名称">
|
<ElFormItem>
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.roleName"
|
v-model="formData.roleName"
|
||||||
placeholder="角色名称"/>
|
placeholder="角色名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="备注">
|
|
||||||
<ElInput
|
|
||||||
v-model="searchForm.memo"
|
|
||||||
placeholder="备注"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<ElTableColumn label="角色代码" prop="roleCode"/>
|
<ElTableColumn label="角色代码" prop="roleCode"/>
|
||||||
<ElTableColumn label="角色名称" prop="roleName"/>
|
<ElTableColumn label="角色名称" prop="roleName"/>
|
||||||
<ElTableColumn label="备注" prop="memo"/>
|
<ElTableColumn label="备注" prop="memo"/>
|
||||||
</template>
|
</template>
|
||||||
<RoleForm ref="roleForm" @edit-succ="research"/>
|
<RoleForm ref="roleForm" :research="research"/>
|
||||||
<BindRes ref="bindRes"/>
|
<BindRes ref="bindRes"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RoleApi from '@/pages/sys/role/role-api.ts'
|
import RoleApi from '@/pages/sys/role/role-api.ts'
|
||||||
import RoleForm from '@/pages/sys/role/RoleForm.vue'
|
import RoleForm from '@/pages/sys/role/RoleForm.vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import BindRes from '@/pages/sys/role/BindRes.vue'
|
import BindRes from '@/pages/sys/role/BindRes.vue'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const roleFormIns = useTemplateRef<InstanceType<typeof RoleForm>>('roleForm')
|
const roleFormIns = useTemplateRef<InstanceType<typeof RoleForm>>('roleForm')
|
||||||
const bindResIns = useTemplateRef<InstanceType<typeof BindRes>>('bindRes')
|
const bindResIns = useTemplateRef<InstanceType<typeof BindRes>>('bindRes')
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
|
const tablePageProps = buildTablePageProps<RoleTypes.SearchRoleParam, RoleTypes.SearchRoleResult>({
|
||||||
|
pageLayout: {
|
||||||
|
enableHighForm: false,
|
||||||
|
},
|
||||||
|
searchForm: {
|
||||||
|
simpleForm: {colCount: 2},
|
||||||
|
paging: RoleApi.paging,
|
||||||
|
},
|
||||||
|
toolBar: {
|
||||||
|
leftTools: [
|
||||||
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
roleFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
|
||||||
const actionColumn = reactive<ActionColumnType<RoleTypes.SearchRoleResult>>({
|
{
|
||||||
tableActions: [
|
tooltip: '编辑',
|
||||||
{
|
icon: 'Edit',
|
||||||
tooltip: '资源',
|
type: 'success',
|
||||||
icon: 'ScaleToOriginal',
|
show({row}) {
|
||||||
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
return row.id != '1'
|
||||||
bindResIns.value?.open(row.id!)
|
},
|
||||||
},
|
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
||||||
},
|
if (row.id == '1') {
|
||||||
{
|
ElMessage.error('不能操作管理员')
|
||||||
tooltip: '编辑',
|
return
|
||||||
icon: 'Edit',
|
}
|
||||||
type: 'success',
|
roleFormIns.value?.open(row)
|
||||||
show({row}) {
|
},
|
||||||
return row.id != '1'
|
},
|
||||||
},
|
{
|
||||||
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
tooltip: '资源',
|
||||||
if (row.id == '1') {
|
type: 'warning',
|
||||||
ElMessage.error('不能操作管理员')
|
icon: 'caidan',
|
||||||
return
|
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
||||||
}
|
bindResIns.value?.open(row.id!)
|
||||||
roleFormIns.value?.open(row)
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
icon: 'Delete',
|
||||||
icon: 'Delete',
|
loading: false,
|
||||||
loading: false,
|
type: 'danger',
|
||||||
type: 'danger',
|
tooltip: '删除',
|
||||||
tooltip: '删除',
|
show({row}) {
|
||||||
confirm: {
|
return row.id != '1'
|
||||||
title: '是否删除当前数据',
|
},
|
||||||
},
|
confirm: {
|
||||||
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
title: '是否删除当前数据',
|
||||||
if (row.id == '1') {
|
},
|
||||||
ElMessage.error('不能操作管理员')
|
action({row}: { row: RoleTypes.SearchRoleResult }) {
|
||||||
return Promise.resolve(false)
|
if (row.id == '1') {
|
||||||
}
|
ElMessage.error('不能操作管理员')
|
||||||
return RoleApi.del([ row.id! ])
|
return Promise.resolve(false)
|
||||||
.then(() => {
|
}
|
||||||
ElMessage.success('删除成功')
|
return RoleApi.del([ row.id! ])
|
||||||
return true
|
.then(() => {
|
||||||
})
|
ElMessage.success('删除成功')
|
||||||
},
|
return true
|
||||||
},
|
})
|
||||||
],
|
},
|
||||||
})
|
},
|
||||||
const leftTools: ToolType[] = [
|
],
|
||||||
{
|
|
||||||
icon: 'Plus',
|
|
||||||
label: '新建',
|
|
||||||
action() {
|
|
||||||
roleFormIns.value?.open()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
})
|
||||||
|
|
||||||
function research() {
|
function research() {
|
||||||
formPageIns.value?.doSearch()
|
tablePageIns.value?.doSearch()
|
||||||
}
|
|
||||||
|
|
||||||
function paging(params: RoleTypes.SearchRoleParam) {
|
|
||||||
return RoleApi.paging(params)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,91 +1,77 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<AFormPanel
|
||||||
:close-on-click-modal="false"
|
ref="formPanel"
|
||||||
@close="dialogCloseHandler"
|
v-bind="formPanelProps">
|
||||||
destroy-on-close
|
<template #default="formData">
|
||||||
width="25vw">
|
<div class="form-items">
|
||||||
<ElForm :model="roleFormData"
|
<ElFormItem label="角色代码">
|
||||||
class="sys_role-form"
|
<ElInput
|
||||||
>
|
v-model="formData.roleCode"
|
||||||
<ElFormItem label="角色代码">
|
placeholder="角色代码"/>
|
||||||
<ElInput
|
</ElFormItem>
|
||||||
v-model="roleFormData.roleCode"
|
<ElFormItem label="角色名称">
|
||||||
|
<ElInput
|
||||||
placeholder="角色代码"/>
|
v-model="formData.roleName"
|
||||||
</ElFormItem>
|
placeholder="角色名称"/>
|
||||||
<ElFormItem label="角色名称">
|
</ElFormItem>
|
||||||
<ElInput
|
<ElFormItem label="备注">
|
||||||
v-model="roleFormData.roleName"
|
<ElInput
|
||||||
|
v-model="formData.memo"
|
||||||
placeholder="角色名称"/>
|
placeholder="备注"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="备注">
|
</div>
|
||||||
<ElInput
|
|
||||||
v-model="roleFormData.memo"
|
|
||||||
|
|
||||||
placeholder="备注"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
<template #footer>
|
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</AFormPanel>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RoleApi from '@/pages/sys/role/role-api.ts'
|
import RoleApi from '@/pages/sys/role/role-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import { ElMessage } from 'element-plus'
|
import AFormPanel, {
|
||||||
|
type AFormPanelInstance,
|
||||||
|
buildFormPanelProps,
|
||||||
|
} from '@/components/a-form-panel/AFormPanel.tsx'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const props = withDefaults(defineProps<{
|
||||||
const showDialog = ref(false)
|
research?: () => void
|
||||||
const submiting = ref(false)
|
}>(), {
|
||||||
const status = ref<'add' | 'view' | 'modify'>('add')
|
research: () => {
|
||||||
const roleFormData = ref<RoleTypes.SearchRoleResult>({})
|
},
|
||||||
|
})
|
||||||
|
const status = ref<'add' | 'modify'>('add')
|
||||||
|
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
|
const formPanelProps = buildFormPanelProps<RoleTypes.SearchRoleResult>({
|
||||||
|
detailsLoader(id?: string) {
|
||||||
|
if (Strings.isBlank(id)) {
|
||||||
|
status.value = 'add'
|
||||||
|
return Promise.resolve()
|
||||||
|
} else {
|
||||||
|
status.value = 'modify'
|
||||||
|
return RoleApi.detail(id!)
|
||||||
|
.then(res => {
|
||||||
|
return {
|
||||||
|
...res.data,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doSubmit(data) {
|
||||||
|
if (status.value === 'add') {
|
||||||
|
return RoleApi.add(data)
|
||||||
|
.then(props.research)
|
||||||
|
} else {
|
||||||
|
return RoleApi.modify(data)
|
||||||
|
.then(props.research)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
function dialogCloseHandler() {
|
watchEffect(() => {
|
||||||
roleFormData.value = {}
|
formPanelProps.title = status.value === 'add' ? '新建角色' : '修改角色'
|
||||||
}
|
})
|
||||||
|
|
||||||
function submitHandler() {
|
|
||||||
if (status.value === 'view') return
|
|
||||||
submiting.value = true
|
|
||||||
if (roleFormData.value.id != null) {
|
|
||||||
RoleApi.modify(roleFormData.value)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
RoleApi.add(roleFormData.value)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open(data: RoleTypes.SearchRoleResult = {}) {
|
open(data?: RoleTypes.SearchRoleResult) {
|
||||||
showDialog.value = true
|
formPanelIns.value?.open(data?.id)
|
||||||
if (!Strings.isBlank(data.id)) {
|
|
||||||
status.value = 'modify'
|
|
||||||
RoleApi.detail(data.id!)
|
|
||||||
.then(res => {
|
|
||||||
roleFormData.value = res.data
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
status.value = 'add'
|
|
||||||
roleFormData.value = data
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,51 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:left-tools="leftTools"
|
<template #highFormItem="formData">
|
||||||
:paging="paging">
|
|
||||||
<template #searchFormItem="{searchForm}">
|
|
||||||
<ElFormItem label="任务名称">
|
<ElFormItem label="任务名称">
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.taskName"
|
v-model="formData.taskName"
|
||||||
placeholder="任务名称"/>
|
placeholder="任务名称"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="任务执行函数">
|
<ElFormItem label="执行函数">
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.fn"
|
v-model="formData.fn"
|
||||||
placeholder="任务执行函数"/>
|
placeholder="执行函数"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="调度方式">
|
<ElFormItem label="调度方式">
|
||||||
<ElSelect
|
<ElSelect
|
||||||
v-model="searchForm.scheduleType"
|
v-model="formData.scheduleType"
|
||||||
clearable placeholder="请选择调度方式" style="width: 150px" @change="paging" @clear="paging">
|
clearable placeholder="请选择调度方式" @change="research" @clear="research">
|
||||||
<ElOption v-for="item in scheduleTypeList" :key="item.value" :label="item.label" :value="item.value"/>
|
<ElOption v-for="item in scheduleTypeList" :key="item.value" :label="item.label" :value="item.value"/>
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="内部任务">
|
|
||||||
<ElCheckbox
|
<ElFormItem v-if="!formData.builtin" label="状态">
|
||||||
@change="research"
|
<ElSelect v-model="formData.disabled" clearable placeholder="请选择状态" @clear="research">
|
||||||
v-model="searchForm.builtin"
|
|
||||||
placeholder="内部任务"/>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem v-if="!searchForm.builtin" label="状态">
|
|
||||||
<ElSelect v-model="searchForm.disabled" clearable placeholder="请选择状态" style="width: 150px" @clear="paging">
|
|
||||||
<ElOption :value="true" label="禁用"/>
|
<ElOption :value="true" label="禁用"/>
|
||||||
<ElOption :value="false" label="启用"/>
|
<ElOption :value="false" label="启用"/>
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template #simpleFormItem="formData">
|
||||||
|
<ElFormItem>
|
||||||
|
<ElSwitch v-model="formData.builtin"
|
||||||
|
active-text="系统任务"
|
||||||
|
inactive-text="用户任务"
|
||||||
|
@change="research"/>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem>
|
||||||
|
<ElInput
|
||||||
|
v-model="formData.taskName"
|
||||||
|
placeholder="任务名称"/>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem>
|
||||||
|
<ElInput
|
||||||
|
v-model="formData.fn"
|
||||||
|
placeholder="任务执行函数"/>
|
||||||
|
</ElFormItem>
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<ElTableColumn label="任务名称" prop="taskName"/>
|
<ElTableColumn label="任务名称" prop="taskName"/>
|
||||||
|
|
@ -53,129 +65,131 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="是否禁用" prop="disabled" width="100">
|
||||||
<ElTableColumn label="是否禁用" width="180">
|
<template #default="{row}">
|
||||||
<template #default="scope">
|
<ElSwitch v-model="row.disabled" :disabled="row.builtin" @change="disabledUserHandler($event,row.id)"/>
|
||||||
<span>
|
|
||||||
{{ scope.row.disabled ? '是' : '否' }}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
|
||||||
<ElTableColumn label="备注" prop="memo"/>
|
<ElTableColumn label="备注" prop="memo"/>
|
||||||
</template>
|
</template>
|
||||||
<TaskForm ref="taskForm" @edit-succ="research"/>
|
<TaskForm ref="taskForm" :research="research"/>
|
||||||
<ScheduleRecodePanel ref="scheduleRecodePanel"/>
|
<ScheduleRecodePanel ref="scheduleRecodePanel"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TaskApi from '@/pages/sys/task/task-api.ts'
|
import TaskApi from '@/pages/sys/task/task-api.ts'
|
||||||
import TaskForm from '@/pages/sys/task/TaskForm.vue'
|
import TaskForm from '@/pages/sys/task/TaskForm.vue'
|
||||||
import ScheduleRecodePanel from '@/pages/sys/task/schedule-recode/ScheduleRecodePanel.vue'
|
import ScheduleRecodePanel from '@/pages/sys/task/schedule-recode/ScheduleRecodePanel.vue'
|
||||||
import Times from '@/common/utils/times.ts'
|
import Times from '@/common/utils/times.ts'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
import { ElMessage } from 'element-plus'
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
|
||||||
|
|
||||||
function research() {
|
|
||||||
formPageIns.value?.doSearch()
|
|
||||||
}
|
|
||||||
|
|
||||||
const taskFormIns = useTemplateRef<InstanceType<typeof TaskForm>>('taskForm')
|
const taskFormIns = useTemplateRef<InstanceType<typeof TaskForm>>('taskForm')
|
||||||
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
|
const tablePageProps = buildTablePageProps<TaskTypes.SearchTaskParam, TaskTypes.SearchTaskResult>({
|
||||||
|
pageLayout: {
|
||||||
|
searchFormHeight: '64px',
|
||||||
|
},
|
||||||
|
searchForm: {
|
||||||
|
highForm: {
|
||||||
|
contentWidth: 200,
|
||||||
|
},
|
||||||
|
simpleForm: {
|
||||||
|
colCount: 3,
|
||||||
|
},
|
||||||
|
paging: TaskApi.paging,
|
||||||
|
},
|
||||||
|
toolBar: {
|
||||||
|
leftTools: [
|
||||||
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
taskFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
foldLimit: 4,
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '编辑',
|
||||||
|
icon: 'Edit',
|
||||||
|
type: 'success',
|
||||||
|
show({row}) {
|
||||||
|
return !row.builtin
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
taskFormIns.value?.open(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: '执行一次',
|
||||||
|
icon: 'putongzhihang',
|
||||||
|
type: 'primary',
|
||||||
|
show({row}) {
|
||||||
|
return !row.disabled
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
TaskApi.trigger(row.id!)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('已提交触发请求')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: '调度记录',
|
||||||
|
type: 'default',
|
||||||
|
icon: 'zhihangjilu',
|
||||||
|
action({row}) {
|
||||||
|
scheduleRecodePanelIns.value?.open(row.id!)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'Delete',
|
||||||
|
loading: false,
|
||||||
|
type: 'danger',
|
||||||
|
tooltip: '删除',
|
||||||
|
confirm: {
|
||||||
|
title: '是否删除当前数据',
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
this.loading = true
|
||||||
|
return TaskApi.del([ row.id! ])
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function disabledUserHandler(val: string | number | boolean, id: string) {
|
||||||
|
TaskApi.disable(id, val as boolean)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success(val ? '禁用成功' : '启用成功')
|
||||||
|
research()
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function research() {
|
||||||
|
tablePageIns.value?.doSearch()
|
||||||
|
}
|
||||||
|
|
||||||
const scheduleRecodePanelIns = useTemplateRef<InstanceType<typeof ScheduleRecodePanel>>('scheduleRecodePanel')
|
const scheduleRecodePanelIns = useTemplateRef<InstanceType<typeof ScheduleRecodePanel>>('scheduleRecodePanel')
|
||||||
const scheduleTypeList = [
|
const scheduleTypeList = [
|
||||||
{value: 'Manually', label: '手动'},
|
{value: 'Manually', label: '手动'},
|
||||||
{value: 'Fixed', label: '固定周期'},
|
{value: 'Fixed', label: '固定周期'},
|
||||||
{value: 'Cron', label: '自定义'},
|
{value: 'Cron', label: '自定义'},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
const actionColumn = reactive<ActionColumnType<TaskTypes.SearchTaskResult>>({
|
|
||||||
tableActions: [
|
|
||||||
{
|
|
||||||
tooltip: '编辑',
|
|
||||||
icon: 'Edit',
|
|
||||||
type: 'success',
|
|
||||||
show({row}) {
|
|
||||||
return !row.builtin
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
taskFormIns.value?.open(row)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tooltip({row}) {
|
|
||||||
return row.disabled ? '启用' : '禁用'
|
|
||||||
},
|
|
||||||
show({row}) {
|
|
||||||
return !row.builtin
|
|
||||||
},
|
|
||||||
icon: 'Edit',
|
|
||||||
action({row}) {
|
|
||||||
return TaskApi.disable(row.id!, !row.disabled!)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success(row.disabled ? '启用成功' : '禁用成功')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tooltip: '执行一次',
|
|
||||||
icon: 'Edit',
|
|
||||||
show({row}) {
|
|
||||||
return !row.disabled
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
TaskApi.trigger(row.id!)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('已提交触发请求')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tooltip: '调度记录',
|
|
||||||
icon: 'Edit',
|
|
||||||
action({row}) {
|
|
||||||
scheduleRecodePanelIns.value?.open(row.id!)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'Delete',
|
|
||||||
loading: false,
|
|
||||||
type: 'danger',
|
|
||||||
tooltip: '删除',
|
|
||||||
confirm: {
|
|
||||||
title: '是否删除当前数据',
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
this.loading = true
|
|
||||||
return TaskApi.del([ row.id! ])
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
const leftTools: ToolType[] = [
|
|
||||||
{
|
|
||||||
icon: 'Plus',
|
|
||||||
label: '新建',
|
|
||||||
action() {
|
|
||||||
taskFormIns.value?.open()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
function paging(param: TaskTypes.SearchTaskParam) {
|
|
||||||
return TaskApi.paging(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,62 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<AFormPanel
|
||||||
:close-on-click-modal="false"
|
ref="formPanel"
|
||||||
destroy-on-close width="25vw" @close="dialogCloseHandler">
|
v-bind="formPanelProps">
|
||||||
<ElForm :model="taskFormData" class="sys_task-form">
|
<template #default="formData">
|
||||||
<ElFormItem label="任务名称">
|
<div class="form-items">
|
||||||
<ElInput v-model="taskFormData.taskName" placeholder="任务名称"/>
|
<ElFormItem label="任务名称">
|
||||||
</ElFormItem>
|
<ElInput v-model="formData.taskName" placeholder="任务名称"/>
|
||||||
<ElFormItem label="任务执行函数">
|
</ElFormItem>
|
||||||
<ElSelect v-model="taskFormData.fn" placeholder="请选择任务执行函数">
|
<ElFormItem label="执行函数">
|
||||||
<ElOption v-for="item in fnList" :key="item.fn" :label="item.fn" :value="item.fn!"/>
|
<ElSelect v-model="formData.fn" placeholder="请选择任务执行函数">
|
||||||
</ElSelect>
|
<ElOption v-for="item in fnList" :key="item.fn" :label="item.fn" :value="item.fn!"/>
|
||||||
</ElFormItem>
|
</ElSelect>
|
||||||
<ElFormItem label="日志等级">
|
</ElFormItem>
|
||||||
<ElSelect v-model="taskFormData.logLevel" placeholder="请选择日志等级">
|
<ElFormItem label="日志等级">
|
||||||
<ElOption v-for="item in logLevelList" :key="item.value" :label="item.label" :value="item.value"/>
|
<ElSelect v-model="formData.logLevel" placeholder="请选择日志等级">
|
||||||
</ElSelect>
|
<ElOption v-for="item in logLevelList" :key="item.value" :label="item.label" :value="item.value"/>
|
||||||
</ElFormItem>
|
</ElSelect>
|
||||||
<ElFormItem label="调度方式">
|
</ElFormItem>
|
||||||
<ElSelect v-model="taskFormData.scheduleType" placeholder="请选择调度方式" @change="scheduleTypeChange">
|
<ElFormItem label="调度方式">
|
||||||
<ElOption v-for="item in scheduleTypeList" :key="item.value" :label="item.label" :value="item.value"/>
|
<ElSelect v-model="formData.scheduleType" placeholder="请选择调度方式">
|
||||||
</ElSelect>
|
<ElOption v-for="item in scheduleTypeList" :key="item.value" :label="item.label" :value="item.value"/>
|
||||||
</ElFormItem>
|
</ElSelect>
|
||||||
<ElFormItem v-if="taskFormData.scheduleType === 'Cron'" label="调度配置">
|
</ElFormItem>
|
||||||
<Cron v-model="taskFormData.scheduleConf" placeholder="调度配置"/>
|
<ElFormItem v-if="formData.scheduleType === 'Cron'" label="调度配置">
|
||||||
</ElFormItem>
|
<Cron v-model="formData.scheduleConf" placeholder="调度配置"/>
|
||||||
<ElFormItem v-else-if="taskFormData.scheduleType === 'Fixed'" label="调度配置">
|
</ElFormItem>
|
||||||
<ElInput v-model="taskFormData.scheduleConf" placeholder="调度配置">
|
<ElFormItem v-else-if="formData.scheduleType === 'Fixed'" label="调度配置">
|
||||||
<template #suffix>周期(秒)</template>
|
<ElInput v-model="formData.scheduleConf" placeholder="调度配置">
|
||||||
</ElInput>
|
<template #suffix>周期(秒)</template>
|
||||||
</ElFormItem>
|
</ElInput>
|
||||||
<ElFormItem label="是否禁用">
|
</ElFormItem>
|
||||||
<ElSwitch v-model="taskFormData.disabled" active-text="禁用" inactive-text="启用"/>
|
<ElFormItem label="是否禁用">
|
||||||
</ElFormItem>
|
<ElSwitch v-model="formData.disabled" active-text="禁用" inactive-text="启用"/>
|
||||||
<ElFormItem label="备注">
|
</ElFormItem>
|
||||||
<ElInput v-model="taskFormData.memo" placeholder="备注"/>
|
<ElFormItem label="备注">
|
||||||
</ElFormItem>
|
<ElInput v-model="formData.memo" placeholder="备注"/>
|
||||||
</ElForm>
|
</ElFormItem>
|
||||||
<template #footer>
|
</div>
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</AFormPanel>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TaskApi from '@/pages/sys/task/task-api.ts'
|
import TaskApi from '@/pages/sys/task/task-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import Cron from '@/pages/sys/task/cron/Cron.vue'
|
import Cron from '@/pages/sys/task/cron/Cron.vue'
|
||||||
|
import AFormPanel, {
|
||||||
|
type AFormPanelInstance,
|
||||||
|
buildFormPanelProps,
|
||||||
|
} from '@/components/a-form-panel/AFormPanel.tsx'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const props = withDefaults(defineProps<{
|
||||||
|
research?: () => void
|
||||||
|
}>(), {
|
||||||
|
research: () => {
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const status = ref<'add' | 'modify'>('add')
|
||||||
|
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
const scheduleTypeList = [
|
const scheduleTypeList = [
|
||||||
{value: 'Manually', label: '手动'},
|
{value: 'Manually', label: '手动'},
|
||||||
{value: 'Fixed', label: '固定周期'},
|
{value: 'Fixed', label: '固定周期'},
|
||||||
|
|
@ -61,73 +69,66 @@ const logLevelList = [
|
||||||
{value: 'ERROR', label: '错误'},
|
{value: 'ERROR', label: '错误'},
|
||||||
{value: 'OFF', label: '关闭'},
|
{value: 'OFF', label: '关闭'},
|
||||||
]
|
]
|
||||||
const showDialog = ref(false)
|
|
||||||
const submiting = ref(false)
|
|
||||||
const status = ref<'add' | 'view' | 'modify'>('add')
|
|
||||||
let taskFormData = ref<TaskTypes.SearchTaskResult>({})
|
|
||||||
const fnList = ref<TaskTypes.FnHandle[]>([])
|
const fnList = ref<TaskTypes.FnHandle[]>([])
|
||||||
|
const formPanelProps = buildFormPanelProps<TaskTypes.SearchTaskResult>({
|
||||||
function dialogCloseHandler() {
|
detailsLoader(id?: string) {
|
||||||
taskFormData.value = {}
|
if (Strings.isBlank(id)) {
|
||||||
}
|
status.value = 'add'
|
||||||
|
return Promise.resolve({
|
||||||
function scheduleTypeChange(val: string) {
|
scheduleConf: '* * * * * ?',
|
||||||
if (val === 'Manually') {
|
scheduleType: 'Manually',
|
||||||
taskFormData.value.scheduleConf = ''
|
logLevel: 'DEBUG',
|
||||||
} else if (val === 'Fixed') {
|
disabled: false,
|
||||||
taskFormData.value.scheduleConf = '1'
|
|
||||||
} else if (val === 'Cron') {
|
|
||||||
taskFormData.value.scheduleConf = '* * * * * ?'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitHandler() {
|
|
||||||
if (status.value === 'view') return
|
|
||||||
submiting.value = true
|
|
||||||
if (taskFormData.value.id != null) {
|
|
||||||
TaskApi.modify(taskFormData.value)
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
} else {
|
||||||
submiting.value = false
|
status.value = 'modify'
|
||||||
})
|
return TaskApi.detail(id!).then((res) => res.data)
|
||||||
} else {
|
}
|
||||||
TaskApi.add(taskFormData.value)
|
},
|
||||||
.then(() => {
|
doSubmit(data) {
|
||||||
ElMessage.success('添加成功')
|
if (status.value === 'add') {
|
||||||
emits('editSucc')
|
return TaskApi.add(data)
|
||||||
showDialog.value = false
|
.then(props.research)
|
||||||
})
|
} else {
|
||||||
.finally(() => {
|
return TaskApi.modify(data)
|
||||||
submiting.value = false
|
.then(props.research)
|
||||||
})
|
}
|
||||||
}
|
},
|
||||||
}
|
watchForm: {
|
||||||
|
formItems: [],
|
||||||
|
callback(formData) {
|
||||||
|
const val = formData.scheduleType
|
||||||
|
if (val === 'Manually') {
|
||||||
|
formData.scheduleConf = ''
|
||||||
|
} else if (val === 'Fixed') {
|
||||||
|
formData.scheduleConf = '1'
|
||||||
|
} else if (val === 'Cron') {
|
||||||
|
formData.scheduleConf = '* * * * * ?'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
watchEffect(() => {
|
||||||
|
formPanelProps.title = status.value === 'add' ? '新建任务' : '修改任务'
|
||||||
|
})
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open(data: TaskTypes.SearchTaskResult = {}) {
|
open(data?: TaskTypes.SearchTaskResult) {
|
||||||
showDialog.value = true
|
formPanelIns.value?.open(data?.id)
|
||||||
TaskApi.fn().then(res => {
|
TaskApi.fn().then(res => {
|
||||||
fnList.value = res.data
|
fnList.value = res.data
|
||||||
})
|
})
|
||||||
if (!Strings.isBlank(data.id)) {
|
|
||||||
status.value = 'modify'
|
|
||||||
TaskApi.detail(data.id!).then((res) => {
|
|
||||||
taskFormData.value = res.data
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
status.value = 'add'
|
|
||||||
data.scheduleConf = '* * * * * ?'
|
|
||||||
taskFormData.value = data
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.sys_task-form {
|
.form-items {
|
||||||
padding 20px
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-areas: "picture ." \
|
||||||
|
"picture .";
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { elIcons } from '@/common/element/element.ts'
|
import { elIcons } from '@/common/element/element.ts'
|
||||||
import CronPanel from '@/pages/sys/task/cron/cron-panel/CronPanel.vue'
|
import CronPanel from '@/pages/sys/task/cron/cron-panel/CronPanel.vue'
|
||||||
import { useCronStore } from '@/pages/sys/task/cron/cron-store.ts'
|
import { useCronStore } from '@/pages/sys/task/cron/cron-store.ts'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue?: string
|
modelValue?: string
|
||||||
|
|
@ -41,12 +42,11 @@ function openPanel() {
|
||||||
<ElButton :icon="elIcons.Timer" type="text" @click="openPanel"/>
|
<ElButton :icon="elIcons.Timer" type="text" @click="openPanel"/>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
title="配置面板"
|
title="配置面板"
|
||||||
:close-on-click-modal="false"
|
width="50vw">
|
||||||
destroy-on-close width="50vw">
|
|
||||||
<CronPanel/>
|
<CronPanel/>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
|
|
||||||
<div class="tool-bar">
|
<!-- <div class="tool-bar">
|
||||||
<ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm"/>
|
<ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm"/>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<ElTable v-loading="searching" :data="tableData"
|
<ElTable v-loading="searching" :data="tableData"
|
||||||
cell-class-name="table-cell"
|
cell-class-name="table-cell"
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
:closed="dialogCloseHandler"
|
||||||
destroy-on-close
|
|
||||||
width="80vw"
|
width="80vw"
|
||||||
@close="dialogCloseHandler">
|
title="执行日志">
|
||||||
<ExecuteLog :schedule-id="scheduleId"/>
|
<ExecuteLog :schedule-id="scheduleId"/>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<ElButton @click="showDialog = false">关闭</ElButton>
|
<ElButton @click="showDialog = false">关闭</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ExecuteLog from '@/pages/sys/task/execute-log/ExecuteLog.vue'
|
import ExecuteLog from '@/pages/sys/task/execute-log/ExecuteLog.vue'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
const scheduleId = ref<string>('')
|
const scheduleId = ref<string>('')
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@
|
||||||
<ElButton :icon="elIcons.Refresh" :loading="searching" @click="reset">重置</ElButton>
|
<ElButton :icon="elIcons.Refresh" :loading="searching" @click="reset">重置</ElButton>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
<div class="tool-bar">
|
<!-- <div class="tool-bar">
|
||||||
<ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm"/>
|
<ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm"/>
|
||||||
</div>
|
</div> -->
|
||||||
<ElTable v-loading="searching" :data="tableData"
|
<ElTable v-loading="searching" :data="tableData"
|
||||||
cell-class-name="table-cell"
|
cell-class-name="table-cell"
|
||||||
class="table-list"
|
class="table-list"
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
title="执行记录"
|
||||||
destroy-on-close
|
|
||||||
width="80vw">
|
width="80vw">
|
||||||
<ScheduleRecode :task-id="taskId"/>
|
<ScheduleRecode :task-id="taskId"/>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<ElButton @click="showDialog = false">关闭</ElButton>
|
<ElButton @click="showDialog = false">关闭</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ScheduleRecode from '@/pages/sys/task/schedule-recode/ScheduleRecode.vue'
|
import ScheduleRecode from '@/pages/sys/task/schedule-recode/ScheduleRecode.vue'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<ADialog v-model:show="showDialog"
|
||||||
:close-on-click-modal="false"
|
:closed="dialogCloseHandler"
|
||||||
@close="dialogCloseHandler"
|
title="分配角色" width="700px">
|
||||||
destroy-on-close
|
|
||||||
width="700">
|
|
||||||
<ElTransfer
|
<ElTransfer
|
||||||
v-model="rightValue"
|
v-model="rightValue"
|
||||||
:button-texts="['解绑', '绑定']"
|
:button-texts="['解绑', '绑定']"
|
||||||
|
|
@ -36,7 +34,7 @@
|
||||||
<ElButton @click="showDialog = false">取消</ElButton>
|
<ElButton @click="showDialog = false">取消</ElButton>
|
||||||
<ElButton :disabled="rightValue.length <= 0" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
<ElButton :disabled="rightValue.length <= 0" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ADialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RoleApi from '@/pages/sys/role/role-api.ts'
|
import RoleApi from '@/pages/sys/role/role-api.ts'
|
||||||
|
|
@ -46,6 +44,7 @@ import {
|
||||||
type TransferDataItem,
|
type TransferDataItem,
|
||||||
} from 'element-plus'
|
} from 'element-plus'
|
||||||
import UserApi from '@/pages/sys/user/user-api.ts'
|
import UserApi from '@/pages/sys/user/user-api.ts'
|
||||||
|
import ADialog from '@/components/a-dialog/ADialog.vue'
|
||||||
|
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
const submiting = ref(false)
|
const submiting = ref(false)
|
||||||
|
|
@ -60,6 +59,7 @@ function dialogCloseHandler() {
|
||||||
allRoles.value = []
|
allRoles.value = []
|
||||||
rightValue.value = []
|
rightValue.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterMethod(query: string, item: TransferDataItem) {
|
function filterMethod(query: string, item: TransferDataItem) {
|
||||||
return Strings.isBlank(query) || (item as RoleTypes.SearchRoleResult).roleCode!.includes(query) || (item as RoleTypes.SearchRoleResult).roleName!.includes(query)
|
return Strings.isBlank(query) || (item as RoleTypes.SearchRoleResult).roleCode!.includes(query) || (item as RoleTypes.SearchRoleResult).roleName!.includes(query)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<FormPage
|
<ATablePage
|
||||||
ref="formPage"
|
ref="tablePage"
|
||||||
:action-column="actionColumn"
|
v-bind="tablePageProps">
|
||||||
:left-tools="leftTools"
|
<template #simpleFormItem="formData">
|
||||||
:paging="paging">
|
<ElFormItem>
|
||||||
<template #searchFormItem="{searchForm}">
|
|
||||||
<ElFormItem label="姓名">
|
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.nickname"
|
v-model="formData.nickname"
|
||||||
placeholder="姓名"/>
|
placeholder="姓名"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="手机号">
|
<ElFormItem>
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="searchForm.phone"
|
v-model="formData.phone"
|
||||||
placeholder="手机号"/>
|
placeholder="手机号"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</template>
|
</template>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<ElTableColumn label="姓名" prop="nickname"/>
|
|
||||||
<ElTableColumn label="头像" prop="avatar" width="60">
|
<ElTableColumn label="头像" prop="avatar" width="60">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<ElImage :preview-src-list="Strings.isBlank(row.avatar)?[]:[AppApi.fileUrl(row.avatar)]" :src="Strings.isBlank(row.avatar)?Avatar:AppApi.fileUrl(row.avatar)" class="avatar" preview-teleported>
|
<ElImage :preview-src-list="Strings.isBlank(row.avatar)?[]:[AppApi.fileUrl(row.avatar)]" :src="Strings.isBlank(row.avatar)?Avatar:AppApi.fileUrl(row.avatar)" class="avatar" preview-teleported>
|
||||||
|
|
@ -29,27 +26,29 @@
|
||||||
</ElImage>
|
</ElImage>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
|
||||||
|
<ElTableColumn label="姓名" prop="nickname"/>
|
||||||
<ElTableColumn label="联系电话" prop="phone"/>
|
<ElTableColumn label="联系电话" prop="phone"/>
|
||||||
<ElTableColumn label="登录手机号" prop="account.phone"/>
|
<!-- <ElTableColumn label="登录手机号" prop="account.phone"/> -->
|
||||||
<ElTableColumn label="用户名" prop="account.username"/>
|
<ElTableColumn label="用户名" prop="account.username"/>
|
||||||
<ElTableColumn label="微信标识" prop="account.wechatOpenid"/>
|
<ElTableColumn label="微信标识" prop="account.wechatOpenid" width="180"/>
|
||||||
<ElTableColumn label="已授权客户端" prop="account.clientCode" width="110">
|
<ElTableColumn label="已授权客户端" prop="account.clientCode" width="130">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<ElCheckboxGroup v-model="row.account.clients" @change="clientChangeHandler($event,row)">
|
<ElCheckboxGroup v-model="row.account.clients" @change="clientChangeHandler($event,row)">
|
||||||
<ElCheckbox v-for="client in ClientUtil.clients" :key="client.val" :disabled="row.id == '1' && client.val === 1" :label="client.txt" :value="client.val"/>
|
<ElCheckbox v-for="client in ClientUtil.clients" :key="client.val" :disabled="row.id == '1' && client.val === 1" :label="client.txt" :value="client.val"/>
|
||||||
</ElCheckboxGroup>
|
</ElCheckboxGroup>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="是否禁用" prop="account.disabled">
|
<ElTableColumn label="是否禁用" prop="account.disabled" width="100">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<ElSwitch v-model="row.account.disabled" :disabled="row.id == '1'" @change="disabledUserHandler($event,row.id)"/>
|
<ElSwitch v-model="row.account.disabled" :disabled="row.id == '1'" @change="disabledUserHandler($event,row.id)"/>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="注册时间" prop="account.regdate" width="170"/>
|
<ElTableColumn label="注册时间" prop="account.regdate" width="180"/>
|
||||||
</template>
|
</template>
|
||||||
<UserForm ref="userForm" @edit-succ="paging"/>
|
<UserForm ref="userForm" :research="research"/>
|
||||||
<BindRole ref="bindRole"/>
|
<BindRole ref="bindRole"/>
|
||||||
</FormPage>
|
</ATablePage>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import UserApi from '@/pages/sys/user/user-api.ts'
|
import UserApi from '@/pages/sys/user/user-api.ts'
|
||||||
|
|
@ -63,19 +62,91 @@ import BindRole from '@/pages/sys/user/BindRole.vue'
|
||||||
import ClientUtil from '@/common/utils/client-util.ts'
|
import ClientUtil from '@/common/utils/client-util.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import Avatar from '@/assets/images/avatar.png'
|
import Avatar from '@/assets/images/avatar.png'
|
||||||
import FormPage from '@/components/page/FormPage.vue'
|
import ATablePage, {
|
||||||
import type {
|
type ATablePageInstance,
|
||||||
ActionColumnType,
|
buildTablePageProps,
|
||||||
ToolType,
|
} from '@/components/a-page/a-table-page/ATablePage.tsx'
|
||||||
} from '@/components/page/a-page-type.ts'
|
|
||||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
|
||||||
|
|
||||||
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
|
|
||||||
const userFormIns = useTemplateRef<InstanceType<typeof UserForm>>('userForm')
|
const userFormIns = useTemplateRef<InstanceType<typeof UserForm>>('userForm')
|
||||||
const bindRoleIns = useTemplateRef<InstanceType<typeof BindRole>>('bindRole')
|
const bindRoleIns = useTemplateRef<InstanceType<typeof BindRole>>('bindRole')
|
||||||
|
const tablePageIns = useTemplateRef<ATablePageInstance>('tablePage')
|
||||||
|
const tablePageProps = buildTablePageProps<UserTypes.SearchUserParam, UserTypes.SearchUserResult>({
|
||||||
|
pageLayout: {
|
||||||
|
enableHighForm: false,
|
||||||
|
},
|
||||||
|
searchForm: {
|
||||||
|
simpleForm: {
|
||||||
|
colCount: 2,
|
||||||
|
},
|
||||||
|
paging(param) {
|
||||||
|
return UserApi.paging(param)
|
||||||
|
.then(res => {
|
||||||
|
(res.data?.records ?? []).map(it => {
|
||||||
|
it.account.clients = ClientUtil.getClients(it.account.clientCode!).map(it => it.val)
|
||||||
|
return it
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
toolBar: {
|
||||||
|
leftTools: [
|
||||||
|
{
|
||||||
|
icon: 'Plus',
|
||||||
|
label: '新建',
|
||||||
|
action() {
|
||||||
|
userFormIns.value?.open()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
actionColumn: {
|
||||||
|
tableActions: [
|
||||||
|
{
|
||||||
|
tooltip: '编辑',
|
||||||
|
icon: 'Edit',
|
||||||
|
type: 'success',
|
||||||
|
action({row}) {
|
||||||
|
userFormIns.value?.open(row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: '权限',
|
||||||
|
icon: 'gongnengquanxian',
|
||||||
|
type: 'warning',
|
||||||
|
action({row}) {
|
||||||
|
bindRoleIns.value?.open(row.id!)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: '重置密码',
|
||||||
|
icon: 'zhongzhimima',
|
||||||
|
type: 'danger',
|
||||||
|
confirm: {
|
||||||
|
title: '确定重置密码?',
|
||||||
|
},
|
||||||
|
show({row}) {
|
||||||
|
return row.id != '1'
|
||||||
|
},
|
||||||
|
action({row}) {
|
||||||
|
if (row.id == '1') {
|
||||||
|
ElMessage.error('不能修改管理员')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UserApi.resetPasswd(row.id!)
|
||||||
|
.then((res) => {
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
function research() {
|
function research() {
|
||||||
formPageIns.value?.doSearch()
|
tablePageIns.value?.doSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
function clientChangeHandler(clients: CheckboxValueType[], data: UserTypes.SearchUserResult) {
|
function clientChangeHandler(clients: CheckboxValueType[], data: UserTypes.SearchUserResult) {
|
||||||
|
|
@ -98,62 +169,6 @@ function disabledUserHandler(val: string | number | boolean, id: string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionColumn = reactive<ActionColumnType<UserTypes.SearchUserResult>>({
|
|
||||||
tableActions: [
|
|
||||||
{
|
|
||||||
tooltip: '编辑',
|
|
||||||
icon: 'Edit',
|
|
||||||
type: 'success',
|
|
||||||
action({row}) {
|
|
||||||
userFormIns.value?.open(row)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tooltip: '权限',
|
|
||||||
icon: 'Edit',
|
|
||||||
action({row}) {
|
|
||||||
bindRoleIns.value?.open(row.id!)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tooltip: '重置密码',
|
|
||||||
icon: 'Edit',
|
|
||||||
show({row}) {
|
|
||||||
return row.id != '1'
|
|
||||||
},
|
|
||||||
action({row}) {
|
|
||||||
if (row.id == '1') {
|
|
||||||
ElMessage.error('不能修改管理员')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
UserApi.resetPasswd(row.id!)
|
|
||||||
.then((res) => {
|
|
||||||
ElMessage.success(res.msg)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
const leftTools: ToolType[] = [
|
|
||||||
{
|
|
||||||
icon: 'Plus',
|
|
||||||
label: '新建',
|
|
||||||
action() {
|
|
||||||
userFormIns.value?.open()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
function paging(param: UserTypes.SearchUserParam) {
|
|
||||||
return UserApi.paging(param)
|
|
||||||
.then(res => {
|
|
||||||
(res.data?.records ?? []).map(it => {
|
|
||||||
it.account.clients = ClientUtil.getClients(it.account.clientCode!).map(it => it.val)
|
|
||||||
return it
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.avatar {
|
.avatar {
|
||||||
|
|
|
||||||
|
|
@ -1,139 +1,130 @@
|
||||||
<template>
|
<template>
|
||||||
<ElDialog v-model="showDialog"
|
<AFormPanel
|
||||||
:close-on-click-modal="false"
|
ref="formPanel"
|
||||||
@close="dialogCloseHandler"
|
v-bind="formPanelProps">
|
||||||
destroy-on-close
|
<template #default="formData">
|
||||||
width="25vw">
|
<div class="form-items">
|
||||||
<ElForm :model="userFormData"
|
<ElFormItem label="头像">
|
||||||
class="sys_user-form"
|
<Uploader
|
||||||
>
|
ref="uploader"
|
||||||
<ElFormItem label="姓名">
|
v-model:file="formData.avatar"/>
|
||||||
<ElInput
|
</ElFormItem>
|
||||||
:readonly="userFormData.id=='1'"
|
<ElFormItem label="姓名">
|
||||||
v-model="userFormData.nickname"
|
<ElInput
|
||||||
|
v-model="formData.nickname"
|
||||||
placeholder="姓名"/>
|
:readonly="formData.id=='1'"
|
||||||
</ElFormItem>
|
placeholder="姓名"/>
|
||||||
<ElFormItem label="头像">
|
</ElFormItem>
|
||||||
<Uploader
|
<ElFormItem label="联系电话">
|
||||||
v-model:file="userFormData.avatar"
|
<ElInput
|
||||||
|
v-model="formData.phone"
|
||||||
:upload-props="{
|
placeholder="联系电话"/>
|
||||||
accept: 'image/*',
|
</ElFormItem>
|
||||||
listType:'picture'
|
<ElFormItem v-if="status === 'add'" label="用户名">
|
||||||
}">
|
<ElInput v-model="formData.account.username" placeholder="用户名"/>
|
||||||
<ElButton>点击上传头像</ElButton>
|
</ElFormItem>
|
||||||
</Uploader>
|
<ElFormItem v-if="status === 'add'" label="密码">
|
||||||
</ElFormItem>
|
<ElInput
|
||||||
<ElFormItem label="联系电话">
|
v-model="formData.account.secret"
|
||||||
<ElInput
|
autocomplete="new-password"
|
||||||
v-model="userFormData.phone"
|
placeholder="密码"
|
||||||
|
show-password
|
||||||
placeholder="联系电话"/>
|
type="password"/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem v-if="status === 'add'" label="用户名">
|
</div>
|
||||||
<ElInput
|
|
||||||
v-model="userFormData.account.username"
|
|
||||||
placeholder="用户名"/>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem v-if="status === 'add'" label="密码">
|
|
||||||
<ElInput
|
|
||||||
v-model="userFormData.account.secret"
|
|
||||||
autocomplete="new-password"
|
|
||||||
placeholder="密码"
|
|
||||||
show-password
|
|
||||||
type="password"/>
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
<template #footer>
|
|
||||||
<ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
|
|
||||||
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler">提交</ElButton>
|
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</AFormPanel>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import UserApi from '@/pages/sys/user/user-api.ts'
|
import UserApi from '@/pages/sys/user/user-api.ts'
|
||||||
import Strings from '@/common/utils/strings.ts'
|
import Strings from '@/common/utils/strings.ts'
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import Uploader from '@/components/uploader/Uploader.vue'
|
import Uploader from '@/components/uploader/Uploader.vue'
|
||||||
|
import AFormPanel, {
|
||||||
|
type AFormPanelInstance,
|
||||||
|
buildFormPanelProps,
|
||||||
|
} from '@/components/a-form-panel/AFormPanel.tsx'
|
||||||
|
|
||||||
const emits = defineEmits([ 'editSucc' ])
|
const props = withDefaults(defineProps<{
|
||||||
const showDialog = ref(false)
|
research?: () => void
|
||||||
const submiting = ref(false)
|
}>(), {
|
||||||
const status = ref<'add' | 'view' | 'modify'>('add')
|
research: () => {
|
||||||
const userFormData = ref<UserTypes.SearchUserResult>({
|
|
||||||
account: {
|
|
||||||
username: '',
|
|
||||||
secret: '',
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
|
||||||
|
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
|
||||||
|
|
||||||
function dialogCloseHandler() {
|
const status = ref<'add' | 'modify'>('add')
|
||||||
userFormData.value = {
|
|
||||||
account: {
|
|
||||||
username: '',
|
|
||||||
secret: '',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitHandler() {
|
const formPanelProps = buildFormPanelProps<UserTypes.SearchUserResult>({
|
||||||
if (status.value === 'view') return
|
detailsLoader(id?: string) {
|
||||||
submiting.value = true
|
if (Strings.isBlank(id)) {
|
||||||
if (userFormData.value.id != null) {
|
|
||||||
const {id, nickname, avatar, email, phone} = userFormData.value
|
|
||||||
UserApi.modify({id, nickname, avatar, email, phone})
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const {nickname, avatar, email, phone, account} = userFormData.value
|
|
||||||
UserApi.add({nickname, avatar, email, phone, account})
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
emits('editSucc')
|
|
||||||
showDialog.value = false
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
submiting.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open(data?: UserTypes.SearchUserResult) {
|
|
||||||
showDialog.value = true
|
|
||||||
if (data != null && !Strings.isBlank(data.id)) {
|
|
||||||
status.value = 'modify'
|
|
||||||
UserApi.detail(data.id!)
|
|
||||||
.then(res => {
|
|
||||||
userFormData.value = {
|
|
||||||
...res.data, account: {},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
status.value = 'add'
|
status.value = 'add'
|
||||||
userFormData.value = {
|
return Promise.resolve({
|
||||||
account: {
|
account: {
|
||||||
username: '',
|
username: '',
|
||||||
secret: '',
|
secret: '',
|
||||||
},
|
},
|
||||||
}
|
} as UserTypes.SearchUserResult)
|
||||||
|
} else {
|
||||||
|
status.value = 'modify'
|
||||||
|
return UserApi.detail(id!)
|
||||||
|
.then(res => {
|
||||||
|
if (res.data.avatar != null) uploaderIns.value?.setDefaultFiles([ res.data.avatar ])
|
||||||
|
return {
|
||||||
|
...res.data, account: {},
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
defaultFormData: {
|
||||||
|
account: {
|
||||||
|
username: '',
|
||||||
|
secret: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
doSubmit(data) {
|
||||||
|
if (status.value === 'add') {
|
||||||
|
const {nickname, avatar, email, phone, account} = data
|
||||||
|
return UserApi.add({nickname, avatar, email, phone, account})
|
||||||
|
.then(props.research)
|
||||||
|
} else {
|
||||||
|
const {id, nickname, avatar, email, phone} = data
|
||||||
|
return UserApi.modify({id, nickname, avatar, email, phone})
|
||||||
|
.then(props.research)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
watchEffect(() => {
|
||||||
|
formPanelProps.title = status.value === 'add' ? '新建用户' : '修改用户'
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open(data?: UserTypes.SearchUserResult) {
|
||||||
|
formPanelIns.value?.open(data?.id)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
.sys_user-form {
|
.form-items {
|
||||||
padding 20px
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
grid-template-areas: "picture ." \
|
||||||
|
"picture .";
|
||||||
|
|
||||||
.avatar-uploader {
|
:deep(.el-form-item) {
|
||||||
width 100%
|
&:first-child {
|
||||||
|
align-items: start;
|
||||||
|
grid-area: picture
|
||||||
|
max-width 300px
|
||||||
|
|
||||||
|
.el-form-item__content {
|
||||||
|
justify-content center
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item__error {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue