chore: 🔨 合并冲突解决
This commit is contained in:
@@ -30,8 +30,6 @@ const watermarkEnabled = computed(() => settingsStore.watermarkEnabled);
|
|||||||
|
|
||||||
// 明亮/暗黑主题水印字体颜色适配
|
// 明亮/暗黑主题水印字体颜色适配
|
||||||
const fontColor = computed(() => {
|
const fontColor = computed(() => {
|
||||||
return settingsStore.theme === ThemeEnum.DARK
|
return settingsStore.theme === ThemeEnum.DARK ? "rgba(255, 255, 255, .15)" : "rgba(0, 0, 0, .15)";
|
||||||
? "rgba(255, 255, 255, .15)"
|
|
||||||
: "rgba(0, 0, 0, .15)";
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-breadcrumb class="flex-y-center">
|
<el-breadcrumb class="flex-y-center">
|
||||||
<transition-group
|
<transition-group enter-active-class="animate__animated animate__fadeInRight">
|
||||||
enter-active-class="animate__animated animate__fadeInRight"
|
|
||||||
>
|
|
||||||
<el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
|
<el-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.path">
|
||||||
<span
|
<span
|
||||||
v-if="
|
v-if="item.redirect === 'noredirect' || index === breadcrumbs.length - 1"
|
||||||
item.redirect === 'noredirect' || index === breadcrumbs.length - 1
|
|
||||||
"
|
|
||||||
class="color-gray-400"
|
class="color-gray-400"
|
||||||
>
|
>
|
||||||
{{ translateRouteTitle(item.meta.title) }}
|
{{ translateRouteTitle(item.meta.title) }}
|
||||||
@@ -36,14 +32,10 @@ const pathCompile = (path: string) => {
|
|||||||
const breadcrumbs = ref<Array<RouteLocationMatched>>([]);
|
const breadcrumbs = ref<Array<RouteLocationMatched>>([]);
|
||||||
|
|
||||||
function getBreadcrumb() {
|
function getBreadcrumb() {
|
||||||
let matched = currentRoute.matched.filter(
|
let matched = currentRoute.matched.filter((item) => item.meta && item.meta.title);
|
||||||
(item) => item.meta && item.meta.title
|
|
||||||
);
|
|
||||||
const first = matched[0];
|
const first = matched[0];
|
||||||
if (!isDashboard(first)) {
|
if (!isDashboard(first)) {
|
||||||
matched = [
|
matched = [{ path: "/dashboard", meta: { title: "dashboard" } } as any].concat(matched);
|
||||||
{ path: "/dashboard", meta: { title: "dashboard" } } as any,
|
|
||||||
].concat(matched);
|
|
||||||
}
|
}
|
||||||
breadcrumbs.value = matched.filter((item) => {
|
breadcrumbs.value = matched.filter((item) => {
|
||||||
return item.meta && item.meta.title && item.meta.breadcrumb !== false;
|
return item.meta && item.meta.title && item.meta.breadcrumb !== false;
|
||||||
@@ -55,10 +47,7 @@ function isDashboard(route: RouteLocationMatched) {
|
|||||||
if (!name) {
|
if (!name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
return name.toString().trim().toLocaleLowerCase() === "Dashboard".toLocaleLowerCase();
|
||||||
name.toString().trim().toLocaleLowerCase() ===
|
|
||||||
"Dashboard".toLocaleLowerCase()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLink(item: any) {
|
function handleLink(item: any) {
|
||||||
|
|||||||
@@ -71,12 +71,7 @@
|
|||||||
<template v-if="typeof item === 'string'">
|
<template v-if="typeof item === 'string'">
|
||||||
<!-- 刷新 -->
|
<!-- 刷新 -->
|
||||||
<template v-if="item === 'refresh'">
|
<template v-if="item === 'refresh'">
|
||||||
<el-button
|
<el-button icon="refresh" circle title="刷新" @click="handleToolbar(item)" />
|
||||||
icon="refresh"
|
|
||||||
circle
|
|
||||||
title="刷新"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- 筛选列 -->
|
<!-- 筛选列 -->
|
||||||
<template v-else-if="item === 'filter'">
|
<template v-else-if="item === 'filter'">
|
||||||
@@ -86,11 +81,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-scrollbar max-height="350px">
|
<el-scrollbar max-height="350px">
|
||||||
<template v-for="col in cols" :key="col">
|
<template v-for="col in cols" :key="col">
|
||||||
<el-checkbox
|
<el-checkbox v-if="col.prop" v-model="col.show" :label="col.label" />
|
||||||
v-if="col.prop"
|
|
||||||
v-model="col.show"
|
|
||||||
:label="col.label"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
@@ -166,10 +157,7 @@
|
|||||||
<template v-if="col.templet === 'image'">
|
<template v-if="col.templet === 'image'">
|
||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<template v-if="Array.isArray(scope.row[col.prop])">
|
<template v-if="Array.isArray(scope.row[col.prop])">
|
||||||
<template
|
<template v-for="(item, index) in scope.row[col.prop]" :key="item">
|
||||||
v-for="(item, index) in scope.row[col.prop]"
|
|
||||||
:key="item"
|
|
||||||
>
|
|
||||||
<el-image
|
<el-image
|
||||||
:src="item"
|
:src="item"
|
||||||
:preview-src-list="scope.row[col.prop]"
|
:preview-src-list="scope.row[col.prop]"
|
||||||
@@ -198,11 +186,7 @@
|
|||||||
<!-- 格式化显示链接 -->
|
<!-- 格式化显示链接 -->
|
||||||
<template v-else-if="col.templet === 'url'">
|
<template v-else-if="col.templet === 'url'">
|
||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<el-link
|
<el-link type="primary" :href="scope.row[col.prop]" target="_blank">
|
||||||
type="primary"
|
|
||||||
:href="scope.row[col.prop]"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{{ scope.row[col.prop] }}
|
{{ scope.row[col.prop] }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</template>
|
</template>
|
||||||
@@ -221,8 +205,7 @@
|
|||||||
:validate-event="false"
|
:validate-event="false"
|
||||||
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)"
|
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)"
|
||||||
@change="
|
@change="
|
||||||
pageData.length > 0 &&
|
pageData.length > 0 && handleModify(col.prop, scope.row[col.prop], scope.row)
|
||||||
handleModify(col.prop, scope.row[col.prop], scope.row)
|
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -253,9 +236,7 @@
|
|||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<template v-if="scope.row[col.prop].startsWith('el-icon-')">
|
<template v-if="scope.row[col.prop].startsWith('el-icon-')">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<component
|
<component :is="scope.row[col.prop].replace('el-icon-', '')" />
|
||||||
:is="scope.row[col.prop].replace('el-icon-', '')"
|
|
||||||
/>
|
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -268,20 +249,15 @@
|
|||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
{{
|
{{
|
||||||
scope.row[col.prop]
|
scope.row[col.prop]
|
||||||
? useDateFormat(
|
? useDateFormat(scope.row[col.prop], col.dateFormat ?? "YYYY-MM-DD HH:mm:ss")
|
||||||
scope.row[col.prop],
|
.value
|
||||||
col.dateFormat ?? "YYYY-MM-DD HH:mm:ss"
|
|
||||||
).value
|
|
||||||
: ""
|
: ""
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 列操作栏 -->
|
<!-- 列操作栏 -->
|
||||||
<template v-else-if="col.templet === 'tool'">
|
<template v-else-if="col.templet === 'tool'">
|
||||||
<template
|
<template v-for="item in col.operat ?? ['edit', 'delete']" :key="item">
|
||||||
v-for="item in col.operat ?? ['edit', 'delete']"
|
|
||||||
:key="item"
|
|
||||||
>
|
|
||||||
<template v-if="typeof item === 'string'">
|
<template v-if="typeof item === 'string'">
|
||||||
<!-- 编辑/删除 -->
|
<!-- 编辑/删除 -->
|
||||||
<template v-if="item === 'edit' || item === 'delete'">
|
<template v-if="item === 'edit' || item === 'delete'">
|
||||||
@@ -329,11 +305,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 自定义 -->
|
<!-- 自定义 -->
|
||||||
<template v-else-if="col.templet === 'custom'">
|
<template v-else-if="col.templet === 'custom'">
|
||||||
<slot
|
<slot :name="col.slotName ?? col.prop" :prop="col.prop" v-bind="scope" />
|
||||||
:name="col.slotName ?? col.prop"
|
|
||||||
:prop="col.prop"
|
|
||||||
v-bind="scope"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -378,10 +350,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据源" prop="origin">
|
<el-form-item label="数据源" prop="origin">
|
||||||
<el-select v-model="exportsFormData.origin">
|
<el-select v-model="exportsFormData.origin">
|
||||||
<el-option
|
<el-option label="当前数据 (当前页的数据)" :value="ExportsOriginEnum.CURRENT" />
|
||||||
label="当前数据 (当前页的数据)"
|
|
||||||
:value="ExportsOriginEnum.CURRENT"
|
|
||||||
/>
|
|
||||||
<el-option
|
<el-option
|
||||||
label="选中数据 (所有选中的数据)"
|
label="选中数据 (所有选中的数据)"
|
||||||
:value="ExportsOriginEnum.SELECTED"
|
:value="ExportsOriginEnum.SELECTED"
|
||||||
@@ -397,11 +366,7 @@
|
|||||||
<el-form-item label="字段" prop="fields">
|
<el-form-item label="字段" prop="fields">
|
||||||
<el-checkbox-group v-model="exportsFormData.fields">
|
<el-checkbox-group v-model="exportsFormData.fields">
|
||||||
<template v-for="col in cols" :key="col">
|
<template v-for="col in cols" :key="col">
|
||||||
<el-checkbox
|
<el-checkbox v-if="col.prop" :value="col.prop" :label="col.label" />
|
||||||
v-if="col.prop"
|
|
||||||
:value="col.prop"
|
|
||||||
:label="col.label"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -410,9 +375,7 @@
|
|||||||
<!-- 弹窗底部操作按钮 -->
|
<!-- 弹窗底部操作按钮 -->
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="padding-right: var(--el-dialog-padding-primary)">
|
<div style="padding-right: var(--el-dialog-padding-primary)">
|
||||||
<el-button type="primary" @click="handleExportsSubmit">
|
<el-button type="primary" @click="handleExportsSubmit">确 定</el-button>
|
||||||
确 定
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleCloseExportsModal">取 消</el-button>
|
<el-button @click="handleCloseExportsModal">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -524,10 +487,7 @@ const pk = props.contentConfig.pk ?? "id";
|
|||||||
// 表格左侧工具栏
|
// 表格左侧工具栏
|
||||||
const toolbar = props.contentConfig.toolbar ?? ["add", "delete"];
|
const toolbar = props.contentConfig.toolbar ?? ["add", "delete"];
|
||||||
// 表格右侧工具栏
|
// 表格右侧工具栏
|
||||||
const defaultToolbar = props.contentConfig.defaultToolbar ?? [
|
const defaultToolbar = props.contentConfig.defaultToolbar ?? ["refresh", "filter"];
|
||||||
"refresh",
|
|
||||||
"filter",
|
|
||||||
];
|
|
||||||
// 表格列
|
// 表格列
|
||||||
const cols = ref(
|
const cols = ref(
|
||||||
props.contentConfig.cols.map((col) => {
|
props.contentConfig.cols.map((col) => {
|
||||||
@@ -535,11 +495,7 @@ const cols = ref(
|
|||||||
if (col.show === undefined) {
|
if (col.show === undefined) {
|
||||||
col.show = true;
|
col.show = true;
|
||||||
}
|
}
|
||||||
if (
|
if (col.prop !== undefined && col.columnKey === undefined && col["column-key"] === undefined) {
|
||||||
col.prop !== undefined &&
|
|
||||||
col.columnKey === undefined &&
|
|
||||||
col["column-key"] === undefined
|
|
||||||
) {
|
|
||||||
col.columnKey = col.prop;
|
col.columnKey = col.prop;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -672,9 +628,7 @@ function handleExports() {
|
|||||||
const filename = exportsFormData.filename
|
const filename = exportsFormData.filename
|
||||||
? exportsFormData.filename
|
? exportsFormData.filename
|
||||||
: props.contentConfig.pageName;
|
: props.contentConfig.pageName;
|
||||||
const sheetname = exportsFormData.sheetname
|
const sheetname = exportsFormData.sheetname ? exportsFormData.sheetname : "sheet";
|
||||||
? exportsFormData.sheetname
|
|
||||||
: "sheet";
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
const workbook = new ExcelJS.Workbook();
|
||||||
const worksheet = workbook.addWorksheet(sheetname);
|
const worksheet = workbook.addWorksheet(sheetname);
|
||||||
const columns: Partial<ExcelJS.Column>[] = [];
|
const columns: Partial<ExcelJS.Column>[] = [];
|
||||||
@@ -700,9 +654,7 @@ function handleExports() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
worksheet.addRows(
|
worksheet.addRows(
|
||||||
exportsFormData.origin === ExportsOriginEnum.SELECTED
|
exportsFormData.origin === ExportsOriginEnum.SELECTED ? selectionData.value : pageData.value
|
||||||
? selectionData.value
|
|
||||||
: pageData.value
|
|
||||||
);
|
);
|
||||||
workbook.xlsx
|
workbook.xlsx
|
||||||
.writeBuffer()
|
.writeBuffer()
|
||||||
@@ -821,11 +773,7 @@ function handleImports() {
|
|||||||
fields.push(cell.value);
|
fields.push(cell.value);
|
||||||
});
|
});
|
||||||
// 遍历工作表的每一行(从第二行开始,因为第一行通常是标题行)
|
// 遍历工作表的每一行(从第二行开始,因为第一行通常是标题行)
|
||||||
for (
|
for (let rowNumber = 2; rowNumber <= worksheet.rowCount; rowNumber++) {
|
||||||
let rowNumber = 2;
|
|
||||||
rowNumber <= worksheet.rowCount;
|
|
||||||
rowNumber++
|
|
||||||
) {
|
|
||||||
const rowData: IObject = {};
|
const rowData: IObject = {};
|
||||||
const row = worksheet.getRow(rowNumber);
|
const row = worksheet.getRow(rowNumber);
|
||||||
// 遍历当前行的每个单元格
|
// 遍历当前行的每个单元格
|
||||||
@@ -903,11 +851,7 @@ function handleOperat(data: IOperatData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 属性修改
|
// 属性修改
|
||||||
function handleModify(
|
function handleModify(field: string, value: boolean | string | number, row: Record<string, any>) {
|
||||||
field: string,
|
|
||||||
value: boolean | string | number,
|
|
||||||
row: Record<string, any>
|
|
||||||
) {
|
|
||||||
if (props.contentConfig.modifyAction) {
|
if (props.contentConfig.modifyAction) {
|
||||||
props.contentConfig.modifyAction({
|
props.contentConfig.modifyAction({
|
||||||
[pk]: row[pk],
|
[pk]: row[pk],
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form ref="formRef" label-width="auto" v-bind="form" :model="formData" :rules="formRules">
|
||||||
ref="formRef"
|
|
||||||
label-width="auto"
|
|
||||||
v-bind="form"
|
|
||||||
:model="formData"
|
|
||||||
:rules="formRules"
|
|
||||||
>
|
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<template v-for="item in formItems" :key="item.prop">
|
<template v-for="item in formItems" :key="item.prop">
|
||||||
<el-col v-show="!item.hidden" v-bind="item.col">
|
<el-col v-show="!item.hidden" v-bind="item.col">
|
||||||
@@ -48,10 +42,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- Checkbox 多选框 -->
|
<!-- Checkbox 多选框 -->
|
||||||
<template v-else-if="item.type === 'checkbox'">
|
<template v-else-if="item.type === 'checkbox'">
|
||||||
<el-checkbox-group
|
<el-checkbox-group v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template v-for="option in item.options" :key="option.value">
|
<template v-for="option in item.options" :key="option.value">
|
||||||
<el-checkbox v-bind="option" />
|
<el-checkbox v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
@@ -59,24 +50,15 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- Input Number 数字输入框 -->
|
<!-- Input Number 数字输入框 -->
|
||||||
<template v-else-if="item.type === 'input-number'">
|
<template v-else-if="item.type === 'input-number'">
|
||||||
<el-input-number
|
<el-input-number v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- TreeSelect 树形选择 -->
|
<!-- TreeSelect 树形选择 -->
|
||||||
<template v-else-if="item.type === 'tree-select'">
|
<template v-else-if="item.type === 'tree-select'">
|
||||||
<el-tree-select
|
<el-tree-select v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- DatePicker 日期选择器 -->
|
<!-- DatePicker 日期选择器 -->
|
||||||
<template v-else-if="item.type === 'date-picker'">
|
<template v-else-if="item.type === 'date-picker'">
|
||||||
<el-date-picker
|
<el-date-picker v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Text 文本 -->
|
<!-- Text 文本 -->
|
||||||
<template v-else-if="item.type === 'text'">
|
<template v-else-if="item.type === 'text'">
|
||||||
|
|||||||
@@ -36,78 +36,48 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<!-- Input 输入框 -->
|
<!-- Input 输入框 -->
|
||||||
<template
|
<template v-if="item.type === 'input' || item.type === undefined">
|
||||||
v-if="item.type === 'input' || item.type === undefined"
|
|
||||||
>
|
|
||||||
<el-input v-model="formData[item.prop]" v-bind="item.attrs" />
|
<el-input v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
</template>
|
</template>
|
||||||
<!-- Select 选择器 -->
|
<!-- Select 选择器 -->
|
||||||
<template v-else-if="item.type === 'select'">
|
<template v-else-if="item.type === 'select'">
|
||||||
<el-select v-model="formData[item.prop]" v-bind="item.attrs">
|
<el-select v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
<template
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-option v-bind="option" />
|
<el-option v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<!-- Radio 单选框 -->
|
<!-- Radio 单选框 -->
|
||||||
<template v-else-if="item.type === 'radio'">
|
<template v-else-if="item.type === 'radio'">
|
||||||
<el-radio-group
|
<el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-radio v-bind="option" />
|
<el-radio v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</template>
|
</template>
|
||||||
<!-- switch 开关 -->
|
<!-- switch 开关 -->
|
||||||
<template v-else-if="item.type === 'switch'">
|
<template v-else-if="item.type === 'switch'">
|
||||||
<el-switch
|
<el-switch v-model="formData[item.prop]" inline-prompt v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
inline-prompt
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Checkbox 多选框 -->
|
<!-- Checkbox 多选框 -->
|
||||||
<template v-else-if="item.type === 'checkbox'">
|
<template v-else-if="item.type === 'checkbox'">
|
||||||
<el-checkbox-group
|
<el-checkbox-group v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-checkbox v-bind="option" />
|
<el-checkbox v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</template>
|
</template>
|
||||||
<!-- Input Number 数字输入框 -->
|
<!-- Input Number 数字输入框 -->
|
||||||
<template v-else-if="item.type === 'input-number'">
|
<template v-else-if="item.type === 'input-number'">
|
||||||
<el-input-number
|
<el-input-number v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- TreeSelect 树形选择 -->
|
<!-- TreeSelect 树形选择 -->
|
||||||
<template v-else-if="item.type === 'tree-select'">
|
<template v-else-if="item.type === 'tree-select'">
|
||||||
<el-tree-select
|
<el-tree-select v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- DatePicker 日期选择器 -->
|
<!-- DatePicker 日期选择器 -->
|
||||||
<template v-else-if="item.type === 'date-picker'">
|
<template v-else-if="item.type === 'date-picker'">
|
||||||
<el-date-picker
|
<el-date-picker v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Text 文本 -->
|
<!-- Text 文本 -->
|
||||||
<template v-else-if="item.type === 'text'">
|
<template v-else-if="item.type === 'text'">
|
||||||
@@ -181,84 +151,48 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<!-- Input 输入框 -->
|
<!-- Input 输入框 -->
|
||||||
<template
|
<template v-if="item.type === 'input' || item.type === undefined">
|
||||||
v-if="item.type === 'input' || item.type === undefined"
|
<el-input v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Select 选择器 -->
|
<!-- Select 选择器 -->
|
||||||
<template v-else-if="item.type === 'select'">
|
<template v-else-if="item.type === 'select'">
|
||||||
<el-select
|
<el-select v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-option v-bind="option" />
|
<el-option v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<!-- Radio 单选框 -->
|
<!-- Radio 单选框 -->
|
||||||
<template v-else-if="item.type === 'radio'">
|
<template v-else-if="item.type === 'radio'">
|
||||||
<el-radio-group
|
<el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-radio v-bind="option" />
|
<el-radio v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</template>
|
</template>
|
||||||
<!-- switch 开关 -->
|
<!-- switch 开关 -->
|
||||||
<template v-else-if="item.type === 'switch'">
|
<template v-else-if="item.type === 'switch'">
|
||||||
<el-switch
|
<el-switch v-model="formData[item.prop]" inline-prompt v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
inline-prompt
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Checkbox 多选框 -->
|
<!-- Checkbox 多选框 -->
|
||||||
<template v-else-if="item.type === 'checkbox'">
|
<template v-else-if="item.type === 'checkbox'">
|
||||||
<el-checkbox-group
|
<el-checkbox-group v-model="formData[item.prop]" v-bind="item.attrs">
|
||||||
v-model="formData[item.prop]"
|
<template v-for="option in item.options" :key="option.value">
|
||||||
v-bind="item.attrs"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-for="option in item.options"
|
|
||||||
:key="option.value"
|
|
||||||
>
|
|
||||||
<el-checkbox v-bind="option" />
|
<el-checkbox v-bind="option" />
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</template>
|
</template>
|
||||||
<!-- Input Number 数字输入框 -->
|
<!-- Input Number 数字输入框 -->
|
||||||
<template v-else-if="item.type === 'input-number'">
|
<template v-else-if="item.type === 'input-number'">
|
||||||
<el-input-number
|
<el-input-number v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- TreeSelect 树形选择 -->
|
<!-- TreeSelect 树形选择 -->
|
||||||
<template v-else-if="item.type === 'tree-select'">
|
<template v-else-if="item.type === 'tree-select'">
|
||||||
<el-tree-select
|
<el-tree-select v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- DatePicker 日期选择器 -->
|
<!-- DatePicker 日期选择器 -->
|
||||||
<template v-else-if="item.type === 'date-picker'">
|
<template v-else-if="item.type === 'date-picker'">
|
||||||
<el-date-picker
|
<el-date-picker v-model="formData[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="formData[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Text 文本 -->
|
<!-- Text 文本 -->
|
||||||
<template v-else-if="item.type === 'text'">
|
<template v-else-if="item.type === 'text'">
|
||||||
|
|||||||
@@ -51,9 +51,7 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
<template v-if="inputTagMap[item.prop].inputVisible">
|
<template v-if="inputTagMap[item.prop].inputVisible">
|
||||||
<el-input
|
<el-input
|
||||||
:ref="
|
:ref="(el: HTMLElement) => (inputTagMap[item.prop].inputRef = el)"
|
||||||
(el: HTMLElement) => (inputTagMap[item.prop].inputRef = el)
|
|
||||||
"
|
|
||||||
v-model="inputTagMap[item.prop].inputValue"
|
v-model="inputTagMap[item.prop].inputValue"
|
||||||
v-bind="inputTagMap[item.prop].inputAttrs"
|
v-bind="inputTagMap[item.prop].inputAttrs"
|
||||||
@keyup.enter="handleInputConfirm(item.prop)"
|
@keyup.enter="handleInputConfirm(item.prop)"
|
||||||
@@ -80,24 +78,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- TreeSelect 树形选择 -->
|
<!-- TreeSelect 树形选择 -->
|
||||||
<template v-else-if="item.type === 'tree-select'">
|
<template v-else-if="item.type === 'tree-select'">
|
||||||
<el-tree-select
|
<el-tree-select v-model="queryParams[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="queryParams[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- DatePicker 日期选择器 -->
|
<!-- DatePicker 日期选择器 -->
|
||||||
<template v-else-if="item.type === 'date-picker'">
|
<template v-else-if="item.type === 'date-picker'">
|
||||||
<el-date-picker
|
<el-date-picker v-model="queryParams[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="queryParams[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="search" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="refresh" @click="handleReset">重置</el-button>
|
<el-button icon="refresh" @click="handleReset">重置</el-button>
|
||||||
<!-- 展开/收起 -->
|
<!-- 展开/收起 -->
|
||||||
<el-link
|
<el-link
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import type {
|
import type { IObject, PageContentInstance, PageModalInstance, PageSearchInstance } from "./types";
|
||||||
IObject,
|
|
||||||
PageContentInstance,
|
|
||||||
PageModalInstance,
|
|
||||||
PageSearchInstance,
|
|
||||||
} from "./types";
|
|
||||||
|
|
||||||
function usePage() {
|
function usePage() {
|
||||||
const searchRef = ref<PageSearchInstance>();
|
const searchRef = ref<PageSearchInstance>();
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const label = ref("");
|
const label = ref("");
|
||||||
const tagType = ref<
|
const tagType = ref<"success" | "warning" | "info" | "primary" | "danger" | undefined>();
|
||||||
"success" | "warning" | "info" | "primary" | "danger" | undefined
|
|
||||||
>();
|
|
||||||
|
|
||||||
const tagSize = ref(props.size as "default" | "large" | "small");
|
const tagSize = ref(props.size as "default" | "large" | "small");
|
||||||
|
|
||||||
@@ -41,18 +39,9 @@ const getLabelAndTagByValue = async (dictCode: string, value: any) => {
|
|||||||
|
|
||||||
// 监听 props 的变化,获取并更新 label 和 tag
|
// 监听 props 的变化,获取并更新 label 和 tag
|
||||||
const fetchLabelAndTag = async () => {
|
const fetchLabelAndTag = async () => {
|
||||||
const result = await getLabelAndTagByValue(
|
const result = await getLabelAndTagByValue(props.code as string, props.modelValue);
|
||||||
props.code as string,
|
|
||||||
props.modelValue
|
|
||||||
);
|
|
||||||
label.value = result.label;
|
label.value = result.label;
|
||||||
tagType.value = result.tag as
|
tagType.value = result.tag as "success" | "warning" | "info" | "primary" | "danger" | undefined;
|
||||||
| "success"
|
|
||||||
| "warning"
|
|
||||||
| "info"
|
|
||||||
| "primary"
|
|
||||||
| "danger"
|
|
||||||
| undefined;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 首次挂载时获取字典数据
|
// 首次挂载时获取字典数据
|
||||||
|
|||||||
@@ -68,8 +68,7 @@ const props = defineProps({
|
|||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "select",
|
default: "select",
|
||||||
validator: (value: string) =>
|
validator: (value: string) => ["select", "radio", "checkbox"].includes(value),
|
||||||
["select", "radio", "checkbox"].includes(value),
|
|
||||||
},
|
},
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -120,9 +119,7 @@ watch(
|
|||||||
(newOptions) => {
|
(newOptions) => {
|
||||||
// options 加载后,确保 selectedValue 可以正确匹配到 options
|
// options 加载后,确保 selectedValue 可以正确匹配到 options
|
||||||
if (newOptions.length > 0 && selectedValue.value !== undefined) {
|
if (newOptions.length > 0 && selectedValue.value !== undefined) {
|
||||||
const matchedOption = newOptions.find(
|
const matchedOption = newOptions.find((option) => option.value === selectedValue.value);
|
||||||
(option) => option.value === selectedValue.value
|
|
||||||
);
|
|
||||||
if (!matchedOption && props.type !== "checkbox") {
|
if (!matchedOption && props.type !== "checkbox") {
|
||||||
// 如果找不到匹配项,清空选中
|
// 如果找不到匹配项,清空选中
|
||||||
selectedValue.value = "";
|
selectedValue.value = "";
|
||||||
|
|||||||
@@ -4,10 +4,7 @@
|
|||||||
class="px-[15px] flex items-center justify-center color-[var(--el-text-color-regular)]"
|
class="px-[15px] flex items-center justify-center color-[var(--el-text-color-regular)]"
|
||||||
@click="toggleClick"
|
@click="toggleClick"
|
||||||
>
|
>
|
||||||
<svg-icon
|
<svg-icon icon-class="collapse" :class="{ hamburger: true, 'is-active': isActive }" />
|
||||||
icon-class="collapse"
|
|
||||||
:class="{ hamburger: true, 'is-active': isActive }"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="iconSelectRef" :style="{ width: props.width }">
|
<div ref="iconSelectRef" :style="{ width: props.width }">
|
||||||
<el-popover
|
<el-popover :visible="popoverVisible" :width="props.width" placement="bottom-end">
|
||||||
:visible="popoverVisible"
|
|
||||||
:width="props.width"
|
|
||||||
placement="bottom-end"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<div @click="popoverVisible = !popoverVisible">
|
<div @click="popoverVisible = !popoverVisible">
|
||||||
<slot>
|
<slot>
|
||||||
<el-input
|
<el-input v-model="selectedIcon" readonly placeholder="点击选择图标" class="reference">
|
||||||
v-model="selectedIcon"
|
|
||||||
readonly
|
|
||||||
placeholder="点击选择图标"
|
|
||||||
class="reference"
|
|
||||||
>
|
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<!-- 根据图标类型展示 -->
|
<!-- 根据图标类型展示 -->
|
||||||
<el-icon v-if="isElementIcon">
|
<el-icon v-if="isElementIcon">
|
||||||
@@ -49,12 +40,7 @@
|
|||||||
|
|
||||||
<!-- 图标选择弹窗 -->
|
<!-- 图标选择弹窗 -->
|
||||||
<div ref="popoverContentRef">
|
<div ref="popoverContentRef">
|
||||||
<el-input
|
<el-input v-model="filterText" placeholder="搜索图标" clearable @input="filterIcons" />
|
||||||
v-model="filterText"
|
|
||||||
placeholder="搜索图标"
|
|
||||||
clearable
|
|
||||||
@input="filterIcons"
|
|
||||||
/>
|
|
||||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||||
<el-tab-pane label="SVG 图标" name="svg">
|
<el-tab-pane label="SVG 图标" name="svg">
|
||||||
<el-scrollbar height="300px">
|
<el-scrollbar height="300px">
|
||||||
@@ -147,9 +133,7 @@ function handleTabClick(tabPane: any) {
|
|||||||
function filterIcons() {
|
function filterIcons() {
|
||||||
if (activeTab.value === "svg") {
|
if (activeTab.value === "svg") {
|
||||||
filteredSvgIcons.value = filterText.value
|
filteredSvgIcons.value = filterText.value
|
||||||
? svgIcons.value.filter((icon) =>
|
? svgIcons.value.filter((icon) => icon.toLowerCase().includes(filterText.value.toLowerCase()))
|
||||||
icon.toLowerCase().includes(filterText.value.toLowerCase())
|
|
||||||
)
|
|
||||||
: svgIcons.value;
|
: svgIcons.value;
|
||||||
} else {
|
} else {
|
||||||
filteredElementIcons.value = filterText.value
|
filteredElementIcons.value = filterText.value
|
||||||
@@ -184,9 +168,7 @@ function clearSelectedIcon() {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadIcons();
|
loadIcons();
|
||||||
if (selectedIcon.value) {
|
if (selectedIcon.value) {
|
||||||
if (
|
if (elementIcons.value.includes(selectedIcon.value.replace("el-icon-", ""))) {
|
||||||
elementIcons.value.includes(selectedIcon.value.replace("el-icon-", ""))
|
|
||||||
) {
|
|
||||||
activeTab.value = "element";
|
activeTab.value = "element";
|
||||||
} else {
|
} else {
|
||||||
activeTab.value = "svg";
|
activeTab.value = "svg";
|
||||||
|
|||||||
@@ -130,14 +130,10 @@ function navigateResults(direction: string) {
|
|||||||
|
|
||||||
if (direction === "up") {
|
if (direction === "up") {
|
||||||
activeIndex.value =
|
activeIndex.value =
|
||||||
activeIndex.value <= 0
|
activeIndex.value <= 0 ? displayResults.value.length - 1 : activeIndex.value - 1;
|
||||||
? displayResults.value.length - 1
|
|
||||||
: activeIndex.value - 1;
|
|
||||||
} else if (direction === "down") {
|
} else if (direction === "down") {
|
||||||
activeIndex.value =
|
activeIndex.value =
|
||||||
activeIndex.value >= displayResults.value.length - 1
|
activeIndex.value >= displayResults.value.length - 1 ? 0 : activeIndex.value + 1;
|
||||||
? 0
|
|
||||||
: activeIndex.value + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,24 +149,19 @@ function navigateToRoute(item: SearchItem) {
|
|||||||
|
|
||||||
function loadRoutes(routes: RouteRecordRaw[], parentPath = "") {
|
function loadRoutes(routes: RouteRecordRaw[], parentPath = "") {
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
const path = route.path.startsWith("/")
|
const path = route.path.startsWith("/") ? route.path : `${parentPath}/${route.path}`;
|
||||||
? route.path
|
if (excludedRoutes.value.includes(route.path) || isExternal(route.path)) return;
|
||||||
: `${parentPath}/${route.path}`;
|
|
||||||
if (excludedRoutes.value.includes(route.path) || isExternal(route.path))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (route.children) {
|
if (route.children) {
|
||||||
loadRoutes(route.children, path);
|
loadRoutes(route.children, path);
|
||||||
} else if (route.meta?.title) {
|
} else if (route.meta?.title) {
|
||||||
const title =
|
const title = route.meta.title === "dashboard" ? "首页" : route.meta.title;
|
||||||
route.meta.title === "dashboard" ? "首页" : route.meta.title;
|
|
||||||
menuItems.value.push({
|
menuItems.value.push({
|
||||||
title,
|
title,
|
||||||
path,
|
path,
|
||||||
name: typeof route.name === "string" ? route.name : undefined,
|
name: typeof route.name === "string" ? route.name : undefined,
|
||||||
icon: route.meta.icon,
|
icon: route.meta.icon,
|
||||||
redirect:
|
redirect: typeof route.redirect === "string" ? route.redirect : undefined,
|
||||||
typeof route.redirect === "string" ? route.redirect : undefined,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 布局大小 -->
|
<!-- 布局大小 -->
|
||||||
<el-tooltip
|
<el-tooltip :content="$t('sizeSelect.tooltip')" effect="dark" placement="bottom">
|
||||||
:content="$t('sizeSelect.tooltip')"
|
|
||||||
effect="dark"
|
|
||||||
placement="bottom"
|
|
||||||
>
|
|
||||||
<el-dropdown trigger="click" @command="handleSizeChange">
|
<el-dropdown trigger="click" @command="handleSizeChange">
|
||||||
<div>
|
<div>
|
||||||
<svg-icon icon-class="size" />
|
<svg-icon icon-class="size" />
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg
|
<svg aria-hidden="true" class="svg-icon" :style="'width:' + size + ';height:' + size">
|
||||||
aria-hidden="true"
|
|
||||||
class="svg-icon"
|
|
||||||
:style="'width:' + size + ';height:' + size"
|
|
||||||
>
|
|
||||||
<use :xlink:href="symbolId" :fill="color" />
|
<use :xlink:href="symbolId" :fill="color" />
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -63,17 +63,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- TreeSelect 树形选择 -->
|
<!-- TreeSelect 树形选择 -->
|
||||||
<template v-else-if="item.type === 'tree-select'">
|
<template v-else-if="item.type === 'tree-select'">
|
||||||
<el-tree-select
|
<el-tree-select v-model="queryParams[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="queryParams[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- DatePicker 日期选择器 -->
|
<!-- DatePicker 日期选择器 -->
|
||||||
<template v-else-if="item.type === 'date-picker'">
|
<template v-else-if="item.type === 'date-picker'">
|
||||||
<el-date-picker
|
<el-date-picker v-model="queryParams[item.prop]" v-bind="item.attrs" />
|
||||||
v-model="queryParams[item.prop]"
|
|
||||||
v-bind="item.attrs"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- Input 输入框 -->
|
<!-- Input 输入框 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -95,9 +89,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="search" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button icon="refresh" @click="handleReset">重置</el-button>
|
<el-button icon="refresh" @click="handleReset">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -119,11 +111,7 @@
|
|||||||
<template v-if="col.templet === 'custom'">
|
<template v-if="col.templet === 'custom'">
|
||||||
<el-table-column v-bind="col">
|
<el-table-column v-bind="col">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<slot
|
<slot :name="col.slotName ?? col.prop" :prop="col.prop" v-bind="scope" />
|
||||||
:name="col.slotName ?? col.prop"
|
|
||||||
:prop="col.prop"
|
|
||||||
v-bind="scope"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
@@ -294,9 +282,7 @@ for (const item of props.selectConfig.tableColumns) {
|
|||||||
// 选择
|
// 选择
|
||||||
const selectedItems = ref<IObject[]>([]);
|
const selectedItems = ref<IObject[]>([]);
|
||||||
const confirmText = computed(() => {
|
const confirmText = computed(() => {
|
||||||
return selectedItems.value.length > 0
|
return selectedItems.value.length > 0 ? `已选(${selectedItems.value.length})` : "确 定";
|
||||||
? `已选(${selectedItems.value.length})`
|
|
||||||
: "确 定";
|
|
||||||
});
|
});
|
||||||
function handleSelect(selection: any[], row: any) {
|
function handleSelect(selection: any[], row: any) {
|
||||||
if (isMultiple || selection.length === 0) {
|
if (isMultiple || selection.length === 0) {
|
||||||
|
|||||||
@@ -35,11 +35,7 @@
|
|||||||
<a class="el-upload-list__item-name" @click="downloadFile(file)">
|
<a class="el-upload-list__item-name" @click="downloadFile(file)">
|
||||||
<el-icon><Document /></el-icon>
|
<el-icon><Document /></el-icon>
|
||||||
<span class="el-upload-list__item-file-name">{{ file.name }}</span>
|
<span class="el-upload-list__item-file-name">{{ file.name }}</span>
|
||||||
<span
|
<span v-if="props.showDelBtn" class="el-icon--close" @click.stop="handleRemove(file)">
|
||||||
v-if="props.showDelBtn"
|
|
||||||
class="el-icon--close"
|
|
||||||
@click.stop="handleRemove(file)"
|
|
||||||
>
|
|
||||||
<el-icon><Close /></el-icon>
|
<el-icon><Close /></el-icon>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -278,9 +274,7 @@ function handleRemove(removeFile: UploadUserFile) {
|
|||||||
if (filePath) {
|
if (filePath) {
|
||||||
FileAPI.deleteByPath(filePath).then(() => {
|
FileAPI.deleteByPath(filePath).then(() => {
|
||||||
// 删除成功回调
|
// 删除成功回调
|
||||||
valFileList.value = valFileList.value.filter(
|
valFileList.value = valFileList.value.filter((file) => file.url !== filePath);
|
||||||
(file) => file.url !== filePath
|
|
||||||
);
|
|
||||||
emit("update:modelValue", valFileList.value);
|
emit("update:modelValue", valFileList.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
<el-upload
|
<el-upload
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:class="
|
:class="fileList.length >= props.limit || !props.showUploadBtn ? 'hide' : 'show'"
|
||||||
fileList.length >= props.limit || !props.showUploadBtn ? 'hide' : 'show'
|
|
||||||
"
|
|
||||||
:before-upload="handleBeforeUpload"
|
:before-upload="handleBeforeUpload"
|
||||||
:action="props.action"
|
:action="props.action"
|
||||||
:headers="props.headers"
|
:headers="props.headers"
|
||||||
@@ -45,12 +43,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { UploadRawFile, UploadUserFile, UploadFile, UploadProps } from "element-plus";
|
||||||
UploadRawFile,
|
|
||||||
UploadUserFile,
|
|
||||||
UploadFile,
|
|
||||||
UploadProps,
|
|
||||||
} from "element-plus";
|
|
||||||
import FileAPI from "@/api/file";
|
import FileAPI from "@/api/file";
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
import { ResultEnum } from "@/enums/ResultEnum";
|
import { ResultEnum } from "@/enums/ResultEnum";
|
||||||
@@ -224,9 +217,7 @@ function handleBeforeUpload(file: UploadRawFile) {
|
|||||||
*/
|
*/
|
||||||
const previewImg: UploadProps["onPreview"] = (uploadFile: UploadFile) => {
|
const previewImg: UploadProps["onPreview"] = (uploadFile: UploadFile) => {
|
||||||
viewFileList.value = fileList.value.map((file) => file.url!);
|
viewFileList.value = fileList.value.map((file) => file.url!);
|
||||||
initialIndex.value = fileList.value.findIndex(
|
initialIndex.value = fileList.value.findIndex((file) => file.url === uploadFile.url);
|
||||||
(file) => file.url === uploadFile.url
|
|
||||||
);
|
|
||||||
viewVisible.value = true;
|
viewVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { ElImageViewer, UploadRawFile, UploadRequestOptions } from "element-plus";
|
||||||
ElImageViewer,
|
|
||||||
UploadRawFile,
|
|
||||||
UploadRequestOptions,
|
|
||||||
} from "element-plus";
|
|
||||||
import FileAPI from "@/api/file";
|
import FileAPI from "@/api/file";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ export const hasPerm: Directive = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error("need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\"");
|
||||||
"need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
<section class="app-main" :style="{ height: appMainHeight }">
|
<section class="app-main" :style="{ height: appMainHeight }">
|
||||||
<router-view>
|
<router-view>
|
||||||
<template #default="{ Component, route }">
|
<template #default="{ Component, route }">
|
||||||
<transition
|
<transition enter-active-class="animate__animated animate__fadeIn" mode="out-in">
|
||||||
enter-active-class="animate__animated animate__fadeIn"
|
|
||||||
mode="out-in"
|
|
||||||
>
|
|
||||||
<keep-alive :include="cachedViews">
|
<keep-alive :include="cachedViews">
|
||||||
<component :is="Component" :key="route.path" />
|
<component :is="Component" :key="route.path" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
|
|||||||
@@ -31,12 +31,7 @@
|
|||||||
class="w400px flex-x-between p-1"
|
class="w400px flex-x-between p-1"
|
||||||
>
|
>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<DictLabel
|
<DictLabel v-model="item.type" code="notice_type" size="small" class="mr-1" />
|
||||||
v-model="item.type"
|
|
||||||
code="notice_type"
|
|
||||||
size="small"
|
|
||||||
class="mr-1"
|
|
||||||
/>
|
|
||||||
<el-text
|
<el-text
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -83,16 +78,8 @@
|
|||||||
class="w400px flex-x-between p-1"
|
class="w400px flex-x-between p-1"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<DictLabel
|
<DictLabel v-model="item.type" code="notice_type" size="small" />
|
||||||
v-model="item.type"
|
<el-link type="primary" class="ml-1" @click="readNotice(item.id)">
|
||||||
code="notice_type"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
<el-link
|
|
||||||
type="primary"
|
|
||||||
class="ml-1"
|
|
||||||
@click="readNotice(item.id)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
@@ -127,22 +114,10 @@
|
|||||||
|
|
||||||
<el-tab-pane label="待办" name="task">
|
<el-tab-pane label="待办" name="task">
|
||||||
<template v-if="tasks.length > 0">
|
<template v-if="tasks.length > 0">
|
||||||
<div
|
<div v-for="(item, index) in tasks" :key="index" class="w400px flex-x-between p-1">
|
||||||
v-for="(item, index) in tasks"
|
|
||||||
:key="index"
|
|
||||||
class="w400px flex-x-between p-1"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<DictLabel
|
<DictLabel v-model="item.type" code="notice_type" size="small" />
|
||||||
v-model="item.type"
|
<el-link type="primary" class="ml-1" @click="readNotice(item.id)">
|
||||||
code="notice_type"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
<el-link
|
|
||||||
type="primary"
|
|
||||||
class="ml-1"
|
|
||||||
@click="readNotice(item.id)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
@@ -196,11 +171,9 @@ const noticeDetailRef = ref();
|
|||||||
|
|
||||||
// 获取未读消息列表并连接 WebSocket
|
// 获取未读消息列表并连接 WebSocket
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
NoticeAPI.getMyNoticePage({ pageNum: 1, pageSize: 5, isRead: 0 }).then(
|
NoticeAPI.getMyNoticePage({ pageNum: 1, pageSize: 5, isRead: 0 }).then((data) => {
|
||||||
(data) => {
|
notices.value = data.list;
|
||||||
notices.value = data.list;
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
WebSocketManager.subscribeToTopic("/user/queue/message", (message) => {
|
WebSocketManager.subscribeToTopic("/user/queue/message", (message) => {
|
||||||
console.log("收到消息:", message);
|
console.log("收到消息:", message);
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dropdown trigger="click">
|
<el-dropdown trigger="click">
|
||||||
<div class="flex-center h100% p13px">
|
<div class="flex-center h100% p13px">
|
||||||
<img
|
<img :src="userStore.userInfo.avatar" class="rounded-full mr-10px w24px h24px" />
|
||||||
:src="userStore.userInfo.avatar"
|
|
||||||
class="rounded-full mr-10px w24px h24px"
|
|
||||||
/>
|
|
||||||
<span>{{ userStore.userInfo.username }}</span>
|
<span>{{ userStore.userInfo.username }}</span>
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
@@ -12,10 +9,7 @@
|
|||||||
<el-dropdown-item @click="handleOpenUserProfile">
|
<el-dropdown-item @click="handleOpenUserProfile">
|
||||||
{{ $t("navbar.profile") }}
|
{{ $t("navbar.profile") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<a
|
<a target="_blank" href="https://gitee.com/youlaiorg/vue3-element-admin">
|
||||||
target="_blank"
|
|
||||||
href="https://gitee.com/youlaiorg/vue3-element-admin"
|
|
||||||
>
|
|
||||||
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
|
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://juejin.cn/post/7228990409909108793">
|
<a target="_blank" href="https://juejin.cn/post/7228990409909108793">
|
||||||
|
|||||||
@@ -1,28 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer v-model="settingsVisible" size="300" :title="$t('settings.project')">
|
||||||
v-model="settingsVisible"
|
|
||||||
size="300"
|
|
||||||
:title="$t('settings.project')"
|
|
||||||
>
|
|
||||||
<el-divider>{{ $t("settings.theme") }}</el-divider>
|
<el-divider>{{ $t("settings.theme") }}</el-divider>
|
||||||
|
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<el-switch
|
<el-switch v-model="isDark" active-icon="Moon" inactive-icon="Sunny" @change="changeTheme" />
|
||||||
v-model="isDark"
|
|
||||||
active-icon="Moon"
|
|
||||||
inactive-icon="Sunny"
|
|
||||||
@change="changeTheme"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-divider>{{ $t("settings.interface") }}</el-divider>
|
<el-divider>{{ $t("settings.interface") }}</el-divider>
|
||||||
|
|
||||||
<div class="py-1 flex-x-between">
|
<div class="py-1 flex-x-between">
|
||||||
<span class="text-xs">{{ $t("settings.themeColor") }}</span>
|
<span class="text-xs">{{ $t("settings.themeColor") }}</span>
|
||||||
<ThemeColorPicker
|
<ThemeColorPicker v-model="settingsStore.themeColor" @update:model-value="changeThemeColor" />
|
||||||
v-model="settingsStore.themeColor"
|
|
||||||
@update:model-value="changeThemeColor"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-1 flex-x-between">
|
<div class="py-1 flex-x-between">
|
||||||
@@ -47,10 +35,7 @@
|
|||||||
|
|
||||||
<el-divider>{{ $t("settings.navigation") }}</el-divider>
|
<el-divider>{{ $t("settings.navigation") }}</el-divider>
|
||||||
|
|
||||||
<LayoutSelect
|
<LayoutSelect v-model="settingsStore.layout" @update:model-value="changeLayout" />
|
||||||
v-model="settingsStore.layout"
|
|
||||||
@update:model-value="changeLayout"
|
|
||||||
/>
|
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ const onMenuOpen = (index: string) => {
|
|||||||
* @param index 当前收起的菜单项索引
|
* @param index 当前收起的菜单项索引
|
||||||
*/
|
*/
|
||||||
const onMenuClose = (index: string) => {
|
const onMenuClose = (index: string) => {
|
||||||
expandedMenuIndexes.value = expandedMenuIndexes.value.filter(
|
expandedMenuIndexes.value = expandedMenuIndexes.value.filter((item) => item !== index);
|
||||||
(item) => item !== index
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,17 +9,10 @@
|
|||||||
:active-text-color="variables['menu-active-text']"
|
:active-text-color="variables['menu-active-text']"
|
||||||
@select="handleMenuSelect"
|
@select="handleMenuSelect"
|
||||||
>
|
>
|
||||||
<el-menu-item
|
<el-menu-item v-for="route in topMenus" :key="route.path" :index="route.path">
|
||||||
v-for="route in topMenus"
|
|
||||||
:key="route.path"
|
|
||||||
:index="route.path"
|
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<template v-if="route.meta && route.meta.icon">
|
<template v-if="route.meta && route.meta.icon">
|
||||||
<el-icon
|
<el-icon v-if="route.meta.icon.startsWith('el-icon')" class="sub-el-icon">
|
||||||
v-if="route.meta.icon.startsWith('el-icon')"
|
|
||||||
class="sub-el-icon"
|
|
||||||
>
|
|
||||||
<component :is="route.meta.icon.replace('el-icon-', '')" />
|
<component :is="route.meta.icon.replace('el-icon-', '')" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<svg-icon v-else :icon-class="route.meta.icon" />
|
<svg-icon v-else :icon-class="route.meta.icon" />
|
||||||
@@ -99,8 +92,6 @@ const navigateToFirstLeftMenu = (menus: RouteRecordRaw[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
topMenus.value = permissionStore.routes.filter(
|
topMenus.value = permissionStore.routes.filter((item) => !item.meta || !item.meta.hidden);
|
||||||
(item) => !item.meta || !item.meta.hidden
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tags-container">
|
<div class="tags-container">
|
||||||
<el-scrollbar
|
<el-scrollbar class="scroll-container" :vertical="false" @wheel.prevent="handleScroll">
|
||||||
class="scroll-container"
|
|
||||||
:vertical="false"
|
|
||||||
@wheel.prevent="handleScroll"
|
|
||||||
>
|
|
||||||
<router-link
|
<router-link
|
||||||
v-for="tag in visitedViews"
|
v-for="tag in visitedViews"
|
||||||
ref="tagRef"
|
ref="tagRef"
|
||||||
@@ -64,12 +60,7 @@ import { useRoute, useRouter, RouteRecordRaw } from "vue-router";
|
|||||||
import { resolve } from "path-browserify";
|
import { resolve } from "path-browserify";
|
||||||
import { translateRouteTitle } from "@/utils/i18n";
|
import { translateRouteTitle } from "@/utils/i18n";
|
||||||
|
|
||||||
import {
|
import { usePermissionStore, useTagsViewStore, useSettingsStore, useAppStore } from "@/store";
|
||||||
usePermissionStore,
|
|
||||||
useTagsViewStore,
|
|
||||||
useSettingsStore,
|
|
||||||
useAppStore,
|
|
||||||
} from "@/store";
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance()!;
|
const { proxy } = getCurrentInstance()!;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
import type { App } from "vue";
|
import type { App } from "vue";
|
||||||
import {
|
import { createRouter, createWebHashHistory, type RouteRecordRaw } from "vue-router";
|
||||||
createRouter,
|
|
||||||
createWebHashHistory,
|
|
||||||
type RouteRecordRaw,
|
|
||||||
} from "vue-router";
|
|
||||||
|
|
||||||
export const Layout = () => import("@/layout/index.vue");
|
export const Layout = () => import("@/layout/index.vue");
|
||||||
|
|
||||||
@@ -65,8 +61,7 @@ export const constantRoutes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: "myNotice",
|
path: "myNotice",
|
||||||
name: "MyNotice",
|
name: "MyNotice",
|
||||||
component: () =>
|
component: () => import("@/views/system/notice/components/MyNotice.vue"),
|
||||||
import("@/views/system/notice/components/MyNotice.vue"),
|
|
||||||
meta: { title: "我的通知", icon: "user", hidden: true },
|
meta: { title: "我的通知", icon: "user", hidden: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ export const useAppStore = defineStore("app", () => {
|
|||||||
// 切换侧边栏
|
// 切换侧边栏
|
||||||
function toggleSidebar() {
|
function toggleSidebar() {
|
||||||
sidebar.opened = !sidebar.opened;
|
sidebar.opened = !sidebar.opened;
|
||||||
sidebarStatus.value = sidebar.opened
|
sidebarStatus.value = sidebar.opened ? SidebarStatusEnum.OPENED : SidebarStatusEnum.CLOSED;
|
||||||
? SidebarStatusEnum.OPENED
|
|
||||||
: SidebarStatusEnum.CLOSED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭侧边栏
|
// 关闭侧边栏
|
||||||
|
|||||||
@@ -10,15 +10,9 @@ export const useSettingsStore = defineStore("setting", () => {
|
|||||||
// 标签
|
// 标签
|
||||||
const tagsView = useStorage<boolean>("tagsView", defaultSettings.tagsView);
|
const tagsView = useStorage<boolean>("tagsView", defaultSettings.tagsView);
|
||||||
// 侧边栏 Logo
|
// 侧边栏 Logo
|
||||||
const sidebarLogo = useStorage<boolean>(
|
const sidebarLogo = useStorage<boolean>("sidebarLogo", defaultSettings.sidebarLogo);
|
||||||
"sidebarLogo",
|
|
||||||
defaultSettings.sidebarLogo
|
|
||||||
);
|
|
||||||
// 固定头部
|
// 固定头部
|
||||||
const fixedHeader = useStorage<boolean>(
|
const fixedHeader = useStorage<boolean>("fixedHeader", defaultSettings.fixedHeader);
|
||||||
"fixedHeader",
|
|
||||||
defaultSettings.fixedHeader
|
|
||||||
);
|
|
||||||
// 布局
|
// 布局
|
||||||
const layout = useStorage<string>("layout", defaultSettings.layout);
|
const layout = useStorage<string>("layout", defaultSettings.layout);
|
||||||
// 水印
|
// 水印
|
||||||
@@ -28,10 +22,7 @@ export const useSettingsStore = defineStore("setting", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 主题
|
// 主题
|
||||||
const themeColor = useStorage<string>(
|
const themeColor = useStorage<string>("themeColor", defaultSettings.themeColor);
|
||||||
"themeColor",
|
|
||||||
defaultSettings.themeColor
|
|
||||||
);
|
|
||||||
const theme = useStorage<string>("theme", defaultSettings.theme);
|
const theme = useStorage<string>("theme", defaultSettings.theme);
|
||||||
|
|
||||||
// 监听主题变化
|
// 监听主题变化
|
||||||
@@ -53,13 +44,7 @@ export const useSettingsStore = defineStore("setting", () => {
|
|||||||
watermarkEnabled,
|
watermarkEnabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
function changeSetting({
|
function changeSetting({ key, value }: { key: string; value: SettingsValue }) {
|
||||||
key,
|
|
||||||
value,
|
|
||||||
}: {
|
|
||||||
key: string;
|
|
||||||
value: SettingsValue;
|
|
||||||
}) {
|
|
||||||
const setting = settingsMap[key];
|
const setting = settingsMap[key];
|
||||||
if (setting) setting.value = value;
|
if (setting) setting.value = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,9 +124,7 @@ export const useTagsViewStore = defineStore("tagsView", () => {
|
|||||||
|
|
||||||
function delLeftViews(view: TagView) {
|
function delLeftViews(view: TagView) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const currIndex = visitedViews.value.findIndex(
|
const currIndex = visitedViews.value.findIndex((v) => v.path === view.path);
|
||||||
(v) => v.path === view.path
|
|
||||||
);
|
|
||||||
if (currIndex === -1) {
|
if (currIndex === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -149,9 +147,7 @@ export const useTagsViewStore = defineStore("tagsView", () => {
|
|||||||
|
|
||||||
function delRightViews(view: TagView) {
|
function delRightViews(view: TagView) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const currIndex = visitedViews.value.findIndex(
|
const currIndex = visitedViews.value.findIndex((v) => v.path === view.path);
|
||||||
(v) => v.path === view.path
|
|
||||||
);
|
|
||||||
if (currIndex === -1) {
|
if (currIndex === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import { getToken } from "@/utils/auth";
|
|||||||
|
|
||||||
class WebSocketManager {
|
class WebSocketManager {
|
||||||
private client: Client | null = null;
|
private client: Client | null = null;
|
||||||
private messageHandlers: Map<string, ((message: string) => void)[]> =
|
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
|
||||||
new Map();
|
|
||||||
private reconnectAttempts = 0;
|
private reconnectAttempts = 0;
|
||||||
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
||||||
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
||||||
@@ -15,9 +14,7 @@ class WebSocketManager {
|
|||||||
|
|
||||||
// 如果没有配置 WebSocket 端点或显式关闭,直接返回
|
// 如果没有配置 WebSocket 端点或显式关闭,直接返回
|
||||||
if (!endpoint) {
|
if (!endpoint) {
|
||||||
console.log(
|
console.log("WebSocket 已被禁用,如需打开请在配置文件中配置 VITE_APP_WS_ENDPOINT");
|
||||||
"WebSocket 已被禁用,如需打开请在配置文件中配置 VITE_APP_WS_ENDPOINT"
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,11 +42,7 @@
|
|||||||
|
|
||||||
<el-table-column label="存储引擎" align="center" prop="engine" />
|
<el-table-column label="存储引擎" align="center" prop="engine" />
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column label="排序规则" align="center" prop="tableCollation" />
|
||||||
label="排序规则"
|
|
||||||
align="center"
|
|
||||||
prop="tableCollation"
|
|
||||||
/>
|
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" />
|
<el-table-column label="创建时间" align="center" prop="createTime" />
|
||||||
|
|
||||||
<el-table-column fixed="right" label="操作" width="200">
|
<el-table-column fixed="right" label="操作" width="200">
|
||||||
@@ -115,10 +111,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="业务名" prop="businessName">
|
<el-form-item label="业务名" prop="businessName">
|
||||||
<el-input
|
<el-input v-model="genConfigFormData.businessName" placeholder="用户" />
|
||||||
v-model="genConfigFormData.businessName"
|
|
||||||
placeholder="用户"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -126,18 +119,12 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="包名" prop="packageName">
|
<el-form-item label="包名" prop="packageName">
|
||||||
<el-input
|
<el-input v-model="genConfigFormData.packageName" placeholder="com.youlai.boot" />
|
||||||
v-model="genConfigFormData.packageName"
|
|
||||||
placeholder="com.youlai.boot"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="模块名" prop="moduleName">
|
<el-form-item label="模块名" prop="moduleName">
|
||||||
<el-input
|
<el-input v-model="genConfigFormData.moduleName" placeholder="system" />
|
||||||
v-model="genConfigFormData.moduleName"
|
|
||||||
placeholder="system"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -145,18 +132,12 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="实体名" prop="entityName">
|
<el-form-item label="实体名" prop="entityName">
|
||||||
<el-input
|
<el-input v-model="genConfigFormData.entityName" placeholder="User" />
|
||||||
v-model="genConfigFormData.entityName"
|
|
||||||
placeholder="User"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="作者">
|
<el-form-item label="作者">
|
||||||
<el-input
|
<el-input v-model="genConfigFormData.author" placeholder="youlai" />
|
||||||
v-model="genConfigFormData.author"
|
|
||||||
placeholder="youlai"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -256,11 +237,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox
|
<el-checkbox v-model="scope.row.isShowInQuery" :true-value="1" :false-value="0" />
|
||||||
v-model="scope.row.isShowInQuery"
|
|
||||||
:true-value="1"
|
|
||||||
:false-value="0"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@@ -277,11 +254,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox
|
<el-checkbox v-model="scope.row.isShowInList" :true-value="1" :false-value="0" />
|
||||||
v-model="scope.row.isShowInList"
|
|
||||||
:true-value="1"
|
|
||||||
:false-value="0"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@@ -298,11 +271,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox
|
<el-checkbox v-model="scope.row.isShowInForm" :true-value="1" :false-value="0" />
|
||||||
v-model="scope.row.isShowInForm"
|
|
||||||
:true-value="1"
|
|
||||||
:false-value="0"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@@ -339,10 +308,7 @@
|
|||||||
<el-table-column label="表单类型" min-width="120">
|
<el-table-column label="表单类型" min-width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-select
|
<el-select
|
||||||
v-if="
|
v-if="scope.row.isShowInQuery === 1 || scope.row.isShowInForm === 1"
|
||||||
scope.row.isShowInQuery === 1 ||
|
|
||||||
scope.row.isShowInForm === 1
|
|
||||||
"
|
|
||||||
v-model="scope.row.formType"
|
v-model="scope.row.formType"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
>
|
>
|
||||||
@@ -562,9 +528,7 @@ const initSort = () => {
|
|||||||
if (sortFlag.value) {
|
if (sortFlag.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const table = document.querySelector(
|
const table = document.querySelector(".elTableCustom .el-table__body-wrapper tbody");
|
||||||
".elTableCustom .el-table__body-wrapper tbody"
|
|
||||||
);
|
|
||||||
sortFlag.value = Sortable.create(<HTMLElement>table, {
|
sortFlag.value = Sortable.create(<HTMLElement>table, {
|
||||||
group: "shared",
|
group: "shared",
|
||||||
animation: 150,
|
animation: 150,
|
||||||
@@ -622,13 +586,7 @@ function handleNextClick() {
|
|||||||
//这里需要校验基础配置
|
//这里需要校验基础配置
|
||||||
const { tableName, packageName, businessName, moduleName, entityName } =
|
const { tableName, packageName, businessName, moduleName, entityName } =
|
||||||
genConfigFormData.value;
|
genConfigFormData.value;
|
||||||
if (
|
if (!tableName || !packageName || !businessName || !moduleName || !entityName) {
|
||||||
!tableName ||
|
|
||||||
!packageName ||
|
|
||||||
!businessName ||
|
|
||||||
!moduleName ||
|
|
||||||
!entityName
|
|
||||||
) {
|
|
||||||
ElMessage.error("表名、业务名、包名、模块名、实体名不能为空");
|
ElMessage.error("表名、业务名、包名、模块名、实体名不能为空");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -755,9 +713,7 @@ const toggleCheckAll = (key: FieldConfigKey, value: boolean) => {
|
|||||||
|
|
||||||
const checkAllSelected = (key: keyof FieldConfig, isCheckAllRef: any) => {
|
const checkAllSelected = (key: keyof FieldConfig, isCheckAllRef: any) => {
|
||||||
const fieldConfigs = genConfigFormData.value?.fieldConfigs || [];
|
const fieldConfigs = genConfigFormData.value?.fieldConfigs || [];
|
||||||
isCheckAllRef.value = fieldConfigs.every(
|
isCheckAllRef.value = fieldConfigs.every((row: FieldConfig) => row[key] === 1);
|
||||||
(row: FieldConfig) => row[key] === 1
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 获取生成预览 */
|
/** 获取生成预览 */
|
||||||
@@ -787,9 +743,7 @@ function handlePreview(tableName: string) {
|
|||||||
* @param data - 数据数组
|
* @param data - 数据数组
|
||||||
* @returns 树形结构根节点
|
* @returns 树形结构根节点
|
||||||
*/
|
*/
|
||||||
function buildTree(
|
function buildTree(data: { path: string; fileName: string; content: string }[]): TreeNode {
|
||||||
data: { path: string; fileName: string; content: string }[]
|
|
||||||
): TreeNode {
|
|
||||||
// 动态获取根节点
|
// 动态获取根节点
|
||||||
const root: TreeNode = { label: "前后端代码", children: [] };
|
const root: TreeNode = { label: "前后端代码", children: [] };
|
||||||
|
|
||||||
@@ -804,11 +758,10 @@ function buildTree(
|
|||||||
"java",
|
"java",
|
||||||
genConfigFormData.value.backendAppName,
|
genConfigFormData.value.backendAppName,
|
||||||
genConfigFormData.value.frontendAppName,
|
genConfigFormData.value.frontendAppName,
|
||||||
(
|
(genConfigFormData.value.packageName + "." + genConfigFormData.value.moduleName).replace(
|
||||||
genConfigFormData.value.packageName +
|
/\./g,
|
||||||
"." +
|
separator
|
||||||
genConfigFormData.value.moduleName
|
),
|
||||||
).replace(/\./g, separator),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 检查路径中的特殊部分并合并它们
|
// 检查路径中的特殊部分并合并它们
|
||||||
|
|||||||
@@ -16,11 +16,7 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-radio-group
|
<el-radio-group v-model="dataRange" size="small" @change="handleDateRangeChange">
|
||||||
v-model="dataRange"
|
|
||||||
size="small"
|
|
||||||
@change="handleDateRangeChange"
|
|
||||||
>
|
|
||||||
<el-radio-button label="近7天" :value="1" />
|
<el-radio-button label="近7天" :value="1" />
|
||||||
<el-radio-button label="近30天" :value="2" />
|
<el-radio-button label="近30天" :value="2" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@@ -209,9 +205,7 @@ const handleResize = () => {
|
|||||||
};
|
};
|
||||||
/** 初始化图表 */
|
/** 初始化图表 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
chart.value = markRaw(
|
chart.value = markRaw(echarts.init(document.getElementById(props.id) as HTMLDivElement));
|
||||||
echarts.init(document.getElementById(props.id) as HTMLDivElement)
|
|
||||||
);
|
|
||||||
loadData();
|
loadData();
|
||||||
|
|
||||||
window.addEventListener("resize", handleResize);
|
window.addEventListener("resize", handleResize);
|
||||||
|
|||||||
@@ -12,20 +12,14 @@
|
|||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ greetings }}</p>
|
<p>{{ greetings }}</p>
|
||||||
<p class="text-sm text-gray">
|
<p class="text-sm text-gray">今日天气晴朗,气温在15℃至25℃之间,东南风。</p>
|
||||||
今日天气晴朗,气温在15℃至25℃之间,东南风。
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="6" :xs="24">
|
<el-col :span="6" :xs="24">
|
||||||
<div class="flex h-full items-center justify-around">
|
<div class="flex h-full items-center justify-around">
|
||||||
<el-statistic
|
<el-statistic v-for="item in statisticData" :key="item.key" :value="item.value">
|
||||||
v-for="item in statisticData"
|
|
||||||
:key="item.key"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<svg-icon :icon-class="item.iconClass" size="20px" />
|
<svg-icon :icon-class="item.iconClass" size="20px" />
|
||||||
@@ -45,9 +39,7 @@
|
|||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex-x-between">
|
<div class="flex-x-between">
|
||||||
<span class="text-[var(--el-text-color-secondary)]">
|
<span class="text-[var(--el-text-color-secondary)]">在线用户</span>
|
||||||
在线用户
|
|
||||||
</span>
|
|
||||||
<el-tag type="success" size="small">-</el-tag>
|
<el-tag type="success" size="small">-</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -56,41 +48,27 @@
|
|||||||
<span class="text-lg">{{ onlineUserCount }}</span>
|
<span class="text-lg">{{ onlineUserCount }}</span>
|
||||||
<svg-icon icon-class="user" size="2em" />
|
<svg-icon icon-class="user" size="2em" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="flex-x-between mt-2 text-sm text-[var(--el-text-color-secondary)]">
|
||||||
class="flex-x-between mt-2 text-sm text-[var(--el-text-color-secondary)]"
|
|
||||||
>
|
|
||||||
<span>总用户数</span>
|
<span>总用户数</span>
|
||||||
<span>5</span>
|
<span>5</span>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col
|
<el-col v-for="(item, index) in visitStatsList" :key="index" :xs="24" :sm="12" :lg="6">
|
||||||
v-for="(item, index) in visitStatsList"
|
|
||||||
:key="index"
|
|
||||||
:xs="24"
|
|
||||||
:sm="12"
|
|
||||||
:lg="6"
|
|
||||||
>
|
|
||||||
<el-skeleton :loading="visitStatsLoading" :rows="5" animated>
|
<el-skeleton :loading="visitStatsLoading" :rows="5" animated>
|
||||||
<template #template>
|
<template #template>
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div>
|
<div>
|
||||||
<el-skeleton-item variant="h3" style="width: 40%" />
|
<el-skeleton-item variant="h3" style="width: 40%" />
|
||||||
<el-skeleton-item
|
<el-skeleton-item variant="rect" style="float: right; width: 1em; height: 1em" />
|
||||||
variant="rect"
|
|
||||||
style="float: right; width: 1em; height: 1em"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="flex-x-between">
|
<div class="flex-x-between">
|
||||||
<el-skeleton-item variant="text" style="width: 30%" />
|
<el-skeleton-item variant="text" style="width: 30%" />
|
||||||
<el-skeleton-item
|
<el-skeleton-item variant="circle" style="width: 2em; height: 2em" />
|
||||||
variant="circle"
|
|
||||||
style="width: 2em; height: 2em"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 flex-x-between">
|
<div class="mt-5 flex-x-between">
|
||||||
<el-skeleton-item variant="text" style="width: 50%" />
|
<el-skeleton-item variant="text" style="width: 50%" />
|
||||||
@@ -114,13 +92,7 @@
|
|||||||
<div class="flex-x-between mt-2">
|
<div class="flex-x-between mt-2">
|
||||||
<div class="flex-y-center">
|
<div class="flex-y-center">
|
||||||
<span class="text-lg">{{ item.todayCount }}</span>
|
<span class="text-lg">{{ item.todayCount }}</span>
|
||||||
<span
|
<span :class="['text-xs', 'ml-2', getGrowthRateClass(item.growthRate)]">
|
||||||
:class="[
|
|
||||||
'text-xs',
|
|
||||||
'ml-2',
|
|
||||||
getGrowthRateClass(item.growthRate),
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Top v-if="item.growthRate > 0" />
|
<Top v-if="item.growthRate > 0" />
|
||||||
<Bottom v-else-if="item.growthRate < 0" />
|
<Bottom v-else-if="item.growthRate < 0" />
|
||||||
@@ -131,9 +103,7 @@
|
|||||||
<svg-icon :icon-class="item.icon" size="2em" />
|
<svg-icon :icon-class="item.icon" size="2em" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="flex-x-between mt-2 text-sm text-[var(--el-text-color-secondary)]">
|
||||||
class="flex-x-between mt-2 text-sm text-[var(--el-text-color-secondary)]"
|
|
||||||
>
|
|
||||||
<span>总{{ item.title }}</span>
|
<span>总{{ item.title }}</span>
|
||||||
<span>{{ item.totalCount }}</span>
|
<span>{{ item.totalCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -161,11 +131,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-scrollbar height="400px">
|
<el-scrollbar height="400px">
|
||||||
<div
|
<div v-for="(item, index) in notices" :key="index" class="flex-y-center py-3">
|
||||||
v-for="(item, index) in notices"
|
|
||||||
:key="index"
|
|
||||||
class="flex-y-center py-3"
|
|
||||||
>
|
|
||||||
<DictLabel v-model="item.type" code="notice_type" size="small" />
|
<DictLabel v-model="item.type" code="notice_type" size="small" />
|
||||||
<el-text
|
<el-text
|
||||||
truncated
|
truncated
|
||||||
@@ -263,11 +229,7 @@ const loadVisitStatsData = async () => {
|
|||||||
const list: VisitStatsVO[] = await StatsAPI.getVisitStats();
|
const list: VisitStatsVO[] = await StatsAPI.getVisitStats();
|
||||||
|
|
||||||
if (list) {
|
if (list) {
|
||||||
const tagTypes: ("primary" | "success" | "warning")[] = [
|
const tagTypes: ("primary" | "success" | "warning")[] = ["primary", "success", "warning"];
|
||||||
"primary",
|
|
||||||
"success",
|
|
||||||
"warning",
|
|
||||||
];
|
|
||||||
const transformedList: VisitStats[] = list.map((item, index) => ({
|
const transformedList: VisitStats[] = list.map((item, index) => ({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
icon: getVisitStatsIcon(item.type),
|
icon: getVisitStatsIcon(item.type),
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
<!-- 接口文档 -->
|
<!-- 接口文档 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<iframe
|
<iframe src="http://vapi.youlai.tech/doc.html" width="100%" height="100%" frameborder="0" />
|
||||||
src="http://vapi.youlai.tech/doc.html"
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
frameborder="0"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ const contentConfig: IContentConfig = {
|
|||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
username: "tom",
|
username: "tom",
|
||||||
avatar:
|
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||||
"https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
|
||||||
percent: 99,
|
percent: 99,
|
||||||
price: 10,
|
price: 10,
|
||||||
url: "https://www.baidu.com",
|
url: "https://www.baidu.com",
|
||||||
@@ -30,8 +29,7 @@ const contentConfig: IContentConfig = {
|
|||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
username: "jerry",
|
username: "jerry",
|
||||||
avatar:
|
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
||||||
"https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
|
|
||||||
percent: 88,
|
percent: 88,
|
||||||
price: 999,
|
price: 999,
|
||||||
url: "https://www.google.com",
|
url: "https://www.google.com",
|
||||||
|
|||||||
@@ -8,9 +8,7 @@
|
|||||||
>
|
>
|
||||||
示例源码 请点击>>>>
|
示例源码 请点击>>>>
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-button type="primary" plain round size="small" @click="isA = !isA">
|
<el-button type="primary" plain round size="small" @click="isA = !isA">切换示例</el-button>
|
||||||
切换示例
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
@@ -146,14 +144,10 @@ function handleOperatClick(data: IOperatData) {
|
|||||||
console.log(data);
|
console.log(data);
|
||||||
// 重置密码
|
// 重置密码
|
||||||
if (data.name === "reset_pwd") {
|
if (data.name === "reset_pwd") {
|
||||||
ElMessageBox.prompt(
|
ElMessageBox.prompt("请输入用户「" + data.row.username + "」的新密码", "重置密码", {
|
||||||
"请输入用户「" + data.row.username + "」的新密码",
|
confirmButtonText: "确定",
|
||||||
"重置密码",
|
cancelButtonText: "取消",
|
||||||
{
|
}).then(({ value }) => {
|
||||||
confirmButtonText: "确定",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
}
|
|
||||||
).then(({ value }) => {
|
|
||||||
if (!value || value.length < 6) {
|
if (!value || value.length < 6) {
|
||||||
ElMessage.warning("密码至少需要6位字符,请重新输入");
|
ElMessage.warning("密码至少需要6位字符,请重新输入");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -5,11 +5,7 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div v-for="item of svg_icons" :key="item">
|
<div v-for="item of svg_icons" :key="item">
|
||||||
<copy-button :text="generateIconCode(item)">
|
<copy-button :text="generateIconCode(item)">
|
||||||
<el-tooltip
|
<el-tooltip effect="dark" :content="generateIconCode(item)" placement="top">
|
||||||
effect="dark"
|
|
||||||
:content="generateIconCode(item)"
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<div class="icon-item">
|
<div class="icon-item">
|
||||||
<svg-icon :icon-class="item" />
|
<svg-icon :icon-class="item" />
|
||||||
<span>{{ item }}</span>
|
<span>{{ item }}</span>
|
||||||
@@ -23,11 +19,7 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div v-for="(icon, name) of icons" :key="name">
|
<div v-for="(icon, name) of icons" :key="name">
|
||||||
<copy-button :text="generateElementIconCode(name)">
|
<copy-button :text="generateElementIconCode(name)">
|
||||||
<el-tooltip
|
<el-tooltip effect="dark" :content="generateElementIconCode(name)" placement="top">
|
||||||
effect="dark"
|
|
||||||
:content="generateElementIconCode(name)"
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<div class="icon-item">
|
<div class="icon-item">
|
||||||
<el-icon :size="20">
|
<el-icon :size="20">
|
||||||
<component :is="icon" />
|
<component :is="icon" />
|
||||||
|
|||||||
@@ -36,11 +36,7 @@ const text = computed(() => {
|
|||||||
>
|
>
|
||||||
示例源码 请点击>>>>
|
示例源码 请点击>>>>
|
||||||
</el-link>
|
</el-link>
|
||||||
<table-select
|
<table-select :text="text" :select-config="selectConfig" @confirm-click="handleConfirm">
|
||||||
:text="text"
|
|
||||||
:select-config="selectConfig"
|
|
||||||
@confirm-click="handleConfirm"
|
|
||||||
>
|
|
||||||
<template #status="scope">
|
<template #status="scope">
|
||||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ const value = ref("初始内容");
|
|||||||
>
|
>
|
||||||
示例源码 请点击>>>>
|
示例源码 请点击>>>>
|
||||||
</el-link>
|
</el-link>
|
||||||
<editor
|
<editor v-model="value" style="z-index: 99999; height: calc(100vh - 180px)" />
|
||||||
v-model="value"
|
|
||||||
style="z-index: 99999; height: calc(100vh - 180px)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -22,19 +22,13 @@
|
|||||||
>
|
>
|
||||||
连接
|
连接
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button type="danger" :disabled="!isConnected" @click="disconnectWebSocket">
|
||||||
type="danger"
|
|
||||||
:disabled="!isConnected"
|
|
||||||
@click="disconnectWebSocket"
|
|
||||||
>
|
|
||||||
断开
|
断开
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" class="text-right">
|
<el-col :span="8" class="text-right">
|
||||||
连接状态:
|
连接状态:
|
||||||
<el-tag v-if="isConnected" class="ml-2" type="success">
|
<el-tag v-if="isConnected" class="ml-2" type="success">已连接</el-tag>
|
||||||
已连接
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-else class="ml-2" type="info">已断开</el-tag>
|
<el-tag v-else class="ml-2" type="info">已断开</el-tag>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -60,9 +54,7 @@
|
|||||||
<el-input v-model="receiver" />
|
<el-input v-model="receiver" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="sendToUser">
|
<el-button type="primary" @click="sendToUser">发送点对点消息</el-button>
|
||||||
发送点对点消息
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
@@ -78,17 +70,14 @@
|
|||||||
'tip-message': message.type === 'tip',
|
'tip-message': message.type === 'tip',
|
||||||
message: message.type !== 'tip',
|
message: message.type !== 'tip',
|
||||||
'message--sent': message.sender === userStore.userInfo.username,
|
'message--sent': message.sender === userStore.userInfo.username,
|
||||||
'message--received':
|
'message--received': message.sender !== userStore.userInfo.username,
|
||||||
message.sender !== userStore.userInfo.username,
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div v-if="message.type != 'tip'" class="message-content">
|
<div v-if="message.type != 'tip'" class="message-content">
|
||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'message-sender':
|
'message-sender': message.sender === userStore.userInfo.username,
|
||||||
message.sender === userStore.userInfo.username,
|
'message-receiver': message.sender !== userStore.userInfo.username,
|
||||||
'message-receiver':
|
|
||||||
message.sender !== userStore.userInfo.username,
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
{{ message.sender }}
|
{{ message.sender }}
|
||||||
@@ -124,16 +113,10 @@ interface MessageType {
|
|||||||
|
|
||||||
const messages = ref<MessageType[]>([]);
|
const messages = ref<MessageType[]>([]);
|
||||||
|
|
||||||
const topicMessage = ref(
|
const topicMessage = ref("亲爱的大冤种们,由于一只史诗级的BUG,系统版本已经被迫回退到了0.0.1。"); // 广播消息
|
||||||
"亲爱的大冤种们,由于一只史诗级的BUG,系统版本已经被迫回退到了0.0.1。"
|
|
||||||
); // 广播消息
|
|
||||||
|
|
||||||
const queneMessage = ref(
|
const queneMessage = ref(
|
||||||
"hi , " +
|
"hi , " + receiver.value + " , 我是" + userStore.userInfo.username + " , 想和你交个朋友 ! "
|
||||||
receiver.value +
|
|
||||||
" , 我是" +
|
|
||||||
userStore.userInfo.username +
|
|
||||||
" , 想和你交个朋友 ! "
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let stompClient: Client;
|
let stompClient: Client;
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ defineOptions({
|
|||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
errGif: new URL("../../assets/images/401.gif", import.meta.url).href,
|
errGif: new URL("../../assets/images/401.gif", import.meta.url).href,
|
||||||
ewizardClap:
|
ewizardClap: "https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",
|
||||||
"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",
|
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -24,9 +23,7 @@ function back() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<el-button icon="el-icon-arrow-left" class="pan-back-btn" @click="back">
|
<el-button icon="el-icon-arrow-left" class="pan-back-btn" @click="back">返回</el-button>
|
||||||
返回
|
|
||||||
</el-button>
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<h1 class="text-jumbo text-ginormous">Oops!</h1>
|
<h1 class="text-jumbo text-ginormous">Oops!</h1>
|
||||||
@@ -49,12 +46,7 @@ function back() {
|
|||||||
</ul>
|
</ul>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<img
|
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream." />
|
||||||
:src="errGif"
|
|
||||||
width="313"
|
|
||||||
height="428"
|
|
||||||
alt="Girl has dropped her ice cream."
|
|
||||||
/>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-dialog v-model="dialogVisible" title="随便看">
|
<el-dialog v-model="dialogVisible" title="随便看">
|
||||||
|
|||||||
@@ -16,44 +16,22 @@ function back() {
|
|||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<div class="pic-404">
|
<div class="pic-404">
|
||||||
<img class="pic-404__parent" src="@/assets/images/404.png" alt="404" />
|
<img class="pic-404__parent" src="@/assets/images/404.png" alt="404" />
|
||||||
<img
|
<img class="pic-404__child left" src="@/assets/images/404_cloud.png" alt="404" />
|
||||||
class="pic-404__child left"
|
<img class="pic-404__child mid" src="@/assets/images/404_cloud.png" alt="404" />
|
||||||
src="@/assets/images/404_cloud.png"
|
<img class="pic-404__child right" src="@/assets/images/404_cloud.png" alt="404" />
|
||||||
alt="404"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
class="pic-404__child mid"
|
|
||||||
src="@/assets/images/404_cloud.png"
|
|
||||||
alt="404"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
class="pic-404__child right"
|
|
||||||
src="@/assets/images/404_cloud.png"
|
|
||||||
alt="404"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="bullshit">
|
<div class="bullshit">
|
||||||
<div class="bullshit__oops">OOPS!</div>
|
<div class="bullshit__oops">OOPS!</div>
|
||||||
<div class="bullshit__info">
|
<div class="bullshit__info">
|
||||||
All rights reserved
|
All rights reserved
|
||||||
<a
|
<a style="color: #20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
|
||||||
style="color: #20a0ff"
|
|
||||||
href="https://wallstreetcn.com"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
wallstreetcn
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="bullshit__headline">
|
|
||||||
The webmaster said that you can not enter this page...
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="bullshit__headline">The webmaster said that you can not enter this page...</div>
|
||||||
<div class="bullshit__info">
|
<div class="bullshit__info">
|
||||||
Please check that the URL you entered is correct, or click the button
|
Please check that the URL you entered is correct, or click the button below to return to the
|
||||||
below to return to the homepage.
|
homepage.
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="bullshit__return-home" @click.prevent="back">
|
<a href="#" class="bullshit__return-home" @click.prevent="back">Back to home</a>
|
||||||
Back to home
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -38,19 +38,13 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
||||||
<el-dropdown-item
|
<el-dropdown-item @click="setLoginCredentials('root', '123456')">
|
||||||
@click="setLoginCredentials('root', '123456')"
|
|
||||||
>
|
|
||||||
超级管理员:root/123456
|
超级管理员:root/123456
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item @click="setLoginCredentials('admin', '123456')">
|
||||||
@click="setLoginCredentials('admin', '123456')"
|
|
||||||
>
|
|
||||||
系统管理员:admin/123456
|
系统管理员:admin/123456
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item @click="setLoginCredentials('test', '123456')">
|
||||||
@click="setLoginCredentials('test', '123456')"
|
|
||||||
>
|
|
||||||
测试小游客:test/123456
|
测试小游客:test/123456
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
@@ -76,11 +70,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 密码 -->
|
<!-- 密码 -->
|
||||||
<el-tooltip
|
<el-tooltip :visible="isCapslock" :content="$t('login.capsLock')" placement="right">
|
||||||
:visible="isCapslock"
|
|
||||||
:content="$t('login.capsLock')"
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper">
|
||||||
<el-icon class="mx-2">
|
<el-icon class="mx-2">
|
||||||
@@ -114,11 +104,7 @@
|
|||||||
@keyup.enter="handleLoginSubmit"
|
@keyup.enter="handleLoginSubmit"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<el-image
|
<el-image :src="captchaBase64" class="captcha-img" @click="getCaptcha" />
|
||||||
:src="captchaBase64"
|
|
||||||
class="captcha-img"
|
|
||||||
@click="getCaptcha"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -161,11 +147,7 @@
|
|||||||
<div class="login-footer">
|
<div class="login-footer">
|
||||||
<el-text size="small">
|
<el-text size="small">
|
||||||
Copyright © 2021 - 2024 youlai.tech All Rights Reserved.
|
Copyright © 2021 - 2024 youlai.tech All Rights Reserved.
|
||||||
<el-link
|
<el-link :underline="false" href="http://beian.miit.gov.cn/" target="_blank">
|
||||||
:underline="false"
|
|
||||||
href="http://beian.miit.gov.cn/"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
皖ICP备20006496号-2
|
皖ICP备20006496号-2
|
||||||
</el-link>
|
</el-link>
|
||||||
</el-text>
|
</el-text>
|
||||||
@@ -200,9 +182,7 @@ const isCapslock = ref(false); // 是否大写锁定
|
|||||||
const captchaBase64 = ref(); // 验证码图片Base64字符串
|
const captchaBase64 = ref(); // 验证码图片Base64字符串
|
||||||
|
|
||||||
const logo = ref(new URL("../../assets/logo.png", import.meta.url).href);
|
const logo = ref(new URL("../../assets/logo.png", import.meta.url).href);
|
||||||
const loginImage = ref(
|
const loginImage = ref(new URL("../../assets/images/login-image.svg", import.meta.url).href);
|
||||||
new URL("../../assets/images/login-image.svg", import.meta.url).href
|
|
||||||
);
|
|
||||||
|
|
||||||
const loginData = ref<LoginData>({
|
const loginData = ref<LoginData>({
|
||||||
username: "admin",
|
username: "admin",
|
||||||
@@ -300,8 +280,7 @@ function parseRedirect(): {
|
|||||||
|
|
||||||
// 主题切换
|
// 主题切换
|
||||||
const toggleTheme = () => {
|
const toggleTheme = () => {
|
||||||
const newTheme =
|
const newTheme = settingsStore.theme === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
|
||||||
settingsStore.theme === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
|
|
||||||
settingsStore.changeTheme(newTheme);
|
settingsStore.changeTheme(newTheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -332,8 +311,7 @@ onMounted(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: url("@/assets/images/login-background-light.jpg") no-repeat center
|
background: url("@/assets/images/login-background-light.jpg") no-repeat center right;
|
||||||
right;
|
|
||||||
|
|
||||||
.login-header {
|
.login-header {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -471,8 +449,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
html.dark {
|
html.dark {
|
||||||
.login {
|
.login {
|
||||||
background: url("@/assets/images/login-background-dark.jpg") no-repeat
|
background: url("@/assets/images/login-background-dark.jpg") no-repeat center right;
|
||||||
center right;
|
|
||||||
|
|
||||||
.login-content {
|
.login-content {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|||||||
@@ -16,12 +16,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
@click="triggerFileUpload"
|
@click="triggerFileUpload"
|
||||||
/>
|
/>
|
||||||
<input
|
<input ref="fileInput" type="file" style="display: none" @change="handleFileChange" />
|
||||||
ref="fileInput"
|
|
||||||
type="file"
|
|
||||||
style="display: none"
|
|
||||||
@change="handleFileChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
{{ userProfile.nickname }}
|
{{ userProfile.nickname }}
|
||||||
@@ -41,10 +36,7 @@
|
|||||||
用户名
|
用户名
|
||||||
</template>
|
</template>
|
||||||
{{ userProfile.username }}
|
{{ userProfile.username }}
|
||||||
<el-icon
|
<el-icon v-if="userProfile.gender === 1" class="align-middle color-blue">
|
||||||
v-if="userProfile.gender === 1"
|
|
||||||
class="align-middle color-blue"
|
|
||||||
>
|
|
||||||
<Male />
|
<Male />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<el-icon v-else class="align-middle color-pink">
|
<el-icon v-else class="align-middle color-pink">
|
||||||
@@ -117,9 +109,7 @@
|
|||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<div class="font-bold">绑定手机</div>
|
<div class="font-bold">绑定手机</div>
|
||||||
<div class="text-14px mt-2">
|
<div class="text-14px mt-2">
|
||||||
<span v-if="userProfile.mobile">
|
<span v-if="userProfile.mobile">已绑定手机号:{{ userProfile.mobile }}</span>
|
||||||
已绑定手机号:{{ userProfile.mobile }}
|
|
||||||
</span>
|
|
||||||
<span v-else>未绑定手机</span>
|
<span v-else>未绑定手机</span>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="userProfile.mobile"
|
v-if="userProfile.mobile"
|
||||||
@@ -147,9 +137,7 @@
|
|||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<div class="font-bold">绑定邮箱</div>
|
<div class="font-bold">绑定邮箱</div>
|
||||||
<div class="text-14px mt-2">
|
<div class="text-14px mt-2">
|
||||||
<span v-if="userProfile.email">
|
<span v-if="userProfile.email">已绑定邮箱:{{ userProfile.email }}</span>
|
||||||
已绑定邮箱:{{ userProfile.email }}
|
|
||||||
</span>
|
|
||||||
<span v-else>未绑定邮箱</span>
|
<span v-else>未绑定邮箱</span>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="userProfile.email"
|
v-if="userProfile.email"
|
||||||
@@ -203,25 +191,13 @@
|
|||||||
:label-width="100"
|
:label-width="100"
|
||||||
>
|
>
|
||||||
<el-form-item label="原密码" prop="oldPassword">
|
<el-form-item label="原密码" prop="oldPassword">
|
||||||
<el-input
|
<el-input v-model="passwordChangeForm.oldPassword" type="password" show-password />
|
||||||
v-model="passwordChangeForm.oldPassword"
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="新密码" prop="newPassword">
|
<el-form-item label="新密码" prop="newPassword">
|
||||||
<el-input
|
<el-input v-model="passwordChangeForm.newPassword" type="password" show-password />
|
||||||
v-model="passwordChangeForm.newPassword"
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
<el-form-item label="确认密码" prop="confirmPassword">
|
||||||
<el-input
|
<el-input v-model="passwordChangeForm.confirmPassword" type="password" show-password />
|
||||||
v-model="passwordChangeForm.confirmPassword"
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<!-- 绑定手机 -->
|
<!-- 绑定手机 -->
|
||||||
@@ -243,11 +219,7 @@
|
|||||||
:disabled="mobileCountdown > 0"
|
:disabled="mobileCountdown > 0"
|
||||||
@click="handleSendVerificationCode('MOBILE')"
|
@click="handleSendVerificationCode('MOBILE')"
|
||||||
>
|
>
|
||||||
{{
|
{{ mobileCountdown > 0 ? `${mobileCountdown}s后重新发送` : "发送验证码" }}
|
||||||
mobileCountdown > 0
|
|
||||||
? `${mobileCountdown}s后重新发送`
|
|
||||||
: "发送验证码"
|
|
||||||
}}
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
@@ -273,11 +245,7 @@
|
|||||||
:disabled="emailCountdown > 0"
|
:disabled="emailCountdown > 0"
|
||||||
@click="handleSendVerificationCode('EMAIL')"
|
@click="handleSendVerificationCode('EMAIL')"
|
||||||
>
|
>
|
||||||
{{
|
{{ emailCountdown > 0 ? `${emailCountdown}s后重新发送` : "发送验证码" }}
|
||||||
emailCountdown > 0
|
|
||||||
? `${emailCountdown}s后重新发送`
|
|
||||||
: "发送验证码"
|
|
||||||
}}
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
@@ -336,9 +304,7 @@ const emailTimer = ref<NodeJS.Timeout | null>(null);
|
|||||||
const passwordChangeRules = {
|
const passwordChangeRules = {
|
||||||
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
|
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
|
||||||
newPassword: [{ required: true, message: "请输入新密码", trigger: "blur" }],
|
newPassword: [{ required: true, message: "请输入新密码", trigger: "blur" }],
|
||||||
confirmPassword: [
|
confirmPassword: [{ required: true, message: "请再次输入新密码", trigger: "blur" }],
|
||||||
{ required: true, message: "请再次输入新密码", trigger: "blur" },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 手机号校验规则
|
// 手机号校验规则
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
v-hasPerm="['sys:dept:add']"
|
v-hasPerm="['sys:dept:add']"
|
||||||
type="success"
|
type="success"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
@click="handleOpenDialog(0, undefined)"
|
@click="handleOpenDialog()"
|
||||||
>
|
>
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|||||||
@@ -32,12 +32,8 @@
|
|||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="发布状态:">
|
<el-descriptions-item label="发布状态:">
|
||||||
<el-tag v-if="notice.publishStatus == 0" type="info">未发布</el-tag>
|
<el-tag v-if="notice.publishStatus == 0" type="info">未发布</el-tag>
|
||||||
<el-tag v-else-if="notice.publishStatus == 1" type="success">
|
<el-tag v-else-if="notice.publishStatus == 1" type="success">已发布</el-tag>
|
||||||
已发布
|
<el-tag v-else-if="notice.publishStatus == -1" type="warning">已撤回</el-tag>
|
||||||
</el-tag>
|
|
||||||
<el-tag v-else-if="notice.publishStatus == -1" type="warning">
|
|
||||||
已撤回
|
|
||||||
</el-tag>
|
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="发布人:">
|
<el-descriptions-item label="发布人:">
|
||||||
{{ notice.publisherName }}
|
{{ notice.publisherName }}
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ const handleFileExceed = () => {
|
|||||||
const handleDownloadTemplate = () => {
|
const handleDownloadTemplate = () => {
|
||||||
UserAPI.downloadTemplate().then((response: any) => {
|
UserAPI.downloadTemplate().then((response: any) => {
|
||||||
const fileData = response.data;
|
const fileData = response.data;
|
||||||
const fileName = decodeURI(
|
const fileName = decodeURI(response.headers["content-disposition"].split(";")[1].split("=")[1]);
|
||||||
response.headers["content-disposition"].split(";")[1].split("=")[1]
|
|
||||||
);
|
|
||||||
const fileType =
|
const fileType =
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user