init
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
.vscode
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
package-lock.json
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
/service/dev
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
yarn.lock
|
||||||
|
*.tsbuildinfo
|
||||||
|
*.env
|
||||||
|
src
|
||||||
|
sub
|
||||||
|
rbBuildAll.bat
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
FROM registry.cn-shanghai.aliyuncs.com/devcon/node:18
|
||||||
|
RUN git clone https://wujiefeng:sange666@git.u8t.cn/batiao/cy-admin.git
|
||||||
|
RUN mv cy-admin /app
|
||||||
|
ADD . /app/src
|
||||||
|
WORKDIR /app
|
||||||
|
RUN mkdir /app/log
|
||||||
|
RUN cd /app && \
|
||||||
|
chmod +x start.sh && \
|
||||||
|
npm config set registry https://registry.npmmirror.com/ && \
|
||||||
|
npm run installModels && \
|
||||||
|
npm run build
|
||||||
|
EXPOSE 9290
|
||||||
|
CMD [ "/app/start.sh" ]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import roleApi from './role';
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/user',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/user',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/user',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/user',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getRoleList() {
|
||||||
|
return roleApi.getDataList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import sourceApi from '../config/source';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getDataList() {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/role',
|
||||||
|
method: 'get',
|
||||||
|
params: {}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/role',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/role',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/role',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getResources: sourceApi.getDataList,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
upload(data: any) {
|
||||||
|
return Request({
|
||||||
|
url: "/admin/cmp_upload",
|
||||||
|
method: "post",
|
||||||
|
data,
|
||||||
|
params: {
|
||||||
|
expire: 24 * 30 * 12 * 10,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
}).then(res => ({ data: {url: res.data} }))
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
|
||||||
|
// 翻译
|
||||||
|
export const translateApi = {
|
||||||
|
translate(params: { text: string, from?: string, to?: string }) {
|
||||||
|
return Request({
|
||||||
|
url: "yt/translate",
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类
|
||||||
|
export const categoryApi = {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/category',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/category',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/category',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/category',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 上传
|
||||||
|
export const uploadApi = {
|
||||||
|
upload(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/upload',
|
||||||
|
method: 'post',
|
||||||
|
data: params,
|
||||||
|
params: {
|
||||||
|
expire: 24 * 30 * 12 * 10,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/page',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/page',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/page',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/page',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/resource',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/resource',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/resource',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/resource',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import { categoryApi, translateApi, uploadApi } from '../common';
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/doc',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/doc',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/doc',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/doc',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getDetail(id: number | string) {
|
||||||
|
return Request({
|
||||||
|
url: `yt/doc/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCategoryList: categoryApi.getDataList,
|
||||||
|
...translateApi,
|
||||||
|
...uploadApi,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { categoryApi } from "../common";
|
||||||
|
export default categoryApi
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import { categoryApi, translateApi } from '../common';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/process',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/process',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/process',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/process',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getDetail(id: number | string) {
|
||||||
|
return Request({
|
||||||
|
url: `yt/process/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCategoryList: categoryApi.getDataList,
|
||||||
|
...translateApi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { categoryApi } from "../common";
|
||||||
|
export default categoryApi
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import { translateApi, categoryApi } from '../common';
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/job',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/job',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/job',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/job',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getDetail(id: number | string) {
|
||||||
|
return Request({
|
||||||
|
url: `yt/job/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCategoryList: categoryApi.getDataList,
|
||||||
|
...translateApi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { categoryApi } from "../common";
|
||||||
|
export default categoryApi
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
login(data: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/user/login',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
account: data.username,
|
||||||
|
password: data.password
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetPassWord(data: any) {
|
||||||
|
return Request({
|
||||||
|
url: "/admin/v2",
|
||||||
|
method: "put",
|
||||||
|
data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
editorConfig(data: any) {
|
||||||
|
return Request({
|
||||||
|
url: "/corp/config",
|
||||||
|
method: "put",
|
||||||
|
data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getConfig() {
|
||||||
|
return Request({
|
||||||
|
url: "/corp/config",
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
flashRole(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: "/corp/flash/role",
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import Request from "lib/utils/requests";
|
||||||
|
import { translateApi, categoryApi, uploadApi } from '../common';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getDataList(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/news',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/news',
|
||||||
|
method: 'put',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/news',
|
||||||
|
method: 'delete',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addData(params: any) {
|
||||||
|
return Request({
|
||||||
|
url: 'yt/news',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getDetail(id: number | string) {
|
||||||
|
return Request({
|
||||||
|
url: `yt/news/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getCategoryList: categoryApi.getDataList,
|
||||||
|
...translateApi,
|
||||||
|
...uploadApi,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import { categoryApi } from "../common";
|
||||||
|
export default categoryApi
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import type { App } from 'vue'
|
||||||
|
|
||||||
|
export default function BeforeMount(app:App<Element>){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,544 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :model-value="show" width="800" :fullscreen="isFullscreen" :close-on-click-modal="false" @close="close"
|
||||||
|
:show-close="false">
|
||||||
|
<template #header>
|
||||||
|
<div class="dialog-header">
|
||||||
|
<span class="dialog-title">{{ title }}</span>
|
||||||
|
<div class="dialog-header-actions">
|
||||||
|
<el-button link circle @click="toggleFullscreen" :title="isFullscreen ? '退出全屏' : '全屏'">
|
||||||
|
<el-icon>
|
||||||
|
<CopyDocument v-if="isFullscreen" />
|
||||||
|
<FullScreen v-else />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<el-button link circle @click="close" title="关闭">
|
||||||
|
<el-icon size="18">
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-form v-if="show" ref="formRef" :model="formData" :rules="formRules" label-position="left"
|
||||||
|
v-loading="detailLoading">
|
||||||
|
|
||||||
|
<div v-if="normalFields.length" class="in18-form-top">
|
||||||
|
<el-form-item v-for="item in normalFields" :key="item.key" :prop="item.key">
|
||||||
|
<template #label>
|
||||||
|
{{ item.name }}
|
||||||
|
</template>
|
||||||
|
<el-input v-if="item.type === 'input'" v-model="formData[item.key]"
|
||||||
|
:placeholder="`请输入${item.name}`" />
|
||||||
|
<el-input v-else-if="item.type === 'textarea'" v-model="formData[item.key]" type="textarea"
|
||||||
|
:rows="4" :placeholder="`请输入${item.name}`" />
|
||||||
|
<el-select v-else-if="item.type === 'select'" v-model="formData[item.key]"
|
||||||
|
:placeholder="`请选择${item.name}`" clearable style="width: 100%">
|
||||||
|
<el-option v-for="opt in getSelectItems(item)" :key="opt.key" :label="opt.name"
|
||||||
|
:value="opt.key" />
|
||||||
|
</el-select>
|
||||||
|
<div v-else-if="isUploadMediaType(item.type)" style="width:100%;">
|
||||||
|
<div class="upload-group">
|
||||||
|
<div class="upload-label">图片</div>
|
||||||
|
<UploadInput :model-value="(formData[item.key]?.image || []).join(',')"
|
||||||
|
:type="item.type.includes('images') ? 'images' : 'image'"
|
||||||
|
:uploadFile="uploadFun" @update:modelValue="(val: string) => {
|
||||||
|
if (!formData[item.key]) formData[item.key] = { image: [], video: [] };
|
||||||
|
formData[item.key].image = val ? val.split(',').filter(Boolean) : [];
|
||||||
|
}" />
|
||||||
|
</div>
|
||||||
|
<div class="upload-group">
|
||||||
|
<div class="upload-label">视频</div>
|
||||||
|
<UploadInput :model-value="(formData[item.key]?.video || []).join(',')" type="video"
|
||||||
|
:uploadFile="uploadFun" @update:modelValue="(val: string) => {
|
||||||
|
if (!formData[item.key]) formData[item.key] = { image: [], video: [] };
|
||||||
|
formData[item.key].video = val ? val.split(',').filter(Boolean) : [];
|
||||||
|
}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.type === 'upload:file'" style="width:100%;" class="upload-file">
|
||||||
|
<UploadInput :model-value="formData[item.key]" type="file" :accept="item.accept || '*'"
|
||||||
|
:uploadFile="uploadFun"
|
||||||
|
@update:modelValue="(val: string) => { formData[item.key] = val }" />
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="in18-form-header">
|
||||||
|
<div class="in18-form-header-left">
|
||||||
|
<span>{{ primaryLocale?.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="in18-form-header-right">
|
||||||
|
<span v-for="locale in secondaryLocales" :key="locale.key" class="locale-tab"
|
||||||
|
:class="{ active: activeSecondaryLocale?.key === locale.key }"
|
||||||
|
@click="activeSecondaryLocale = locale">
|
||||||
|
{{ locale.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="translateFields.length && secondaryLocales.length" class="in18-form-wrapper">
|
||||||
|
<div class="in18-form-left">
|
||||||
|
<el-form-item v-for="item in translateFields" :key="item.key"
|
||||||
|
:prop="`translations.${primaryLocaleKey}.${item.key}`">
|
||||||
|
<template #label>
|
||||||
|
{{ item.name }}
|
||||||
|
</template>
|
||||||
|
<el-input v-if="item.type === 'input'"
|
||||||
|
v-model="formData.translations[primaryLocaleKey][item.key]"
|
||||||
|
:placeholder="`请输入${item.name}`" />
|
||||||
|
<el-input v-else-if="item.type === 'textarea'"
|
||||||
|
v-model="formData.translations[primaryLocaleKey][item.key]" type="textarea"
|
||||||
|
:rows="4" :placeholder="`请输入${item.name}`" />
|
||||||
|
<el-select v-else-if="item.type === 'select'"
|
||||||
|
v-model="formData.translations[primaryLocaleKey][item.key]"
|
||||||
|
:placeholder="`请选择${item.name}`" clearable style="width: 100%">
|
||||||
|
<el-option v-for="opt in getSelectItems(item)" :key="opt.key" :label="opt.name"
|
||||||
|
:value="opt.key" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<div class="in18-form-center">
|
||||||
|
<el-button v-if="activeSecondaryLocale" type="primary" :loading="translating"
|
||||||
|
@click="handleTranslate">
|
||||||
|
翻译
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div v-if="activeSecondaryLocale" class="in18-form-right">
|
||||||
|
<el-form-item v-for="item in translateFields" :key="item.key">
|
||||||
|
<template #label>
|
||||||
|
{{ item.name }}
|
||||||
|
</template>
|
||||||
|
<div v-if="item.type === 'input' || item.type === 'textarea'" class="field-with-translate">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.translations[activeSecondaryLocale?.key || ''][item.key]"
|
||||||
|
:type="item.type === 'textarea' ? 'textarea' : undefined"
|
||||||
|
:rows="item.type === 'textarea' ? 4 : undefined"
|
||||||
|
:placeholder="`请输入${item.name}`" />
|
||||||
|
<el-button link size="small" class="translate-icon"
|
||||||
|
:loading="translatingFieldKey === item.key" @click="handleTranslateField(item.key)"
|
||||||
|
title="翻译该字段">
|
||||||
|
<el-icon color="#409eff">
|
||||||
|
<Promotion />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-select v-else-if="item.type === 'select'"
|
||||||
|
v-model="formData.translations[activeSecondaryLocale?.key || ''][item.key]"
|
||||||
|
:placeholder="`请选择${item.name}`" clearable style="width: 100%">
|
||||||
|
<el-option v-for="opt in getSelectItems(item)" :key="opt.key" :label="opt.name"
|
||||||
|
:value="opt.key" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submit">确认提交</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, computed, watch, ref, nextTick } from 'vue'
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { Close, Promotion, FullScreen, CopyDocument } from '@element-plus/icons-vue'
|
||||||
|
import UploadInput from "lib/components/UploadInput.vue";
|
||||||
|
|
||||||
|
type FormItemType =
|
||||||
|
| 'input'
|
||||||
|
| 'select'
|
||||||
|
| 'textarea'
|
||||||
|
| 'upload:images,video'
|
||||||
|
| 'upload:image,video'
|
||||||
|
| 'upload:file'
|
||||||
|
|
||||||
|
type FormItem = {
|
||||||
|
name: string
|
||||||
|
key: string
|
||||||
|
type: FormItemType
|
||||||
|
value: string | number | { image: string[]; video: string[] }
|
||||||
|
items?: { key: string; name: string }[]
|
||||||
|
getItems?: () => { key: string; name: string }[]
|
||||||
|
must?: boolean
|
||||||
|
shouldTranslate?: boolean
|
||||||
|
accept?: string
|
||||||
|
[prop: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocaleItem = {
|
||||||
|
name: string
|
||||||
|
key: string
|
||||||
|
isPrimary?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
show: boolean
|
||||||
|
id: string | number
|
||||||
|
title?: string
|
||||||
|
form: FormItem[]
|
||||||
|
locales: LocaleItem[]
|
||||||
|
translateApi: (data: { text: string; from?: string; to?: string }) => Promise<any>
|
||||||
|
detailApi: (id: number) => Promise<any>
|
||||||
|
uploadFun?: (formData: FormData) => Promise<any>
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
show: false,
|
||||||
|
id: '',
|
||||||
|
title: '详情',
|
||||||
|
form: () => [],
|
||||||
|
locales: () => [],
|
||||||
|
translateApi: () => Promise.reject({ code: 500, message: 'translateApi not implemented' }),
|
||||||
|
detailApi: () => Promise.reject({ code: 500, message: 'detailApi not implemented' }),
|
||||||
|
uploadFun: () => Promise.reject({ code: 500, message: 'uploadFun not implemented' }),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'submit'])
|
||||||
|
|
||||||
|
const primaryLocale = computed(() => props.locales.find((l) => l.isPrimary) || props.locales[0])
|
||||||
|
const primaryLocaleKey = computed(() => primaryLocale.value?.key || 'ZH')
|
||||||
|
const secondaryLocales = computed(() => props.locales.filter((l) => !l.isPrimary))
|
||||||
|
const activeSecondaryLocale = ref<LocaleItem | null>(null)
|
||||||
|
const normalFields = computed(() => props.form.filter((f) => !f.shouldTranslate))
|
||||||
|
const translateFields = computed(() => props.form.filter((f) => f.shouldTranslate))
|
||||||
|
|
||||||
|
function isUploadMediaType(type: string): boolean {
|
||||||
|
return type === 'upload:images,video' || type === 'upload:image,video'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectItems(item: FormItem): { key: string; name: string }[] {
|
||||||
|
return item.items ?? item.getItems?.() ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTranslateResult(res: any): string {
|
||||||
|
return res?.data?.text ?? res?.data ?? res?.result ?? (typeof res === 'string' ? res : '')
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
const formRules = computed<FormRules>(() => {
|
||||||
|
const rules: FormRules = {}
|
||||||
|
normalFields.value.forEach((item) => {
|
||||||
|
if (item.must) {
|
||||||
|
rules[item.key] = [{ required: true, message: `请输入${item.name}`, trigger: ['blur', 'change'] }]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
translateFields.value.forEach((item) => {
|
||||||
|
if (item.must) {
|
||||||
|
const prop = `translations.${primaryLocaleKey.value}.${item.key}`
|
||||||
|
rules[prop] = [{ required: true, message: `请输入${item.name}`, trigger: ['blur', 'change'] }]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rules
|
||||||
|
})
|
||||||
|
|
||||||
|
const formData = reactive<{
|
||||||
|
[key: string]: any
|
||||||
|
translations: Record<string, Record<string, any>>
|
||||||
|
}>({
|
||||||
|
translations: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const translating = ref(false)
|
||||||
|
const translatingFieldKey = ref<string>('')
|
||||||
|
const isFullscreen = ref(false)
|
||||||
|
const detailLoading = ref(false)
|
||||||
|
|
||||||
|
function toggleFullscreen() {
|
||||||
|
isFullscreen.value = !isFullscreen.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetFormData() {
|
||||||
|
Object.keys(formData).forEach((k) => {
|
||||||
|
if (k !== 'translations') delete formData[k]
|
||||||
|
})
|
||||||
|
formData.translations = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initFormData() {
|
||||||
|
const normal: Record<string, any> = {}
|
||||||
|
const translations: Record<string, Record<string, any>> = {}
|
||||||
|
|
||||||
|
props.form.forEach((item) => {
|
||||||
|
if (item.shouldTranslate) {
|
||||||
|
props.locales.forEach((locale) => {
|
||||||
|
if (!translations[locale.key]) translations[locale.key] = {}
|
||||||
|
translations[locale.key][item.key] = item.value ?? ''
|
||||||
|
})
|
||||||
|
} else if (isUploadMediaType(item.type)) {
|
||||||
|
const val: any = item.value
|
||||||
|
normal[item.key] = (val && typeof val === 'object' && Array.isArray(val.image) && Array.isArray(val.video))
|
||||||
|
? val
|
||||||
|
: { image: [], video: [] }
|
||||||
|
} else {
|
||||||
|
normal[item.key] = item.value ?? ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(formData).forEach((k) => {
|
||||||
|
if (k !== 'translations') delete formData[k]
|
||||||
|
})
|
||||||
|
Object.keys(normal).forEach((k) => {
|
||||||
|
formData[k] = normal[k]
|
||||||
|
})
|
||||||
|
formData.translations = translations
|
||||||
|
|
||||||
|
if (secondaryLocales.value.length > 0 && !activeSecondaryLocale.value) {
|
||||||
|
activeSecondaryLocale.value = secondaryLocales.value[0]
|
||||||
|
} else if (secondaryLocales.value.length > 0) {
|
||||||
|
const stillExists = secondaryLocales.value.some((l) => l.key === activeSecondaryLocale.value?.key)
|
||||||
|
if (!stillExists) {
|
||||||
|
activeSecondaryLocale.value = secondaryLocales.value[0]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
activeSecondaryLocale.value = null
|
||||||
|
}
|
||||||
|
nextTick(() => formRef.value?.clearValidate())
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.show, props.form, props.locales],
|
||||||
|
async () => {
|
||||||
|
if (props.show) {
|
||||||
|
initFormData()
|
||||||
|
if (props.id) {
|
||||||
|
detailLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = await props.detailApi(Number(props.id))
|
||||||
|
if (data) {
|
||||||
|
const pKey = primaryLocaleKey.value
|
||||||
|
Object.keys(data).forEach((localeKey) => {
|
||||||
|
const localeData = data[localeKey]
|
||||||
|
if (!localeData || typeof localeData !== 'object' || !props.locales.some((l) => l.key === localeKey)) return
|
||||||
|
Object.keys(localeData).forEach((fieldKey) => {
|
||||||
|
const field = props.form.find((f) => f.key === fieldKey)
|
||||||
|
if (!field) return
|
||||||
|
if (field.shouldTranslate) {
|
||||||
|
if (!formData.translations[localeKey]) formData.translations[localeKey] = {}
|
||||||
|
formData.translations[localeKey][fieldKey] = localeData[fieldKey]
|
||||||
|
} else if (localeKey === pKey) {
|
||||||
|
formData[fieldKey] = localeData[fieldKey]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load detail:', e)
|
||||||
|
ElMessage.error('加载详情失败')
|
||||||
|
} finally {
|
||||||
|
detailLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
isFullscreen.value = false
|
||||||
|
resetFormData()
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleTranslate() {
|
||||||
|
if (!primaryLocale.value || !activeSecondaryLocale.value || translating.value) return
|
||||||
|
|
||||||
|
const fromKey = primaryLocale.value.key
|
||||||
|
const toKey = activeSecondaryLocale.value.key
|
||||||
|
const texts: { key: string; text: string }[] = []
|
||||||
|
|
||||||
|
translateFields.value.forEach((item) => {
|
||||||
|
const val = formData.translations?.[fromKey]?.[item.key]
|
||||||
|
if (val != null && String(val).trim()) {
|
||||||
|
texts.push({ key: item.key, text: String(val).trim() })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (texts.length === 0) return
|
||||||
|
|
||||||
|
translating.value = true
|
||||||
|
try {
|
||||||
|
const results = await Promise.allSettled(
|
||||||
|
texts.map(async ({ key, text }) => {
|
||||||
|
const res = await props.translateApi({ text, from: fromKey, to: toKey })
|
||||||
|
return { key, translated: parseTranslateResult(res) }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
let failCount = 0
|
||||||
|
for (const result of results) {
|
||||||
|
if (result.status === 'fulfilled') {
|
||||||
|
const { key, translated } = result.value
|
||||||
|
if (formData.translations[toKey]) {
|
||||||
|
formData.translations[toKey][key] = translated
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
failCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failCount > 0) {
|
||||||
|
ElMessage.warning(`${failCount} 个字段翻译失败`)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Translate failed:', e)
|
||||||
|
ElMessage.error('翻译失败')
|
||||||
|
} finally {
|
||||||
|
translating.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleTranslateField(itemKey: string) {
|
||||||
|
if (!primaryLocale.value || !activeSecondaryLocale.value || translatingFieldKey.value) return
|
||||||
|
const fromKey = primaryLocale.value.key
|
||||||
|
const toKey = activeSecondaryLocale.value.key
|
||||||
|
const text = formData.translations?.[fromKey]?.[itemKey]
|
||||||
|
if (text == null || !String(text).trim()) return
|
||||||
|
translatingFieldKey.value = itemKey
|
||||||
|
try {
|
||||||
|
const res = await props.translateApi({ text: String(text).trim(), from: fromKey, to: toKey })
|
||||||
|
if (formData.translations[toKey]) formData.translations[toKey][itemKey] = parseTranslateResult(res)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Translate failed:', e)
|
||||||
|
ElMessage.error('翻译失败')
|
||||||
|
} finally {
|
||||||
|
translatingFieldKey.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
try {
|
||||||
|
await formRef.value?.validate()
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data: Record<string, any> = { id: props.id || '' }
|
||||||
|
normalFields.value.forEach((item) => {
|
||||||
|
data[item.key] = formData[item.key]
|
||||||
|
})
|
||||||
|
if (Object.keys(formData.translations || {}).length > 0) {
|
||||||
|
data.translations = formData.translations
|
||||||
|
}
|
||||||
|
emit('submit', data)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.dialog-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 40px;
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-header {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid var(--el-border-color);
|
||||||
|
|
||||||
|
.in18-form-header-left,
|
||||||
|
.in18-form-header-right {
|
||||||
|
flex: 1;
|
||||||
|
padding: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-header-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.locale-tab {
|
||||||
|
padding: 5px 12px;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: var(--el-color-primary);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.active) {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-top {
|
||||||
|
padding: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
min-height: 200px;
|
||||||
|
border-bottom: 1px solid var(--el-border-color);
|
||||||
|
|
||||||
|
.in18-form-left,
|
||||||
|
.in18-form-right {
|
||||||
|
flex: 1;
|
||||||
|
padding: 15px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-left {
|
||||||
|
border-right: 1px solid var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-with-translate {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.el-input,
|
||||||
|
.el-textarea {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.translate-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.in18-form-center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 15px;
|
||||||
|
min-width: 80px;
|
||||||
|
border-right: 1px solid var(--el-border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :model-value="show" width="900" :fullscreen="isFullscreen" :close-on-click-modal="false" @close="close"
|
||||||
|
:show-close="false">
|
||||||
|
<template #header>
|
||||||
|
<div class="jfd-header">
|
||||||
|
<span class="jfd-title">{{ title }}</span>
|
||||||
|
<div class="jfd-header-actions">
|
||||||
|
<el-button link circle @click="isFullscreen = !isFullscreen"
|
||||||
|
:title="isFullscreen ? '退出全屏' : '全屏'">
|
||||||
|
<el-icon>
|
||||||
|
<CopyDocument v-if="isFullscreen" />
|
||||||
|
<FullScreen v-else />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<el-button link circle @click="close" title="关闭">
|
||||||
|
<el-icon size="18">
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-tabs v-if="langKeys.length" v-model="activeTab" type="border-card">
|
||||||
|
<el-tab-pane v-for="lang in langKeys" :key="lang" :label="lang" :name="lang">
|
||||||
|
<el-scrollbar max-height="60vh">
|
||||||
|
<div class="jfd-content">
|
||||||
|
<NodeEditor v-for="sKey in getSectionKeys(lang)" :key="sKey" :parent="formData[lang]"
|
||||||
|
:field-key="sKey" :field-map="fieldMap" :depth="0" />
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<el-empty v-else description="无数据" />
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submit">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch, defineComponent, h, type PropType, type VNode, type Component } from 'vue'
|
||||||
|
import { Close, FullScreen, CopyDocument, Plus, Delete } from '@element-plus/icons-vue'
|
||||||
|
import {
|
||||||
|
ElFormItem, ElInput, ElInputNumber, ElSwitch, ElButton,
|
||||||
|
ElCollapse, ElCollapseItem, ElIcon
|
||||||
|
} from 'element-plus'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
show: boolean
|
||||||
|
title?: string
|
||||||
|
data: Record<string, any>
|
||||||
|
fieldMap?: Record<string, string>
|
||||||
|
}>(), {
|
||||||
|
show: false,
|
||||||
|
title: '配置编辑',
|
||||||
|
data: () => ({}),
|
||||||
|
fieldMap: () => ({}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'submit'])
|
||||||
|
|
||||||
|
const isFullscreen = ref(false)
|
||||||
|
const formData = ref<Record<string, any>>({})
|
||||||
|
const activeTab = ref('')
|
||||||
|
|
||||||
|
const langKeys = computed(() => Object.keys(formData.value))
|
||||||
|
|
||||||
|
function getSectionKeys(lang: string) {
|
||||||
|
const langData = formData.value[lang]
|
||||||
|
return langData && typeof langData === 'object' ? Object.keys(langData) : []
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemTemplates: Record<string, any> = {}
|
||||||
|
|
||||||
|
function collectItemTemplates(data: any) {
|
||||||
|
if (data === null || data === undefined) return
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
if (data.length > 0 && typeof data[0] === 'object' && !Array.isArray(data[0])) {
|
||||||
|
for (const key of Object.keys(data[0])) {
|
||||||
|
collectItemTemplates(data[0][key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.forEach(item => collectItemTemplates(item))
|
||||||
|
} else if (typeof data === 'object') {
|
||||||
|
for (const key of Object.keys(data)) {
|
||||||
|
const val = data[key]
|
||||||
|
if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'object' && !Array.isArray(val[0])) {
|
||||||
|
if (!itemTemplates[key]) {
|
||||||
|
itemTemplates[key] = createEmpty(val[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectItemTemplates(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.show, (val) => {
|
||||||
|
if (val && props.data) {
|
||||||
|
formData.value = JSON.parse(JSON.stringify(props.data))
|
||||||
|
Object.keys(itemTemplates).forEach(k => delete itemTemplates[k])
|
||||||
|
const firstLang = langKeys.value[0]
|
||||||
|
if (firstLang) collectItemTemplates(formData.value[firstLang])
|
||||||
|
activeTab.value = firstLang || ''
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
isFullscreen.value = false
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
emit('submit', JSON.parse(JSON.stringify(formData.value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEmpty(template: any): any {
|
||||||
|
if (typeof template === 'string') return ''
|
||||||
|
if (typeof template === 'number') return 0
|
||||||
|
if (typeof template === 'boolean') return false
|
||||||
|
if (Array.isArray(template)) return []
|
||||||
|
if (typeof template === 'object' && template !== null) {
|
||||||
|
const obj: any = {}
|
||||||
|
for (const k of Object.keys(template)) obj[k] = createEmpty(template[k])
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeEditor: Component = defineComponent({
|
||||||
|
name: 'NodeEditor',
|
||||||
|
props: {
|
||||||
|
parent: { type: Object as PropType<any>, required: true },
|
||||||
|
fieldKey: { type: [String, Number] as PropType<string | number>, required: true },
|
||||||
|
fieldMap: { type: Object as PropType<Record<string, string>>, default: () => ({}) },
|
||||||
|
depth: { type: Number, default: 0 },
|
||||||
|
},
|
||||||
|
setup(p) {
|
||||||
|
return () => {
|
||||||
|
const value = p.parent[p.fieldKey]
|
||||||
|
const key = p.fieldKey
|
||||||
|
const fm = p.fieldMap
|
||||||
|
const depth = p.depth
|
||||||
|
const label = typeof key === 'string' ? (fm[key] || key) : `#${Number(key) + 1}`
|
||||||
|
|
||||||
|
if (value === null || value === undefined) return null
|
||||||
|
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return h(ElFormItem, { label, class: 'jfd-form-item' }, () =>
|
||||||
|
h(ElSwitch, {
|
||||||
|
modelValue: value,
|
||||||
|
'onUpdate:modelValue': (v: any) => { p.parent[key] = v },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return h(ElFormItem, { label, class: 'jfd-form-item' }, () =>
|
||||||
|
h(ElInputNumber, {
|
||||||
|
modelValue: value,
|
||||||
|
'onUpdate:modelValue': (v: number | undefined) => { p.parent[key] = v ?? 0 },
|
||||||
|
controlsPosition: 'right',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const isLong = value.length > 50
|
||||||
|
return h(ElFormItem, { label, class: 'jfd-form-item' }, () =>
|
||||||
|
h(ElInput, {
|
||||||
|
modelValue: value,
|
||||||
|
...(isLong ? { type: 'textarea', autosize: { minRows: 2, maxRows: 6 } } : {}),
|
||||||
|
'onUpdate:modelValue': (v: string) => { p.parent[key] = v },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
const keyStr = String(key)
|
||||||
|
const hasLiveObj = value.length > 0 && typeof value[0] === 'object' && !Array.isArray(value[0])
|
||||||
|
const savedTemplate = itemTemplates[keyStr]
|
||||||
|
const isObjArr = hasLiveObj || !!savedTemplate
|
||||||
|
|
||||||
|
if (!isObjArr) {
|
||||||
|
return h('div', { class: 'jfd-array-group' }, [
|
||||||
|
h('div', { class: 'jfd-group-header' }, [
|
||||||
|
h('span', { class: 'jfd-group-title' }, label),
|
||||||
|
h(ElButton, {
|
||||||
|
size: 'small', type: 'primary', link: true,
|
||||||
|
onClick: () => value.push(''),
|
||||||
|
}, () => [h(ElIcon, { size: 14 }, () => h(Plus)), ' 添加'])
|
||||||
|
]),
|
||||||
|
...value.map((_: any, i: number) =>
|
||||||
|
h('div', { class: 'jfd-string-item', key: i }, [
|
||||||
|
h(ElInput, {
|
||||||
|
modelValue: value[i],
|
||||||
|
'onUpdate:modelValue': (v: string) => { value[i] = v },
|
||||||
|
}),
|
||||||
|
h(ElButton, {
|
||||||
|
size: 'small', type: 'danger', link: true,
|
||||||
|
onClick: () => value.splice(i, 1),
|
||||||
|
}, () => h(ElIcon, { size: 14 }, () => h(Delete)))
|
||||||
|
])
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeNewItem = () => {
|
||||||
|
const tpl = hasLiveObj ? value[0] : savedTemplate
|
||||||
|
return JSON.parse(JSON.stringify(tpl ? createEmpty(tpl) : {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('div', { class: 'jfd-array-group' }, [
|
||||||
|
h('div', { class: 'jfd-group-header' }, [
|
||||||
|
h('span', { class: 'jfd-group-title' }, label),
|
||||||
|
h(ElButton, {
|
||||||
|
size: 'small', type: 'primary', link: true,
|
||||||
|
onClick: () => value.push(makeNewItem()),
|
||||||
|
}, () => [h(ElIcon, { size: 14 }, () => h(Plus)), ' 添加'])
|
||||||
|
]),
|
||||||
|
h(ElCollapse, { class: 'jfd-obj-array' }, () =>
|
||||||
|
value.map((item: any, i: number) => {
|
||||||
|
const tag = item.title || item.name || item.text || ''
|
||||||
|
return h(ElCollapseItem, {
|
||||||
|
title: `${label} #${i + 1}${tag ? ' - ' + tag : ''}`,
|
||||||
|
name: `${String(key)}-${i}`,
|
||||||
|
key: i,
|
||||||
|
}, () => [
|
||||||
|
...Object.keys(item).map(k =>
|
||||||
|
h(NodeEditor, { parent: item, fieldKey: k, fieldMap: fm, depth: depth + 1, key: k })
|
||||||
|
),
|
||||||
|
h('div', { class: 'jfd-item-actions' },
|
||||||
|
h(ElButton, {
|
||||||
|
size: 'small', type: 'danger',
|
||||||
|
onClick: () => value.splice(i, 1),
|
||||||
|
}, () => [h(ElIcon, { size: 14 }, () => h(Delete)), ' 删除此项'])
|
||||||
|
)
|
||||||
|
])
|
||||||
|
})
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
const children = Object.keys(value).map(k =>
|
||||||
|
h(NodeEditor, { parent: value, fieldKey: k, fieldMap: fm, depth: depth + 1, key: k })
|
||||||
|
)
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return h('div', { class: 'jfd-section' }, [
|
||||||
|
h('div', { class: 'jfd-section-header' }, label),
|
||||||
|
h('div', { class: 'jfd-section-body' }, children)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('div', { class: 'jfd-nested' }, [
|
||||||
|
h('div', { class: 'jfd-nested-title' }, label),
|
||||||
|
...children
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.jfd-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.jfd-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-content {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-form-item {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-section-header {
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 15px;
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
border-bottom: 1px solid var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-section-body {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-array-group {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-group-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-group-title {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-string-item {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-item-actions {
|
||||||
|
text-align: right;
|
||||||
|
margin-top: 8px;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px dashed var(--el-border-color-lighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-nested {
|
||||||
|
margin-left: 12px;
|
||||||
|
padding-left: 12px;
|
||||||
|
border-left: 2px solid var(--el-border-color);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-nested-title {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfd-obj-array .el-collapse-item__header {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"title": "工商年报",
|
||||||
|
"baseUrl": "/companyHome",
|
||||||
|
"tokenKey": "token",
|
||||||
|
"messageDuration": 3000,
|
||||||
|
"requestTimeout": 60000,
|
||||||
|
"successCode": [
|
||||||
|
200,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"invalidCode": [
|
||||||
|
1001106,
|
||||||
|
1001003,
|
||||||
|
11009
|
||||||
|
],
|
||||||
|
"menus":false,
|
||||||
|
"noLogin": false,
|
||||||
|
"mainColor": "#1677ff",
|
||||||
|
"port": 9290 ,
|
||||||
|
"noPermissionCode": 401,
|
||||||
|
"rbBuldInfo": {
|
||||||
|
"api": "http://rb2.batiao8.com/console/custom/deploy/f5b5219cce4a7d47a60416ef4d3fa891",
|
||||||
|
"key": "bNJXlzwc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 语言
|
||||||
|
export const LOCALES = [
|
||||||
|
{
|
||||||
|
name: '中文',
|
||||||
|
key: 'ZH',
|
||||||
|
isPrimary: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'English',
|
||||||
|
key: 'EN',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 分类
|
||||||
|
export const categoryTypes = [
|
||||||
|
{ key: 'process', name: '历程', path: '/history' },
|
||||||
|
{ key: 'news', name: '新闻', path: '/news' },
|
||||||
|
{ key: 'file', name: '文件', path: '/document' },
|
||||||
|
{ key: 'job', name: '招聘', path: '/jobs' },
|
||||||
|
{ key: 'job_type', name: '职业类型', path: '/jobs' },
|
||||||
|
{ key: 'job_area', name: '业务领域', path: '/jobs' },
|
||||||
|
{ key: 'job_unit', name: '所属板块', path: '/jobs' },
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
.upload-flie {
|
||||||
|
.el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.avatar-uploader-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8c939d;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded-img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
import type { TopLayoutType } from 'lib/type/TopLayout'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { indexStore } from 'lib/stores'
|
||||||
|
import login from 'src/api/login'
|
||||||
|
import clipboard from 'clipboard'
|
||||||
|
import 'src/layout/TopLayout.scss'
|
||||||
|
import TableLayout from 'lib/layout/TableLayout.vue'
|
||||||
|
import message from 'lib/utils/message'
|
||||||
|
import type { Form, FormData } from 'lib/type/TableData'
|
||||||
|
import { formatConfig } from 'src/tools'
|
||||||
|
|
||||||
|
// const TableLayout: any = utils.deepClone(tl)
|
||||||
|
const store = indexStore()
|
||||||
|
const data: TopLayoutType = {
|
||||||
|
userButtons: [
|
||||||
|
// {
|
||||||
|
// name: '修改配置',
|
||||||
|
// type: 'success',
|
||||||
|
// icon: 'EditPen',
|
||||||
|
// onClick(self) {
|
||||||
|
// self.methods?.getConfig(self)
|
||||||
|
// ;(self.bean as any).configForm.show = 'form'
|
||||||
|
// }
|
||||||
|
// // getHide() {
|
||||||
|
// // return store.$state.kwargs.role != 1
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '用户信息',
|
||||||
|
// type: 'success',
|
||||||
|
// icon: 'User',
|
||||||
|
// onClick(self) {
|
||||||
|
// ;(self.bean as any).userInfoDialogShow = true
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '修改密码',
|
||||||
|
// type: 'warning',
|
||||||
|
// icon: 'Key',
|
||||||
|
// onClick(self) {
|
||||||
|
// ;(self.bean as any).resetPasswordDialogShow = true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
bean: {
|
||||||
|
userInfoDialogShow: false,
|
||||||
|
resetPasswordDialogShow: false,
|
||||||
|
resetPasswordInput: '',
|
||||||
|
resetPasswordInputOld: '',
|
||||||
|
resetPasswordInputTwo: '',
|
||||||
|
configForm: {
|
||||||
|
hideButton: true,
|
||||||
|
show: false,
|
||||||
|
data: [],
|
||||||
|
async subFun(self, data) {
|
||||||
|
// console.log(data)
|
||||||
|
for (const key in data){
|
||||||
|
if (typeof data[key] === "object" && Array.isArray(data[key])){
|
||||||
|
data[key] = data[key].join(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return login.editorConfig(data)
|
||||||
|
}
|
||||||
|
} as Form
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleEditorConfigSubmit(self: TopLayoutType) {
|
||||||
|
login.editorConfig((self.bean as any).editorConfigInfo).then((res: any) => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
ElMessage.success('配置修改成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.success('配置修改失败')
|
||||||
|
}
|
||||||
|
self.methods?.updateConfig(self)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleResetPasswordSubmit(self: TopLayoutType) {
|
||||||
|
if ((self.bean as any).resetPasswordInputOld === '') {
|
||||||
|
ElMessage.error('旧密码不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((self.bean as any).resetPasswordInput === '') {
|
||||||
|
ElMessage.error('密码不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((self.bean as any).resetPasswordInput !== (self.bean as any).resetPasswordInputTwo) {
|
||||||
|
ElMessage.error('两次输入的密码不一致')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
login
|
||||||
|
.resetPassWord({
|
||||||
|
old_password: (self.bean as any).resetPasswordInputOld,
|
||||||
|
password: (self.bean as any).resetPasswordInput
|
||||||
|
})
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('密码修改成功')
|
||||||
|
setTimeout(() => {
|
||||||
|
store.logout()
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
copy(text: string) {
|
||||||
|
clipboard.copy(text)
|
||||||
|
message.success('复制成功')
|
||||||
|
},
|
||||||
|
async getConfig(self: TopLayoutType) {
|
||||||
|
const res = await login.getConfig()
|
||||||
|
let formData: FormData[] = res.data
|
||||||
|
formData = formatConfig(formData)
|
||||||
|
;(self.bean as any).configForm.data = formData
|
||||||
|
}
|
||||||
|
},
|
||||||
|
launchTask: [
|
||||||
|
// async (self) => {
|
||||||
|
// const res = await login.getHomeData({})
|
||||||
|
// ;(self.bean as any).homeData = res.data
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
addNods: [
|
||||||
|
(self) => {
|
||||||
|
return (
|
||||||
|
<el-dialog width="500" append-to-body vModel={(self.bean as any).userInfoDialogShow}>
|
||||||
|
<el-form label-width="100">
|
||||||
|
<el-form-item label="名称:">
|
||||||
|
<div>{store.$state.kwargs.realname}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="角色:">
|
||||||
|
<div>{store.$state.kwargs.role_name}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="级别:">
|
||||||
|
<div>{store.$state.kwargs.level_name}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上级名称:">
|
||||||
|
<div>{store.$state.kwargs.parent_info.realname}</div>
|
||||||
|
</el-form-item>
|
||||||
|
{/* <el-form-item label="上级角色:">
|
||||||
|
<div>{store.$state.kwargs.parent_info.role_name}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上级级别:">
|
||||||
|
<div>{store.$state.kwargs.parent_info.level_name}</div>
|
||||||
|
</el-form-item> */}
|
||||||
|
{/*<el-form-item label="分享二维码:">*/}
|
||||||
|
{/* <img style={{*/}
|
||||||
|
{/* width:"256px",*/}
|
||||||
|
{/* height:"256px"*/}
|
||||||
|
{/* }} src={'data:image/png;base64,' + self.bean?.homeData.qrcode} />*/}
|
||||||
|
{/*</el-form-item>*/}
|
||||||
|
{/*<el-form-item label="分享链接:">*/}
|
||||||
|
{/* <div class="flex-row" style={{*/}
|
||||||
|
{/* alignItems:"center",*/}
|
||||||
|
{/* columnGap:"10px"*/}
|
||||||
|
{/* }}>*/}
|
||||||
|
{/* <span>{self.bean?.homeData.url}</span>*/}
|
||||||
|
{/* <el-button*/}
|
||||||
|
{/* type="primary"*/}
|
||||||
|
{/* size="small"*/}
|
||||||
|
{/* onClick={() => {*/}
|
||||||
|
{/* self.methods?.copy(self.bean?.homeData.url)*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/* >*/}
|
||||||
|
{/* 复制*/}
|
||||||
|
{/* </el-button>*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/*</el-form-item>*/}
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
(self) => {
|
||||||
|
return (
|
||||||
|
<el-dialog width="500" append-to-body vModel={(self.bean as any).resetPasswordDialogShow}>
|
||||||
|
<el-form label-width="80">
|
||||||
|
<el-form-item label="旧密码">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
vModel={(self.bean as any).resetPasswordInputOld}
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码">
|
||||||
|
<el-input type="password" vModel={(self.bean as any).resetPasswordInput}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="再次输入">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
vModel={(self.bean as any).resetPasswordInputTwo}
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
onClick={() => {
|
||||||
|
;(self.bean as any).resetPasswordDialogShow = false
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
;(self.methods as any).handleResetPasswordSubmit(self)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
(self) => {
|
||||||
|
let element: any = <></>
|
||||||
|
if (self.bean && TableLayout.methods) {
|
||||||
|
element = TableLayout.methods.createForm.call(
|
||||||
|
{
|
||||||
|
...TableLayout.methods,
|
||||||
|
...self.this_,
|
||||||
|
fetchData: () => {}
|
||||||
|
},
|
||||||
|
self.bean.configForm,
|
||||||
|
{
|
||||||
|
id: 'form'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "yintai-company-home-am",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": "https://git.u8t.cn/batiao/corp-bm.git",
|
||||||
|
"author": "YSASM <1613921123@qq.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@amap/amap-jsapi-loader": "^1.0.1"
|
||||||
|
},
|
||||||
|
"lib": "cy-admin"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import dotenv from "dotenv"
|
||||||
|
dotenv.config()
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const isDev = process.env.DEV
|
||||||
|
console.log("isDev:" + isDev)
|
||||||
|
export default {
|
||||||
|
'/companyHome': {
|
||||||
|
target: isDev ? "http://10.3.0.7:9999/":'https://companyapi.batiao8.com/',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/companyHome/, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_23_247"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_23_247)"><g><path d="M12.00706015625,1.47662353515625C6.21137015625,1.47662353515625,1.51416015625,6.17383353515625,1.51416015625,11.96952353515625C1.51416015625,17.76522353515625,6.21137015625,22.46242353515625,12.00706015625,22.46242353515625C17.80276015625,22.46242353515625,22.49996015625,17.76522353515625,22.49996015625,11.96952353515625C22.49996015625,6.17383353515625,17.80276015625,1.47662353515625,12.00706015625,1.47662353515625ZM16.18026015625,10.95350353515625C16.18026015625,11.39236353515625,15.85046015625,11.72482353515625,15.40896015625,11.72482353515625L12.89016015625,11.72482353515625L12.89016015625,13.29142353515625L15.40896015625,13.29142353515625C15.84786015625,13.29142353515625,16.18026015625,13.62132353515625,16.18026015625,14.06282353515625L16.18026015625,14.20112353515625C16.18026015625,14.64002353515625,15.85046015625,14.97242353515625,15.40896015625,14.97242353515625L12.89016015625,14.97242353515625L12.89016015625,16.65872353515625C12.89016015625,17.097623535156252,12.56036015625,17.43012353515625,12.11876015625,17.43012353515625L11.91926015625,17.43012353515625C11.51506015625,17.37422353515625,11.21180015625,17.02052353515625,11.21180015625,16.61622353515625L11.21180015625,14.97512353515625L8.599870156249999,14.97512353515625C8.16101015625,14.97512353515625,7.82853015625,14.64532353515625,7.82853015625,14.20382353515625L7.82853015625,14.06542353515625C7.82853015625,13.62662353515625,8.15835015625,13.29412353515625,8.599870156249999,13.29412353515625L11.21180015625,13.29412353515625L11.21180015625,11.72752353515625L8.599870156249999,11.72752353515625C8.16101015625,11.72752353515625,7.82853015625,11.39768353515625,7.82853015625,10.95616353515625L7.82853015625,10.81785353515625C7.82853015625,10.37898353515625,8.15835015625,10.04650353515625,8.599870156249999,10.04650353515625L11.23574015625,10.04650353515625L9.254180156250001,7.93462353515625C8.940330156249999,7.62076353515625,8.96161015625,7.08614353515625,9.30206015625,6.74569353515625C9.61592015625,6.43183353515625,10.15054015625,6.45045353515625,10.49365015625,6.79356353515625L10.49631015625,6.79622353515625L12.04166015625,8.445303535156249L13.65886015625,6.93187353515625C13.97266015625,6.61802353515625,14.50726015625,6.63930353515625,14.84776015625,6.97975353515625L14.85576015625,6.98773353515625C15.13766015625,7.32553353515625,15.11376015625,7.81227353515625,14.80256015625,8.12347353515625L14.79986015625,8.12613353515625L12.74916015625,10.04916353515625L15.41166015625,10.04916353515625C15.85046015625,10.04916353515625,16.182960156249997,10.37898353515625,16.182960156249997,10.82051353515625L16.18026015625,10.95350353515625Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_23_282"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_23_282)"><g><path d="M7.2913005859375,8.84384478515625C6.1767905859375,6.23605478515625,7.4064805859375,3.2201447851562497,10.026700585937501,2.13513078515625C12.6469105859375,1.05011978515625,15.6487505859375,2.31378178515625,16.704150585937498,4.9460747851562505C17.728750585937497,7.53348478515625,16.487450585937502,10.46435478515625,13.9160505859375,11.52872478515625C11.3447705859375,12.59305478515625,8.395130585937501,11.39702478515625,7.2913005859375,8.84238478515625L7.2913005859375,8.84384478515625ZM20.4850505859375,22.25375478515625C20.9145505859375,22.25375478515625,21.2607505859375,21.88855478515625,21.2257505859375,21.45755478515625C20.8750505859375,17.19895478515625,17.7676505859375,13.74085478515625,13.7296505859375,12.95925478515625C13.5885505859375,12.93365478515625,13.4445505859375,12.98485478515625,13.3512505859375,13.09375478515625Q12.3271505859375,14.29315478515625,12.1167705859375,14.55025478515625C12.0943405859375,14.57945478515625,12.0888005859375,14.61825478515625,12.1021605859375,14.65255478515625L13.6653505859375,18.71975478515625C13.6945505859375,18.78845478515625,13.6799505859375,18.86875478515625,13.6317505859375,18.92425478515625L12.0641805859375,21.15515478515625C12.0326505859375,21.19805478515625,11.9686005859375,21.19805478515625,11.9370805859375,21.15515478515625L10.3694905859375,18.92285478515625C10.3211205859375,18.86625478515625,10.3081705859375,18.78745478515625,10.3358905859375,18.71835478515625L11.8990905859375,14.65105478515625C11.9137205859375,14.61695478515625,11.9080905859375,14.57745478515625,11.8844805859375,14.54875478515625Q11.6741105859375,14.29165478515625,10.6499905859375,13.09225478515625C10.557260585937499,12.98255478515625,10.412740585937499,12.93125478515625,10.2716105859375,12.95785478515625C6.230670585937499,13.73945478515625,3.1203355859375,17.19745478515625,2.7740944959375,21.45605478515625C2.7408270859375,21.88645478515625,3.0817325859375,22.25355478515625,3.5133275859375,22.25235478515625L20.4850505859375,22.25235478515625L20.4850505859375,22.25375478515625Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_30_116"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath><clipPath id="master_svg1_30_016"><rect x="0.625" y="0.625" width="22.75" height="22.75" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_30_116)"><g clip-path="url(#master_svg1_30_016)"></g><g><path d="M22.625,5.35937201171875L22.625,7.13019201171875L1.375,7.13019201171875L1.375,5.35895201171875C1.37765625,4.38232401171875,2.055872,3.59165413171875,2.89259,3.58856201171875L21.1078,3.58856201171875C21.9445,3.59165413171875,22.6223,4.38278101171875,22.625,5.35937201171875ZM22.625,8.45832201171875L22.625,18.70396201171875C22.6223,19.64596201171875,21.9445,20.40836201171875,21.1074,20.41146201171875L2.8921799999999998,20.41146201171875C2.055457,20.40836201171875,1.3776355,19.64556201171875,1.375,18.70396201171875L1.375,8.45832201171875L22.625,8.45832201171875ZM3.39551,12.87303201171875L6.75038,12.87303201171875C7.13201,12.87303201171875,7.44233,12.57951201171875,7.44233,12.21517201171875C7.44233,11.85215201171875,7.13244,11.55731201171875,6.75038,11.55731201171875L3.39551,11.55731201171875C3.01301,11.55729201171875,2.70312,11.85213201171875,2.70312,12.21515201171875C2.70312,12.57949201171875,3.01301,12.87300201171875,3.39551,12.87303201171875ZM8.070509999999999,14.08116201171875L3.39508,14.08116201171875C3.01303,14.08076201171875,2.70312,14.37556201171875,2.70312,14.73906201171875C2.70312,15.10336201171875,3.01301,15.39686201171875,3.39551,15.39686201171875L8.070509999999999,15.39686201171875C8.452580000000001,15.39686201171875,8.762920000000001,15.10296201171875,8.762920000000001,14.73906201171875C8.762920000000001,14.37556201171875,8.453009999999999,14.08116201171875,8.07008,14.08116201171875L8.070509999999999,14.08116201171875Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_23_261"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_23_261)"><g><path d="M18.47168671875,2.52362060546875L5.71448671875,2.52362060546875C4.00208671875,2.52362060546875,2.60888671875,3.91682060546875,2.60888671875,5.62922060546875L2.60888671875,18.38642060546875C2.60888671875,20.09882060546875,4.00208671875,21.49202060546875,5.71448671875,21.49202060546875L18.47168671875,21.49202060546875C20.18408671875,21.49202060546875,21.57728671875,20.09882060546875,21.57728671875,18.38642060546875L21.57728671875,5.62922060546875C21.57608671875,3.91682060546875,20.18288671875,2.52362060546875,18.47168671875,2.52362060546875ZM8.330486718749999,6.50042060546875C8.74088671875,6.36722060546875,9.180086718750001,6.59162060546875,9.31328671875,7.00082060546875C9.702886718750001,8.20590060546875,10.82599671875,9.02156060546875,12.09248671875,9.01922060546875C13.36328671875,9.01922060546875,14.48048671875,8.20802060546875,14.87288671875,7.00082060546875C15.00608671875,6.59162060546875,15.44648671875,6.36722060546875,15.85568671875,6.49922060546875C16.26488671875,6.63122060546875,16.48928671875,7.07162060546875,16.35728671875,7.48202060546875C15.75608671875,9.33482060546875,14.04248671875,10.57922060546875,12.09368671875,10.57922060546875C10.15081671875,10.58304060546875,8.427796718749999,9.331870605468751,7.83008671875,7.48322060546875C7.69568671875,7.07402060546875,7.92008671875,6.63362060546875,8.330486718749999,6.50042060546875ZM15.90968671875,18.174020605468748L8.27648671875,18.174020605468748C7.84570671875,18.174020605468748,7.49648671875,17.82482060546875,7.49648671875,17.39402060546875C7.49648671875,16.96322060546875,7.84570671875,16.614020605468752,8.27648671875,16.614020605468752L15.90968671875,16.614020605468752C16.34048671875,16.614020605468752,16.68968671875,16.96322060546875,16.68968671875,17.39402060546875C16.68968671875,17.82482060546875,16.34048671875,18.174020605468748,15.90968671875,18.174020605468748Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_25_023"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_25_023)"><g><path d="M20.3684552734375,2.87506103515625C21.5060552734375,2.87506103515625,22.4283552734375,3.79731803515625,22.4283552734375,4.93498103515625L22.4283552734375,15.58886103515625C22.4283552734375,16.72656103515625,21.5060552734375,17.648761035156248,20.3684552734375,17.648761035156248L3.6315752734375,17.648761035156248C2.4939132734375002,17.648761035156248,1.5716555386445,16.72656103515625,1.5716552734375,15.58886103515625L1.5716552734375,4.93498103515625C1.5716555386445,3.79731803515625,2.4939132734375002,2.87506103515625,3.6315752734375,2.87506103515625L20.3684552734375,2.87506103515625ZM19.1736552734375,6.78633103515625C18.8587552734375,6.42393103515625,18.3096552734375,6.3856510351562505,17.9474552734375,6.70085103515625L13.8528552734375,10.26245103515625L11.3099252734375,7.72720103515625L11.2537952734375,7.67570103515625C10.9217452734375,7.39824103515625,10.4361952734375,7.40724103515625,10.1146552734375,7.69682103515625L5.1708552734375,12.14985103515625L5.117295273437501,12.20238103515625C4.8094752734375,12.53210103515625,4.8050052734375,13.04246103515625,5.1069952734375,13.37756103515625L5.159525273437501,13.43116103515625C5.4891752734375,13.73866103515625,5.9991952734375,13.74306103515625,6.3341952734375,13.44146103515625L10.6651752734375,9.53942103515625L13.1988552734375,12.06539103515625L13.2539552734375,12.11638103515625C13.5784552734375,12.38829103515625,14.0573552734375,12.38829103515625,14.3828552734375,12.10608103515625L19.0881552734375,8.01199103515625L19.1427552734375,7.96049103515625C19.4533552734375,7.64017103515625,19.4718552734375,7.12931103515625,19.1736552734375,6.78633103515625ZM6.3517052734375,19.38686103515625L17.6488552734375,19.38686103515625Q18.5181552734375,19.38686103515625,18.5181552734375,20.25616103515625L18.5181552734375,20.25566103515625Q18.5181552734375,21.12496103515625,17.6488552734375,21.12496103515625L6.3517052734375,21.12496103515625Q5.482425273437499,21.12496103515625,5.482425273437499,20.25566103515625L5.482425273437499,20.25616103515625Q5.482425273437499,19.38686103515625,6.3517052734375,19.38686103515625Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_26_214"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_26_214)"><g><path d="M20.65235859375,12.00840673828125C20.65285859375,11.10123673828125,20.96205859375,10.22121673828125,21.52905859375,9.51307673828125C21.75295859375,9.18208673828125,21.75295859375,8.74814673828125,21.52905859375,8.41714673828125L19.84305859375,5.60145673828125C19.63985859375,5.22094673828125,19.22675859375,5.001076738281251,18.79765859375,5.04506673828125C16.986358593749998,5.24947673828125,15.26625859375,4.2021667382812495,14.61625859375,2.49914073828125C14.46275859375,2.12427373828125,14.09395859375,1.88288943828125,13.68895859375,1.89216503728125L10.70468859375,1.89216503728125C9.99654859375,1.89216503728125,9.62561859375,2.12821073828125,9.49072859375,2.49914073828125C8.81391859375,4.29947673828125,6.95056859375,5.36222673828125,5.05643859375,5.02820673828125C4.64990859375,4.96186673828125,4.24538859375,5.15738673828125,4.04481859375,5.517156738281249L2.35877259375,8.31598673828125C2.12715409375,8.650756738281249,2.12715409375,9.09400673828125,2.35877259375,9.42877673828125C3.60826859375,10.91521673828125,3.60826859375,13.08480673828125,2.35877259375,14.57120673828125C2.12715469375,14.90600673828125,2.12715469375,15.34920673828125,2.35877259375,15.68400673828125L4.04481859375,18.48280673828125C4.24538859375,18.84260673828125,4.64990859375,19.03810673828125,5.05643859375,18.97180673828125C6.95056859375,18.63770673828125,8.81391859375,19.70050673828125,9.49072859375,21.50080673828125C9.64428859375,21.87570673828125,10.013068593749999,22.11710673828125,10.41805859375,22.10780673828125L13.38545859375,22.10780673828125C14.09365859375,22.10780673828125,14.46455859375,21.87180673828125,14.59945859375,21.50080673828125C15.26125859375,19.74340673828125,17.05745859375,18.68390673828125,18.91575859375,18.95490673828125C19.34485859375,18.99890673828125,19.75785859375,18.77900673828125,19.96105859375,18.39850673828125L21.64705859375,15.58280673828125C21.87105859375,15.25180673828125,21.87105859375,14.81790673828125,21.64705859375,14.48690673828125C21.04105859375,13.79930673828125,20.68985859375,12.92420673828125,20.65235859375,12.00840673828125ZM12.00293859375,16.07180673828125C9.75880859375,16.07180673828125,7.93957859375,14.25250673828125,7.93957859375,12.00840673828125C7.93957859375,9.76428673828125,9.75880859375,7.94505673828125,12.00293859375,7.94505673828125C14.24705859375,7.94505673828125,16.06625859375,9.76428673828125,16.06625859375,12.00840673828125C16.06625859375,14.25250673828125,14.24705859375,16.07180673828125,12.00293859375,16.07180673828125Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_26_027"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g><g></g><g clip-path="url(#master_svg0_26_027)"><g><path d="M21.13432109375,2.11511928125C20.72432109375,1.72154628125,20.16822109375,1.50048828125,19.58842109375,1.50048828125L4.28533109375,1.50048828125C3.70560109375,1.50048828125,3.14944109375,1.72154628125,2.73948709375,2.11511928125C2.32953309375,2.50876828125,2.09912109375,3.04259828125,2.09912109375,3.59918828125L2.09912109375,20.38888828125C2.09912109375,21.54798828125,3.07799309375,22.48758828125,4.28533109375,22.48758828125L19.58842109375,22.48758828125C20.16822109375,22.48758828125,20.72432109375,22.26648828125,21.13432109375,21.87288828125C21.54422109375,21.47928828125,21.77452109375,20.94548828125,21.77452109375,20.38888828125L21.77452109375,3.59920828125C21.77452109375,3.04259828125,21.54422109375,2.50878828125,21.13432109375,2.11511928125ZM14.12302109375,17.24088828125L6.47140109375,17.24088828125C5.86780109375,17.24088828125,5.37844109375,16.77098828125,5.37844109375,16.191488281250003C5.37844109375,15.61188828125,5.867811093749999,15.14218828125,6.47140109375,15.14218828125L14.12302109375,15.14218828125C14.72662109375,15.14218828125,15.21612109375,15.61188828125,15.21612109375,16.191488281250003C15.21612109375,16.77098828125,14.72662109375,17.24088828125,14.12302109375,17.24088828125ZM17.40242109375,12.51878828125L6.47140109375,12.51878828125C5.86780109375,12.51878828125,5.37844109375,12.04888828125,5.37844109375,11.46930828125C5.37844109375,10.88980828125,5.867811093749999,10.41991828125,6.47140109375,10.41991828125L17.40242109375,10.41991828125C18.00582109375,10.41991828125,18.49532109375,10.88980828125,18.49532109375,11.46930828125C18.49532109375,12.04888828125,18.00582109375,12.51878828125,17.40242109375,12.51878828125ZM17.40242109375,7.79659828125L6.47140109375,7.79659828125C5.86780109375,7.79659828125,5.37844109375,7.32678828125,5.37844109375,6.74721828125C5.37844109375,6.16762828125,5.867811093749999,5.69790828125,6.47140109375,5.69790828125L17.40242109375,5.69790828125C18.00582109375,5.69790828125,18.49532109375,6.16762828125,18.49532109375,6.74721828125C18.49532109375,7.32678828125,18.00582109375,7.79659828125,17.40242109375,7.79659828125Z" fill="#FFFFFF" fill-opacity="1"/></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_23_269"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_23_269)"><g><path d="M21.7877193359375,10.14785L13.4000193359375,2.0802680000000002C12.5966193359375,1.3065769999999999,11.3375393359375,1.3065769999999999,10.5320493359375,2.0802680000000002L2.1422733359375,10.14785C1.5212007359375,10.74561,1.3367863359375,11.6126,1.6568613359375,12.4117C1.9790563359375,13.2108,2.7145893359375,13.7068,3.5751893359375,13.7068L4.2662193359375,13.7068L4.2662193359375,19.9303C4.2662193359375,21.3526,5.423569335937501,22.51,6.8458893359375,22.51L10.2670893359375,22.51L10.2670893359375,16.6214C10.2670893359375,15.8753,10.8754493359375,15.2669,11.6216193359375,15.2669L12.5436193359375,15.2669C13.2898193359375,15.2669,13.8981193359375,15.8753,13.8981193359375,16.6214L13.8981193359375,22.0373L13.9002193359375,22.0373L13.9002193359375,22.5078L17.3193193359375,22.5078C18.7416193359375,22.5078,19.8990193359375,21.3505,19.8990193359375,19.9282L19.8990193359375,13.7068L20.3569193359375,13.7068C21.2175193359375,13.7068,21.9530193359375,13.2108,22.2752193359375,12.4117C22.5953193359375,11.6126,22.4087193359375,10.74561,21.7877193359375,10.14785Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,191 @@
|
||||||
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
|
import TableLayout from "lib/layout/TableLayout.vue";
|
||||||
|
import MainLayout from "lib/layout/MainLayout.vue";
|
||||||
|
const routes: Array<RouteRecordRaw> = [
|
||||||
|
{
|
||||||
|
meta: {
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
path: "/login",
|
||||||
|
component: () => import("src/views/LoginPage.vue"),
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
redirect: "/home",
|
||||||
|
component: MainLayout,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "home",
|
||||||
|
component: () => import("src/views/HomeView.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "首页",
|
||||||
|
icon: "首页",
|
||||||
|
myico: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/admin",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "账号管理",
|
||||||
|
icon: "用户列表",
|
||||||
|
myico: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "账号列表",
|
||||||
|
icon: "用户列表",
|
||||||
|
myico: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "role",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "角色管理",
|
||||||
|
icon: "用户列表",
|
||||||
|
myico: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/history",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "银泰历程",
|
||||||
|
icon: "TrendCharts",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "银泰历程",
|
||||||
|
icon: "TrendCharts",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "typesManage",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "类型管理",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/news",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "新闻管理",
|
||||||
|
icon: "VideoCamera",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "新闻列表",
|
||||||
|
icon: "VideoCamera",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "typesManage",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "类型管理",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/jobs",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "招聘管理",
|
||||||
|
icon: "House",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "招聘列表",
|
||||||
|
icon: "Memo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "typesManage",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "类型管理",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/document",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "文档管理",
|
||||||
|
icon: "Files",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "文档列表",
|
||||||
|
icon: "Files",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "typesManage",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "类型管理",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/config",
|
||||||
|
component: MainLayout,
|
||||||
|
meta: {
|
||||||
|
title: "配置管理",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "list",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "页面配置",
|
||||||
|
icon: "Setting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "source",
|
||||||
|
component: TableLayout,
|
||||||
|
meta: {
|
||||||
|
title: "资源管理",
|
||||||
|
icon: "Refresh",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routes;
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { Form } from 'lib/type/TableData'
|
||||||
|
|
||||||
|
export function formatConfig(config: Array<any>) {
|
||||||
|
if (typeof config === 'object') {
|
||||||
|
config = JSON.parse(JSON.stringify(config))
|
||||||
|
}
|
||||||
|
config?.forEach((item: any) => {
|
||||||
|
let defaultValue: any = ''
|
||||||
|
if (item.type === 'text') {
|
||||||
|
item.type = 'input'
|
||||||
|
item.rows = 5
|
||||||
|
defaultValue = item.value || ''
|
||||||
|
} else if (item.type === 'radio') {
|
||||||
|
item.type = 'select'
|
||||||
|
item.items = item.option.map((item: any) => {
|
||||||
|
return {
|
||||||
|
key: item.value,
|
||||||
|
name: item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delete item.option
|
||||||
|
defaultValue = item.value || ''
|
||||||
|
} else if (item.type === 'checkbox') {
|
||||||
|
item.multiple = true
|
||||||
|
item.type = 'select'
|
||||||
|
item.items = item.option.map((item: any) => {
|
||||||
|
return {
|
||||||
|
key: item.value,
|
||||||
|
name: item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delete item.option
|
||||||
|
defaultValue = item.value.split(',')
|
||||||
|
if (defaultValue.length === 1 && defaultValue[0] === '') {
|
||||||
|
defaultValue = []
|
||||||
|
}
|
||||||
|
} else if (item.type === 'switch') {
|
||||||
|
item.openValue = true
|
||||||
|
item.closeValue = false
|
||||||
|
defaultValue = !!item.value
|
||||||
|
} else if (item.type === 'json') {
|
||||||
|
item.type = 'jsonInput'
|
||||||
|
defaultValue = item.value || ''
|
||||||
|
} else {
|
||||||
|
defaultValue = item.value || ''
|
||||||
|
}
|
||||||
|
item.getValue = () => defaultValue
|
||||||
|
delete item.value
|
||||||
|
})
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateFormData(form: Form, data: Array<any>) {
|
||||||
|
while (form.data.length > 0) {
|
||||||
|
form.data.pop()
|
||||||
|
}
|
||||||
|
for (const d of data) {
|
||||||
|
form.data.push(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
.upload-flie {
|
||||||
|
.el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.avatar-uploader-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8c939d;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded-img{
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
margin: 10px auto 0 30px;
|
||||||
|
|
||||||
|
:deep(.el-tabs__header) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
import './ConfigView.scss'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import login from 'src/api/login'
|
||||||
|
import { indexStore } from 'lib/stores'
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const store = indexStore()
|
||||||
|
const bean = reactive({
|
||||||
|
resetPasswordDialogShow: false,
|
||||||
|
resetPasswordInput: '',
|
||||||
|
resetPasswordInputOld: '',
|
||||||
|
resetPasswordInputTwo: '',
|
||||||
|
|
||||||
|
editorConfigDialogShow: false,
|
||||||
|
editorConfigInfo: {
|
||||||
|
oa_appid: '',
|
||||||
|
oa_secret: '',
|
||||||
|
link_prev:'',
|
||||||
|
show_conn:"false",
|
||||||
|
show_seal:"false",
|
||||||
|
// service_phone: '',
|
||||||
|
// service_qrcode: {
|
||||||
|
// url: ''
|
||||||
|
// },
|
||||||
|
service_weixin:"",
|
||||||
|
robot_key:'',
|
||||||
|
// service_type: '1',
|
||||||
|
front_host: '',
|
||||||
|
back_host: '',
|
||||||
|
privacy: '',
|
||||||
|
user: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const methods = reactive({
|
||||||
|
handleEditorConfigSubmit() {
|
||||||
|
login.editorConfig(bean.editorConfigInfo).then((res: any) => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
ElMessage.success('配置修改成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.success('配置修改失败')
|
||||||
|
}
|
||||||
|
methods.updateConfig()
|
||||||
|
bean.editorConfigDialogShow = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleResetPasswordSubmit() {
|
||||||
|
if (bean.resetPasswordInputOld === '') {
|
||||||
|
ElMessage.error('旧密码不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (bean.resetPasswordInput === '') {
|
||||||
|
ElMessage.error('密码不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (bean.resetPasswordInput !== bean.resetPasswordInputTwo) {
|
||||||
|
ElMessage.error('两次输入的密码不一致')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
login
|
||||||
|
.resetPassWord({
|
||||||
|
old_password: bean.resetPasswordInputOld,
|
||||||
|
password: bean.resetPasswordInput
|
||||||
|
})
|
||||||
|
.then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('密码修改成功')
|
||||||
|
setTimeout(() => {
|
||||||
|
store.logout()
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateConfig() {
|
||||||
|
login.getConfig().then((res) => {
|
||||||
|
bean.editorConfigInfo = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
methods.updateConfig()
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<div class="page" style="height: 100%;display: flex;flex-direction: column;">
|
||||||
|
{/* <el-tabs vModel={state.activeName} type="card" class="tabs">
|
||||||
|
<el-tab-pane label="修改密码" name="1">
|
||||||
|
<el-form label-width="80">
|
||||||
|
<el-form-item label="旧密码">
|
||||||
|
<el-input type="password" vModel={bean.resetPasswordInputOld}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码">
|
||||||
|
<el-input type="password" vModel={bean.resetPasswordInput}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="再次输入">
|
||||||
|
<el-input type="password" vModel={bean.resetPasswordInputTwo}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
methods.handleResetPasswordSubmit()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="修改配置" name="2"> */}
|
||||||
|
<el-form label-width="100" class="tabs">
|
||||||
|
<el-form-item label="APPID">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.oa_appid}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SECRET">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.oa_secret}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="客服链接">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.service_weixin}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
{/* <el-form-item label="客服类型">
|
||||||
|
<el-select vModel={bean.editorConfigInfo.service_type}>
|
||||||
|
<el-option label="手机" value="1"></el-option>
|
||||||
|
<el-option label="二维码" value="2"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
{bean.editorConfigInfo.service_type == '1' ? (
|
||||||
|
<el-form-item label="电话号码">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.service_phone}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
) : (
|
||||||
|
<el-form-item label="二维码">
|
||||||
|
<el-upload
|
||||||
|
class="upload-flie"
|
||||||
|
action="/corpapi/corp/config/upload"
|
||||||
|
headers={{
|
||||||
|
'x-token': store.$state.token,
|
||||||
|
'x-host': window.location.host
|
||||||
|
// 'x-host': 'a1.batiao8.com'
|
||||||
|
}}
|
||||||
|
show-file-list={false}
|
||||||
|
onSuccess={(response: any) => {
|
||||||
|
bean.editorConfigInfo.service_qrcode = response.data
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{bean.editorConfigInfo.service_qrcode ? (
|
||||||
|
<img class="uploaded-img" src={bean.editorConfigInfo.service_qrcode.url} />
|
||||||
|
) : (
|
||||||
|
<el-icon class="avatar-uploader-icon">
|
||||||
|
<Plus />
|
||||||
|
</el-icon>
|
||||||
|
)}
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
)} */}
|
||||||
|
{/* front_host:"",
|
||||||
|
back_host:"",
|
||||||
|
privacy:"",
|
||||||
|
user:"" */}
|
||||||
|
<el-form-item label="前端域名">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.front_host}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="后端域名">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.back_host}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="机器人配置">
|
||||||
|
<el-input vModel={bean.editorConfigInfo.robot_key}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="隐私政策">
|
||||||
|
<el-input type="textarea" vModel={bean.editorConfigInfo.privacy}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户协议">
|
||||||
|
<el-input type="textarea" vModel={bean.editorConfigInfo.user}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="链接前缀">
|
||||||
|
<el-input type="textarea" vModel={bean.editorConfigInfo.link_prev}></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="查看联络人">
|
||||||
|
<el-switch vModel={bean.editorConfigInfo.show_conn} activeValue={'true'} inactiveValue={'false'}></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打印公章">
|
||||||
|
<el-switch vModel={bean.editorConfigInfo.show_seal} activeValue={'true'} inactiveValue={'false'}></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
methods.handleEditorConfigSubmit()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
{/* </el-tab-pane>
|
||||||
|
</el-tabs> */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
首页
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="page"
|
||||||
|
style="
|
||||||
|
background: url('src/pub/login.jpg');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="login-box flex-col">
|
||||||
|
<div class="title">{{ corpName }}</div>
|
||||||
|
<div class="input-box flex-row">
|
||||||
|
<label class="input-label">账号</label>
|
||||||
|
<ElInput class="input" v-model="username"></ElInput>
|
||||||
|
</div>
|
||||||
|
<div class="input-box flex-row">
|
||||||
|
<label class="input-label">密码</label>
|
||||||
|
<ElInput class="input" v-model="password" type="password" show-password></ElInput>
|
||||||
|
</div>
|
||||||
|
<!-- <div v-if="!hideCorpList" class="input-box flex-row">
|
||||||
|
<label class="input-label">企业</label>
|
||||||
|
<ElSelect
|
||||||
|
placeholder="请选择要登陆的企业"
|
||||||
|
class="input"
|
||||||
|
v-model="corp"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
>
|
||||||
|
<ElOption
|
||||||
|
v-for="(item, index) in corpList"
|
||||||
|
:key="index"
|
||||||
|
:label="(item as any).name"
|
||||||
|
:value="(item as any).id"
|
||||||
|
>
|
||||||
|
</ElOption>
|
||||||
|
</ElSelect>
|
||||||
|
</div> -->
|
||||||
|
<ElButton type="primary" class="login" @click="login">登录</ElButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { getConfig } from 'lib/config'
|
||||||
|
import { indexStore } from 'lib/stores'
|
||||||
|
import message from 'lib/utils/message'
|
||||||
|
import login from 'src/api/login'
|
||||||
|
// import Request from 'lib/utils/requests'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
corp: '',
|
||||||
|
baseUrl: getConfig('baseUrl'),
|
||||||
|
corpList: [],
|
||||||
|
corpName: ''
|
||||||
|
// hideCorpList: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const store = indexStore()
|
||||||
|
store.logout(true)
|
||||||
|
store.$patch({
|
||||||
|
headers: {
|
||||||
|
'x-host': import.meta.env.VITE_PUBLIC_ENV == 'dev' ? 'a1.batiao8.com' : window.location.host
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Request({
|
||||||
|
// url: '/corp/available/corp',
|
||||||
|
// method: 'get'
|
||||||
|
// }).then((res: any) => {
|
||||||
|
// this.corpList = res.data
|
||||||
|
// const params = this.getHashParams()
|
||||||
|
// if (params.corp_id) {
|
||||||
|
// this.corp = params.corp_id
|
||||||
|
// this.hideCorpList = true
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// 获取企业名
|
||||||
|
|
||||||
|
this.corpName = '银泰官网后台'
|
||||||
|
store.$patch({
|
||||||
|
title: this.corpName
|
||||||
|
})
|
||||||
|
window.onkeydown = (e) => {
|
||||||
|
if (e.key == 'Enter') {
|
||||||
|
this.login()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
window.onkeydown = null
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getHashParams() {
|
||||||
|
// 移除hash中的'#'
|
||||||
|
let hash = window.location.hash
|
||||||
|
.replace(window.location.hash.split('?')[0], '')
|
||||||
|
.replace('?', '')
|
||||||
|
// 分割hash为键值对
|
||||||
|
let params: any = {}
|
||||||
|
let vars = hash.split('&')
|
||||||
|
for (let i = 0; i < vars.length; i++) {
|
||||||
|
let pair = vars[i].split('=')
|
||||||
|
params[pair[0]] = decodeURIComponent(pair[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
},
|
||||||
|
login() {
|
||||||
|
if (this.username == '') {
|
||||||
|
message.error('请输入用户名')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.password == '') {
|
||||||
|
message.error('请输入密码')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if (!this.corp) {
|
||||||
|
// message.error('请选择企业')
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// const corp: any = this.corpList.find((item: any) => item.id == this.corp)
|
||||||
|
const store = indexStore()
|
||||||
|
store.$patch({
|
||||||
|
baseUrl: this.baseUrl
|
||||||
|
})
|
||||||
|
store
|
||||||
|
.login({
|
||||||
|
username: this.username,
|
||||||
|
password: this.password
|
||||||
|
})
|
||||||
|
.then((res: any) => {
|
||||||
|
store.$patch({
|
||||||
|
token: res.data.token,
|
||||||
|
nickname: this.username,
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
// tableData: res.data.table,
|
||||||
|
// menus: res.data.menus,
|
||||||
|
kwargs: res.data
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.$router.push('/')
|
||||||
|
// setTimeout(() => {
|
||||||
|
// location.reload()
|
||||||
|
// }, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page {
|
||||||
|
// background-image: url("src/pub/login.jpg");
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
//height: 400px;
|
||||||
|
width: 400px;
|
||||||
|
// border: solid;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 1px 1px 10px 2px rgb(69, 82, 141);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 30px auto 20px auto;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgb(26, 36, 83);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box {
|
||||||
|
margin: 10px auto;
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
.input-label {
|
||||||
|
align-self: center;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
margin: 30px auto;
|
||||||
|
width: 300px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const res = await self.api?.getRoleList()
|
||||||
|
self.bean.roleList = res.data.items.map((item:any) => ({key: item.id, name: item.name}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
name: '用户名',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'create',
|
||||||
|
form: {
|
||||||
|
title: '新建',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
name: '用户名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'account',
|
||||||
|
name: '账号',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'password',
|
||||||
|
name: '密码',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'role',
|
||||||
|
name: '角色',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.roleList : []
|
||||||
|
},
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.addData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
name: '用户名',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'account',
|
||||||
|
name: '账号',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'role_name',
|
||||||
|
name: '角色',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'status',
|
||||||
|
name: '状态',
|
||||||
|
width: '100px',
|
||||||
|
editor: {
|
||||||
|
type: 'switch',
|
||||||
|
openValue: 1,
|
||||||
|
closeValue: 2,
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({id: String(data.id), status: String(data.status)})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'update',
|
||||||
|
form: {
|
||||||
|
title: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
primary: 'id',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
name: '用户名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'role_id',
|
||||||
|
name: '角色',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.roleList : []
|
||||||
|
},
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'status',
|
||||||
|
name: '状态',
|
||||||
|
type: 'switch',
|
||||||
|
openValue: 1,
|
||||||
|
closeValue: 2,
|
||||||
|
tips: '启用/禁用',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id), role_id: String(data.role_id), status: String(data.status)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const res = await self.api?.getResources()
|
||||||
|
self.bean.resources = res.data.items.map((item:any) => {
|
||||||
|
const type = item.type === 'page' ? '页面' : '接口'
|
||||||
|
return {
|
||||||
|
key: item.id,
|
||||||
|
name: `【${type}】${item.name}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'username',
|
||||||
|
name: '用户名',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'create',
|
||||||
|
form: {
|
||||||
|
title: '新建',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '角色',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'resource',
|
||||||
|
name: '权限',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self: any) => {
|
||||||
|
return self.bean ? self.bean.resources : []
|
||||||
|
},
|
||||||
|
multiple: true,
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
const params = {
|
||||||
|
...data,
|
||||||
|
resource: data.resource.map((i:number) => String(i))
|
||||||
|
}
|
||||||
|
return self.api?.addData(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '角色',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'desc',
|
||||||
|
name: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'update',
|
||||||
|
form: {
|
||||||
|
title: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
primary: 'id',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '角色',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'resource',
|
||||||
|
name: '权限',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self: any) => {
|
||||||
|
return self.bean ? self.bean.resources : []
|
||||||
|
},
|
||||||
|
multiple: true,
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
.category-row,
|
||||||
|
.active-category-row {
|
||||||
|
.cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.el-table__row--level-0 .el-tooltip__trigger>span {
|
||||||
|
margin: 0 !important;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.el-table__row--level-0 {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-category-row {
|
||||||
|
background: greenyellow !important;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import './index.less'
|
||||||
|
import JsonFormDialog from 'src/components/JsonFormDialog.vue'
|
||||||
|
const data: TableData = {
|
||||||
|
rowKey: 'id',
|
||||||
|
defaultExpandAll: true,
|
||||||
|
sizeOption: [1000, 100, 500, 2000],
|
||||||
|
fetchFun(self, data) {
|
||||||
|
return self.api?.getDataList(data).then((res: any) => {
|
||||||
|
const items = res.data.items || []
|
||||||
|
const backendItem = items.find((item:any) => item.tags.includes('backend'))
|
||||||
|
if(backendItem) {
|
||||||
|
try {
|
||||||
|
(self.bean as any).fieldMap = JSON.parse(backendItem.content || '{}')
|
||||||
|
} catch(err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const flatData = items.map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
key: item.id,
|
||||||
|
id: item.id,
|
||||||
|
pid: String(item.pid ?? 0),
|
||||||
|
color: 'category'
|
||||||
|
}))
|
||||||
|
res.data.items = self.methods?.getTree(flatData) ?? flatData
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTree(arr: any[]) {
|
||||||
|
const map: any = {}
|
||||||
|
const roots: any[] = []
|
||||||
|
|
||||||
|
arr.forEach((item: any) => {
|
||||||
|
map[item.key] = { ...item, children: [] }
|
||||||
|
})
|
||||||
|
|
||||||
|
arr.forEach((item: any) => {
|
||||||
|
const node = map[item.key]
|
||||||
|
if (item.pid === 0 || item.pid === '0') {
|
||||||
|
roots.push(node)
|
||||||
|
} else {
|
||||||
|
if (map[item.pid]) {
|
||||||
|
map[item.pid].children.push(node)
|
||||||
|
} else {
|
||||||
|
roots.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return roots
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
(self: any) => {
|
||||||
|
return self.bean && <JsonFormDialog
|
||||||
|
show={self.bean.showJsonFormDialog}
|
||||||
|
title={self.bean?.currentRow?.name || '配置'}
|
||||||
|
data={self.bean.jsonFormData}
|
||||||
|
fieldMap={self.bean.fieldMap}
|
||||||
|
onClose={() => {
|
||||||
|
self.bean.showJsonFormDialog = false
|
||||||
|
}}
|
||||||
|
onSubmit={async (data: any) => {
|
||||||
|
await self.api?.updateData({
|
||||||
|
id: String(self.bean.currentRow.id),
|
||||||
|
content: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
self.bean.showJsonFormDialog = false
|
||||||
|
self.methods.fetchData()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.showJsonFormDialog = false
|
||||||
|
self.bean.currentRow = null
|
||||||
|
self.bean.jsonFormData = {}
|
||||||
|
// self.bean.fieldMap = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '配置名',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'create',
|
||||||
|
form: {
|
||||||
|
title: '新建',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: '父级',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '配置名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'page',
|
||||||
|
name: '页面路径',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'extra',
|
||||||
|
hide: true,
|
||||||
|
name: '配置内容',
|
||||||
|
type: 'input',
|
||||||
|
rows: 4
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.addData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: 'PID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '配置名',
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'page',
|
||||||
|
name: '页面路径',
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
name: 'JSON配置',
|
||||||
|
width: '200px',
|
||||||
|
editor: {
|
||||||
|
type: 'json',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
name: '配置',
|
||||||
|
width: '100px',
|
||||||
|
renderBodyCell({self, row}:any) {
|
||||||
|
if(row.tags.includes('backend')) {
|
||||||
|
return <span></span>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<el-button size="small" type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
try {
|
||||||
|
self.bean.jsonFormData = JSON.parse(row.content || '{}')
|
||||||
|
} catch {
|
||||||
|
self.bean.jsonFormData = {}
|
||||||
|
}
|
||||||
|
self.bean.currentRow = row
|
||||||
|
self.bean.showJsonFormDialog = true
|
||||||
|
}}
|
||||||
|
>配置</el-button>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'weight',
|
||||||
|
name: '权重',
|
||||||
|
width: '100px',
|
||||||
|
editor: {
|
||||||
|
type: 'input',
|
||||||
|
subFun(self, data, row) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id), pid: String(row.pid)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'tags',
|
||||||
|
name: '标签',
|
||||||
|
editor: {
|
||||||
|
type: 'input',
|
||||||
|
subFun(self, data, row) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id), pid: String(row.pid)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'update',
|
||||||
|
form: {
|
||||||
|
title: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
primary: 'id',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: '父级',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '配置名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'page',
|
||||||
|
name: '页面路径',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
hide: true,
|
||||||
|
name: '配置内容',
|
||||||
|
type: 'input',
|
||||||
|
rows: 4
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '名称',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
type: 'select',
|
||||||
|
items: [
|
||||||
|
{ key: 'page',name: '页面' },
|
||||||
|
{ key: 'api',name: 'API' },
|
||||||
|
],
|
||||||
|
value: 'page'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'path',
|
||||||
|
name: '路径',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'create',
|
||||||
|
form: {
|
||||||
|
title: '新建',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '名称',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
type: 'select',
|
||||||
|
items: [
|
||||||
|
{ key: 'page',name: '页面' },
|
||||||
|
{ key: 'api',name: 'API' },
|
||||||
|
],
|
||||||
|
value: 'page'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'path',
|
||||||
|
name: '路径',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.addData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '名称',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'path',
|
||||||
|
name: '路径',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'method',
|
||||||
|
name: '方法',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'update',
|
||||||
|
form: {
|
||||||
|
title: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
primary: 'id',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '名称',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
type: 'select',
|
||||||
|
items: [
|
||||||
|
{ key: 'page',name: '页面' },
|
||||||
|
{ key: 'api',name: 'API' },
|
||||||
|
],
|
||||||
|
value: 'page'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'path',
|
||||||
|
name: '路径',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({...data, id: String(data.id)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import type { TableData } from "lib/type/TableData"
|
||||||
|
const data:TableData = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import In18FormDialog from '../../components/In18FormDialog.vue'
|
||||||
|
import { LOCALES } from '../../data/const'
|
||||||
|
import { categoryTypes } from '../../data/const'
|
||||||
|
import utils from 'lib/utils'
|
||||||
|
let types: any[] = []
|
||||||
|
const pathname = utils.getPathName()
|
||||||
|
types = categoryTypes.filter(item => pathname.includes(item.path))
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
(self: any) => {
|
||||||
|
return (
|
||||||
|
self.bean &&
|
||||||
|
<In18FormDialog
|
||||||
|
show={self.bean.showEditorDialog}
|
||||||
|
id={self.bean.id}
|
||||||
|
form={self.bean.form}
|
||||||
|
locales={self.bean.locales}
|
||||||
|
onClose={() => {
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
}}
|
||||||
|
onSubmit={async (data) => {
|
||||||
|
const params = {
|
||||||
|
...data,
|
||||||
|
id: data.id ? String(data.id) : '',
|
||||||
|
category_id: data.category_id ? String(data.category_id) : '',
|
||||||
|
}
|
||||||
|
if(data.id) {
|
||||||
|
await self.api?.updateData(params)
|
||||||
|
} else {
|
||||||
|
await self.api?.addData(params)
|
||||||
|
}
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
self.methods.fetchData()
|
||||||
|
}}
|
||||||
|
translateApi={self.api?.translate}
|
||||||
|
detailApi={async (id: number) => {
|
||||||
|
const res = await self.api?.getDetail(id);
|
||||||
|
const data = res.data;
|
||||||
|
Object.keys(data).forEach((langKey) => {
|
||||||
|
const langData = data[langKey];
|
||||||
|
Object.keys(langData).forEach((fieldKey) => {
|
||||||
|
const field = self.bean.form.find((f:any) => f.key === fieldKey);
|
||||||
|
if(fieldKey === 'name') {
|
||||||
|
data[langKey]['file_name'] = langData[fieldKey]
|
||||||
|
}
|
||||||
|
if (!field) return;
|
||||||
|
data[langKey][fieldKey] = langData[fieldKey];
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}}
|
||||||
|
uploadFun={self.api?.upload}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.form = [
|
||||||
|
{
|
||||||
|
name: '分类',
|
||||||
|
key: 'category_id',
|
||||||
|
type: 'select',
|
||||||
|
getItems: () => self.bean.docTypes,
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '文件路径',
|
||||||
|
key: 'path',
|
||||||
|
type: 'upload:file',
|
||||||
|
accept: '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '文件名',
|
||||||
|
key: 'file_name',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
self.bean.locales = LOCALES
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const types = ['file'] as const
|
||||||
|
const results = await Promise.all(
|
||||||
|
types.map((type) =>
|
||||||
|
self.api?.getCategoryList({ page: 1, size: 1000, type })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const toOptions = (items: any[]) => items.map((item: any) => ({ key: item.id, name: item.name }));
|
||||||
|
|
||||||
|
[self.bean.docTypes] = results.map(
|
||||||
|
(res) => toOptions(res?.data?.items ?? [])
|
||||||
|
)
|
||||||
|
console.log('docTypes', self.bean.docTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
type: 'select',
|
||||||
|
value: 'ZH',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.locales : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category_id',
|
||||||
|
name: '分类',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
getItems: (self: any) => {
|
||||||
|
return self.bean ? self.bean.docTypes : []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'file_name',
|
||||||
|
name: '文件名',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
onlyFun: {
|
||||||
|
title: '新建',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self) {
|
||||||
|
if(self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '文件名',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'path',
|
||||||
|
name: '文件路径',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
key: 'update',
|
||||||
|
onlyFun: {
|
||||||
|
title: '编辑',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self, row) {
|
||||||
|
if(self.bean) {
|
||||||
|
self.bean.id = row.id;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import data from '../history/typesManage'
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import In18FormDialog from '../../components/In18FormDialog.vue'
|
||||||
|
import { LOCALES } from '../../data/const'
|
||||||
|
import { categoryTypes } from '../../data/const'
|
||||||
|
import utils from 'lib/utils'
|
||||||
|
let types: any[] = []
|
||||||
|
const pathname = utils.getPathName()
|
||||||
|
types = categoryTypes.filter(item => pathname.includes(item.path))
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
(self: any) => {
|
||||||
|
return (
|
||||||
|
self.bean &&
|
||||||
|
<In18FormDialog
|
||||||
|
show={self.bean.showEditorDialog}
|
||||||
|
id={self.bean.id}
|
||||||
|
form={self.bean.form}
|
||||||
|
locales={self.bean.locales}
|
||||||
|
onClose={() => {
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
}}
|
||||||
|
onSubmit={async (data) => {
|
||||||
|
await self.api?.addData(data)
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
self.methods.fetchData()
|
||||||
|
}}
|
||||||
|
translateApi={self.api?.translate}
|
||||||
|
detailApi={async (id: number) => {
|
||||||
|
const res = await self.api?.getDetail(id);
|
||||||
|
const data = res.data;
|
||||||
|
Object.keys(data).forEach((langKey) => {
|
||||||
|
const langData = data[langKey];
|
||||||
|
Object.keys(langData).forEach((fieldKey) => {
|
||||||
|
const field = self.bean.form.find((f:any) => f.key === fieldKey);
|
||||||
|
if (!field) return;
|
||||||
|
data[langKey][fieldKey] = langData[fieldKey];
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.form = [
|
||||||
|
{
|
||||||
|
name: '分类',
|
||||||
|
key: 'category_id',
|
||||||
|
type: 'select',
|
||||||
|
must: true,
|
||||||
|
getItems: () => {
|
||||||
|
return self.bean ? self.bean.processTypes : []
|
||||||
|
},
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '标题',
|
||||||
|
key: 'title',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '内容',
|
||||||
|
key: 'content',
|
||||||
|
type: 'textarea',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
self.bean.locales = LOCALES
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const types = ['process'] as const
|
||||||
|
const results = await Promise.all(
|
||||||
|
types.map((type) =>
|
||||||
|
self.api?.getCategoryList({ page: 1, size: 1000, type })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const toOptions = (items: any[]) => items.map((item: any) => ({ key: item.id, name: item.name }));
|
||||||
|
|
||||||
|
[self.bean.processTypes] = results.map(
|
||||||
|
(res) => toOptions(res?.data?.items ?? [])
|
||||||
|
)
|
||||||
|
console.log('processTypes', self.bean.processTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
type: 'select',
|
||||||
|
value: 'ZH',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.locales : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category_id',
|
||||||
|
name: '分类',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
getItems: (self: any) => {
|
||||||
|
return self.bean ? self.bean.processTypes : []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '标题',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
onlyFun: {
|
||||||
|
title: '新建',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self) {
|
||||||
|
if(self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
width: '80px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category_name',
|
||||||
|
name: '分类',
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '标题',
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
name: '内容',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
key: 'update',
|
||||||
|
onlyFun: {
|
||||||
|
title: '编辑',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self, row) {
|
||||||
|
if(self.bean) {
|
||||||
|
self.bean.id = row.id;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import { categoryTypes } from '../../data/const'
|
||||||
|
import utils from 'lib/utils'
|
||||||
|
let types: any[] = []
|
||||||
|
const pathname = utils.getPathName()
|
||||||
|
types = categoryTypes.filter(item => pathname.includes(item.path))
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self) => {
|
||||||
|
const pathname = utils.getPathName()
|
||||||
|
types = categoryTypes.filter(item => pathname.includes(item.path))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
type: 'select',
|
||||||
|
getValue: () => types[0] ? types[0].key : '',
|
||||||
|
getItems: () => types,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '分类名',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'create',
|
||||||
|
form: {
|
||||||
|
title: '新建',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: '父ID',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '分类名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
name: '类型',
|
||||||
|
type: 'select',
|
||||||
|
getItems: () => types,
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.addData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: 'PID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '分类名',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'dialogForm',
|
||||||
|
key: 'update',
|
||||||
|
form: {
|
||||||
|
title: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
primary: 'id',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: 'pid',
|
||||||
|
name: '父ID',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
name: '分类名',
|
||||||
|
type: 'input',
|
||||||
|
must: true
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// key: 'type',
|
||||||
|
// name: '类型',
|
||||||
|
// type: 'select',
|
||||||
|
// getItems: () => types,
|
||||||
|
// must: true
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.updateData({ ...data, id: String(data.id), pid: String(data.pid) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,317 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import In18FormDialog from '../../components/In18FormDialog.vue'
|
||||||
|
import { LOCALES } from '../../data/const'
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
(self: any) => {
|
||||||
|
return (
|
||||||
|
self.bean &&
|
||||||
|
<In18FormDialog
|
||||||
|
show={self.bean.showEditorDialog}
|
||||||
|
id={self.bean.id}
|
||||||
|
form={self.bean.form}
|
||||||
|
locales={self.bean.locales}
|
||||||
|
onClose={() => {
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
}}
|
||||||
|
onSubmit={async (data) => {
|
||||||
|
const params = {
|
||||||
|
...data,
|
||||||
|
id: data.id ? String(data.id) : undefined,
|
||||||
|
job_area: data.job_area ? String(data.job_area) : undefined,
|
||||||
|
job_unit: data.job_unit ? String(data.job_unit) : undefined,
|
||||||
|
job_type: data.job_type ? String(data.job_type) : undefined,
|
||||||
|
recruit_count: data.recruit_count ? String(data.recruit_count) : undefined,
|
||||||
|
}
|
||||||
|
if(data.id) {
|
||||||
|
await self.api?.updateData(params)
|
||||||
|
} else {
|
||||||
|
await self.api?.addData(params)
|
||||||
|
}
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
self.methods.fetchData()
|
||||||
|
}}
|
||||||
|
translateApi={self.api?.translate}
|
||||||
|
detailApi={async (id: number) => {
|
||||||
|
const res = await self.api?.getDetail(id);
|
||||||
|
const data = res.data;
|
||||||
|
Object.keys(data).forEach((langKey) => {
|
||||||
|
const langData = data[langKey];
|
||||||
|
Object.keys(langData).forEach((fieldKey) => {
|
||||||
|
const field = self.bean.form.find((f:any) => f.key === fieldKey);
|
||||||
|
if (fieldKey === 'title') {
|
||||||
|
data[langKey]['name'] = langData[fieldKey];
|
||||||
|
}
|
||||||
|
if(fieldKey === 'category') {
|
||||||
|
data[langKey]['job_type'] = langData[fieldKey].job_type;
|
||||||
|
data[langKey]['job_area'] = langData[fieldKey].job_area;
|
||||||
|
data[langKey]['job_unit'] = langData[fieldKey].job_unit;
|
||||||
|
}
|
||||||
|
if (!field) return;
|
||||||
|
data[langKey][fieldKey] = langData[fieldKey];
|
||||||
|
})
|
||||||
|
})
|
||||||
|
console.log('data', data)
|
||||||
|
return data
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
console.log('self.bean.jobTypes', self.bean.jobTypes)
|
||||||
|
self.bean.form = [
|
||||||
|
{
|
||||||
|
name: '职业类别',
|
||||||
|
key: 'job_type',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
getItems: () => self.bean.jobTypes,
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '业务领域',
|
||||||
|
key: 'job_area',
|
||||||
|
type: 'select',
|
||||||
|
getItems: () => self.bean.jobAreas,
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '所属板块',
|
||||||
|
key: 'job_unit',
|
||||||
|
type: 'select',
|
||||||
|
getItems: () => self.bean.jobUnits,
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '招聘人数',
|
||||||
|
key: 'recruit_count',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '城市',
|
||||||
|
key: 'city',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '岗位名称',
|
||||||
|
key: 'name',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '岗位描述',
|
||||||
|
key: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '任职需求',
|
||||||
|
key: 'requirement',
|
||||||
|
type: 'textarea',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联系方式',
|
||||||
|
key: 'contract_info',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
self.bean.locales = LOCALES
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const types = ['job_type', 'job_area', 'job_unit'] as const
|
||||||
|
const results = await Promise.all(
|
||||||
|
types.map((type) =>
|
||||||
|
self.api?.getCategoryList({ page: 1, size: 1000, type })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const toOptions = (items: any[]) => items.map((item: any) => ({ key: item.id, name: item.name }));
|
||||||
|
|
||||||
|
[self.bean.jobTypes, self.bean.jobAreas, self.bean.jobUnits] = results.map(
|
||||||
|
(res) => toOptions(res?.data?.items ?? [])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
type: 'select',
|
||||||
|
value: 'ZH',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.locales : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '职位名称',
|
||||||
|
type: 'input',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'job_type',
|
||||||
|
name: '职业类别',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.jobTypes : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'job_area',
|
||||||
|
name: '业务领域',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.jobAreas : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'job_unit',
|
||||||
|
name: '所属板块',
|
||||||
|
type: 'select',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.jobUnits : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
onlyFun: {
|
||||||
|
title: '新建',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self) {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '职位名称',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category',
|
||||||
|
name: '职业类型 | 业务领域 | 所属板块',
|
||||||
|
renderBodyCell(data) {
|
||||||
|
let item: any = {}
|
||||||
|
try {
|
||||||
|
item = JSON.parse(data.row.category)
|
||||||
|
} catch (error) {
|
||||||
|
item = data.row.category
|
||||||
|
}
|
||||||
|
return <div style="display: flex; gap: 5px;">
|
||||||
|
<el-tag>{item.job_type_name}</el-tag>
|
||||||
|
<el-tag type="warning">{item.job_area_name}</el-tag>
|
||||||
|
<el-tag type="success">{item.job_unit_name}</el-tag>
|
||||||
|
</div>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'description',
|
||||||
|
name: '岗位描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'requirement',
|
||||||
|
name: '任职需求',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'recruit_count',
|
||||||
|
name: '招聘人数',
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'contract_info',
|
||||||
|
name: '联系方式',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '创建时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
key: 'update',
|
||||||
|
onlyFun: {
|
||||||
|
title: '编辑',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self, row) {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = row.id;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import data from '../history/typesManage'
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,278 @@
|
||||||
|
import type { TableData } from 'lib/type/TableData'
|
||||||
|
import { LOCALES } from '../../data/const'
|
||||||
|
import In18FormDialog from '../../components/In18FormDialog.vue'
|
||||||
|
|
||||||
|
const data: TableData = {
|
||||||
|
async fetchFun(self, data) {
|
||||||
|
const res = await self.api?.getDataList(data)
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
addNods: [
|
||||||
|
(self: any) => {
|
||||||
|
return (
|
||||||
|
self.bean &&
|
||||||
|
<In18FormDialog
|
||||||
|
show={self.bean.showEditorDialog}
|
||||||
|
id={self.bean.id}
|
||||||
|
form={self.bean.form}
|
||||||
|
locales={self.bean.locales}
|
||||||
|
onClose={() => {
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
}}
|
||||||
|
onSubmit={async (data) => {
|
||||||
|
const params = {
|
||||||
|
...data,
|
||||||
|
id: data.id ? String(data.id) : undefined,
|
||||||
|
category_id: data.category_id ? String(data.category_id) : undefined,
|
||||||
|
}
|
||||||
|
if(data.id) {
|
||||||
|
await self.api?.updateData(params)
|
||||||
|
} else {
|
||||||
|
await self.api?.addData(params)
|
||||||
|
}
|
||||||
|
self.bean.showEditorDialog = false;
|
||||||
|
self.bean.id = null;
|
||||||
|
self.methods.fetchData()
|
||||||
|
}}
|
||||||
|
translateApi={self.api?.translate}
|
||||||
|
detailApi={async (id: number) => {
|
||||||
|
const res = await self.api?.getDetail(id);
|
||||||
|
const data = res.data;
|
||||||
|
Object.keys(data).forEach((langKey) => {
|
||||||
|
const langData = data[langKey];
|
||||||
|
Object.keys(langData).forEach((fieldKey) => {
|
||||||
|
const field = self.bean.form.find((f:any) => f.key === fieldKey);
|
||||||
|
if (fieldKey === 'covers') {
|
||||||
|
data[langKey]['cover_resource'] = langData[fieldKey];
|
||||||
|
}
|
||||||
|
if (!field) return;
|
||||||
|
data[langKey][fieldKey] = langData[fieldKey];
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}}
|
||||||
|
uploadFun={self.api?.upload}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
launchTask: [
|
||||||
|
async (self) => {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.locales = LOCALES;
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.form = [
|
||||||
|
{
|
||||||
|
name: '分类',
|
||||||
|
key: 'category_id',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
getItems: () => {
|
||||||
|
return self.bean ? self.bean.newsTypes : []
|
||||||
|
},
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '封面类型',
|
||||||
|
key: 'cover_show',
|
||||||
|
type: 'select',
|
||||||
|
items: [
|
||||||
|
{key: 'image', name: '图片'},
|
||||||
|
{key: 'video', name: '视频'},
|
||||||
|
],
|
||||||
|
value: 'image',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '封面',
|
||||||
|
key: 'cover_resource',
|
||||||
|
type: 'upload:image,video',
|
||||||
|
relateKey: 'cover_show',
|
||||||
|
uploadFun: self.api?.upload,
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '标题',
|
||||||
|
key: 'title',
|
||||||
|
type: 'input',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '内容',
|
||||||
|
key: 'content',
|
||||||
|
type: 'textarea',
|
||||||
|
value: '',
|
||||||
|
must: true,
|
||||||
|
shouldTranslate: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async (self: any) => {
|
||||||
|
if (self.bean) {
|
||||||
|
const types = ['news'] as const
|
||||||
|
const results = await Promise.all(
|
||||||
|
types.map((type) =>
|
||||||
|
self.api?.getCategoryList({ page: 1, size: 1000, type })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const toOptions = (items: any[]) => items.map((item: any) => ({ key: item.id, name: item.name }));
|
||||||
|
|
||||||
|
[self.bean.newsTypes] = results.map(
|
||||||
|
(res) => toOptions(res?.data?.items ?? [])
|
||||||
|
)
|
||||||
|
console.log('newsTypes', self.bean.newsTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fliter: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
type: 'select',
|
||||||
|
value: 'ZH',
|
||||||
|
getItems: (self) => {
|
||||||
|
return self.bean ? self.bean.locales : []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category_id',
|
||||||
|
name: '分类',
|
||||||
|
type: 'select',
|
||||||
|
value: '',
|
||||||
|
getItems: (self: any) => {
|
||||||
|
return self.bean ? self.bean.newsTypes : []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '标题',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
name: '内容',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'publish_time',
|
||||||
|
name: '发布时间',
|
||||||
|
type: 'input'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
onlyFun: {
|
||||||
|
title: '新建',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self) {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = null;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableColumns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
name: 'ID',
|
||||||
|
width: '80px',
|
||||||
|
showJson: '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'lang',
|
||||||
|
name: '语言',
|
||||||
|
width: '80px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'category_name',
|
||||||
|
name: '分类',
|
||||||
|
width: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'covers',
|
||||||
|
name: '封面',
|
||||||
|
width: '200px',
|
||||||
|
renderBodyCell(data) {
|
||||||
|
let covers = data.row.covers
|
||||||
|
try {
|
||||||
|
covers = JSON.parse(data.row.covers)
|
||||||
|
} catch (error) {
|
||||||
|
covers = data.row.covers
|
||||||
|
}
|
||||||
|
return <el-image src={covers.image} preview-src-list={[covers.image]} preview-teleported style="width: 80px; height: 100%;" />
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'covers_show',
|
||||||
|
name: '封面类型',
|
||||||
|
width: '100px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
name: '标题',
|
||||||
|
width: '200px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'content',
|
||||||
|
name: '内容',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'create_time',
|
||||||
|
name: '发布时间',
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'count',
|
||||||
|
name: '阅读次数',
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'table_tools',
|
||||||
|
name: '操作',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'onlyFun',
|
||||||
|
key: 'update',
|
||||||
|
onlyFun: {
|
||||||
|
title: '编辑',
|
||||||
|
type: ' ' as any,
|
||||||
|
fun(self, row) {
|
||||||
|
if (self.bean) {
|
||||||
|
self.bean.id = row.id;
|
||||||
|
self.bean.showEditorDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'popoverConfirm',
|
||||||
|
key: 'delete',
|
||||||
|
confirm: {
|
||||||
|
title: '删除',
|
||||||
|
primary: 'id',
|
||||||
|
subFun(self, data) {
|
||||||
|
return self.api?.deleteData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default data
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import data from '../history/typesManage'
|
||||||
|
|
||||||
|
export default data
|
||||||