mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-08-28 10:09:54 +08:00
发布v2.12.1版本,更新内容请查看:https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-update-log.md
This commit is contained in:
@@ -37,19 +37,12 @@ module.exports = defineConfig({
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { varsIgnorePattern: '.*', args: 'none' }],
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
// we are only using this rule to check for unused arguments since TS
|
||||
// catches unused variables but not args.
|
||||
{ varsIgnorePattern: '.*', args: 'none' },
|
||||
],
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hotgo",
|
||||
"version": "2.11.5",
|
||||
"version": "2.12.1",
|
||||
"author": {
|
||||
"name": "MengShuai",
|
||||
"email": "133814250@qq.com",
|
||||
@@ -28,39 +28,39 @@
|
||||
"test prod gzip": "http-server dist --cors --gzip -c-1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vicons/antd": "^0.10.0",
|
||||
"@vicons/ionicons5": "^0.10.0",
|
||||
"@vueup/vue-quill": "^1.1.0",
|
||||
"@vueuse/core": "^5.3.0",
|
||||
"@vicons/antd": "^0.12.0",
|
||||
"@vicons/ionicons5": "^0.12.0",
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"@vueuse/core": "^10.7.1",
|
||||
"axios": "^0.21.4",
|
||||
"date-fns": "^2.28.0",
|
||||
"echarts": "^5.3.2",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"naive-ui": "^2.34.3",
|
||||
"pinia": "^2.0.14",
|
||||
"naive-ui": "^2.36.0",
|
||||
"pinia": "^2.1.7",
|
||||
"qrcode.vue": "3.3.3",
|
||||
"qs": "^6.10.3",
|
||||
"quill-image-uploader": "^1.2.4",
|
||||
"quill-image-uploader": "^1.3.0",
|
||||
"quill-magic-url": "^4.2.0",
|
||||
"throttle-debounce": "^5.0.0",
|
||||
"vue": "^3.2.35",
|
||||
"vue-router": "^4.0.15",
|
||||
"vue-types": "^4.1.1",
|
||||
"vue": "^3.4.0",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue-types": "^5.1.1",
|
||||
"vue3-json-viewer": "^2.2.2",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"weixin-js-sdk": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^12.1.4",
|
||||
"@commitlint/config-conventional": "^12.1.4",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/node": "^15.14.9",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"@vitejs/plugin-vue": "^1.10.2",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@commitlint/cli": "^17.7.0",
|
||||
"@commitlint/config-conventional": "^17.7.0",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/node": "^18.17.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.1",
|
||||
"@vue/compiler-sfc": "^3.2.33",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
@@ -93,11 +93,11 @@
|
||||
"tailwindcss": "^2.2.19",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-vue-components": "^0.17.21",
|
||||
"vite": "^2.9.8",
|
||||
"vite-plugin-compression": "^0.3.6",
|
||||
"vite": "^4.2.7",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^2.1.2",
|
||||
"vite-plugin-require-transform": "^1.0.5",
|
||||
"vite-plugin-style-import": "^1.4.1",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vite-plugin-top-level-await": "^1.2.2",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-eslint-parser": "^7.11.0"
|
||||
@@ -134,6 +134,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/bufanyun/hotgo",
|
||||
"engines": {
|
||||
"node": "^12 || >=14"
|
||||
"node": ">=16"
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { http } from '@/utils/http/axios';
|
||||
import { useUserStoreWidthOut } from '@/store/modules/user';
|
||||
|
||||
// 获取验证码
|
||||
export function GetCaptcha() {
|
||||
@@ -10,9 +11,15 @@ export function GetCaptcha() {
|
||||
|
||||
// 上传图片
|
||||
export function UploadImage(params) {
|
||||
const useUserStore = useUserStoreWidthOut();
|
||||
const headers = {
|
||||
Authorization: useUserStore.token,
|
||||
uploadType: 'default',
|
||||
};
|
||||
return http.request({
|
||||
url: '/upload/image',
|
||||
url: '/upload/file',
|
||||
method: 'post',
|
||||
params,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@
|
||||
ref="fileUploadRef"
|
||||
:width="dialogWidth"
|
||||
:finish-call="handleFinishCall"
|
||||
max-upload="20"
|
||||
:max-upload="20"
|
||||
/>
|
||||
|
||||
<Preview ref="previewRef" />
|
||||
|
@@ -9,8 +9,8 @@ import { PageEnum } from '@/enums/pageEnum';
|
||||
|
||||
import { useGlobSetting } from '@/hooks/setting';
|
||||
|
||||
import { isString } from '@/utils/is/';
|
||||
import { deepMerge, isUrl } from '@/utils';
|
||||
import { isString, isUrl } from '@/utils/is/';
|
||||
import { deepMerge } from '@/utils';
|
||||
import { setObjToUrlParams } from '@/utils/urlUtils';
|
||||
|
||||
import { CreateAxiosOptions, RequestOptions, Result } from './types';
|
||||
|
@@ -250,9 +250,35 @@ export function lighten(color: string, amount: number) {
|
||||
)}${addLight(color.substring(4, 6), amount)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否 url
|
||||
* */
|
||||
export function isUrl(url: string) {
|
||||
return /^(http|https):\/\//g.test(url);
|
||||
// 获取树的所有节点key
|
||||
export function getAllExpandKeys(treeData: any): any[] {
|
||||
let expandedKeys = [];
|
||||
const expandKeys = (items: any[]) => {
|
||||
items.forEach((item: any) => {
|
||||
expandedKeys.push(item.key);
|
||||
if (item.children && item.children.length > 0) {
|
||||
expandKeys(item.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
expandKeys(unref(treeData));
|
||||
|
||||
// 去重并转换为数组
|
||||
expandedKeys = Array.from(new Set(expandedKeys));
|
||||
return expandedKeys;
|
||||
}
|
||||
|
||||
// 从树中查找指定ID
|
||||
export function findTreeDataById(data: any[], id: number | string) {
|
||||
for (const item of data) {
|
||||
if (item.id === id) {
|
||||
return item;
|
||||
}
|
||||
if (item.children) {
|
||||
const found = findTreeDataById(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -1,33 +1,50 @@
|
||||
import { CSSProperties, VNodeChild } from 'vue';
|
||||
import { createTypes, VueTypeValidableDef, VueTypesInterface } from 'vue-types';
|
||||
import {
|
||||
createTypes,
|
||||
VueTypeExtendCallback,
|
||||
VueTypeValidableDef,
|
||||
VueTypesInterface,
|
||||
} from 'vue-types';
|
||||
|
||||
export type VueNode = VNodeChild | JSX.Element;
|
||||
|
||||
type PropTypes = VueTypesInterface & {
|
||||
type ExtendedPropTypes = VueTypesInterface & {
|
||||
readonly style: VueTypeValidableDef<CSSProperties>;
|
||||
readonly VNodeChild: VueTypeValidableDef<VueNode>;
|
||||
};
|
||||
|
||||
const propTypes = createTypes({
|
||||
func: undefined,
|
||||
bool: undefined,
|
||||
string: undefined,
|
||||
number: undefined,
|
||||
object: undefined,
|
||||
integer: undefined,
|
||||
}) as PropTypes;
|
||||
class CustomVueTypes
|
||||
extends (createTypes({
|
||||
func: undefined,
|
||||
bool: undefined,
|
||||
string: undefined,
|
||||
number: undefined,
|
||||
object: undefined,
|
||||
integer: undefined,
|
||||
}) as VueTypesInterface)
|
||||
implements ExtendedPropTypes
|
||||
{
|
||||
static extend(types: VueTypeExtendCallback[]): CustomVueTypes {
|
||||
return types.reduce((result, { name, ...callbacks }) => {
|
||||
result[name] = { getter: true, ...callbacks };
|
||||
return result;
|
||||
}, this);
|
||||
}
|
||||
|
||||
propTypes.extend([
|
||||
readonly style!: VueTypeValidableDef<CSSProperties>;
|
||||
readonly VNodeChild!: VueTypeValidableDef<VueNode>;
|
||||
}
|
||||
|
||||
const propTypes = CustomVueTypes.extend([
|
||||
{
|
||||
name: 'style',
|
||||
getter: true,
|
||||
type: [String, Object],
|
||||
default: undefined,
|
||||
},
|
||||
{
|
||||
name: 'VNodeChild',
|
||||
getter: true,
|
||||
type: undefined,
|
||||
},
|
||||
]);
|
||||
|
||||
export { propTypes };
|
||||
|
@@ -2,65 +2,69 @@
|
||||
<div>
|
||||
<n-spin :show="loading" description="请稍候...">
|
||||
<n-modal
|
||||
v-model:show="isShowModal"
|
||||
v-model:show="showModal"
|
||||
:mask-closable="false"
|
||||
:show-icon="false"
|
||||
preset="dialog"
|
||||
:title="params?.id > 0 ? '编辑 #' + params?.id : '添加'"
|
||||
transform-origin="center"
|
||||
:title="formValue.id > 0 ? '编辑 #' + formValue.id : '添加'"
|
||||
:style="{
|
||||
width: dialogWidth,
|
||||
}"
|
||||
>
|
||||
<n-form
|
||||
:model="params"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
label-placement="left"
|
||||
:label-width="100"
|
||||
class="py-4"
|
||||
>
|
||||
<n-form-item label="分类ID" path="categoryId">
|
||||
<n-input-number placeholder="请输入分类ID" v-model:value="params.categoryId" />
|
||||
<n-scrollbar style="max-height: 87vh" class="pr-5">
|
||||
<n-form
|
||||
:model="formValue"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
:label-placement="settingStore.isMobile ? 'top' : 'left'"
|
||||
:label-width="100"
|
||||
class="py-4"
|
||||
>
|
||||
<n-form-item label="分类ID" path="categoryId">
|
||||
<n-input-number placeholder="请输入分类ID" v-model:value="formValue.categoryId" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="标题" path="title">
|
||||
<n-input placeholder="请输入标题" v-model:value="params.title" />
|
||||
<n-input placeholder="请输入标题" v-model:value="formValue.title" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="描述" path="description">
|
||||
<n-input type="textarea" placeholder="描述" v-model:value="params.description" />
|
||||
<n-input type="textarea" placeholder="描述" v-model:value="formValue.description" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="内容" path="content">
|
||||
<Editor style="height: 450px" id="content" v-model:value="params.content" />
|
||||
<Editor style="height: 450px" id="content" v-model:value="formValue.content" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="单图" path="image">
|
||||
<UploadImage :maxNumber="1" v-model:value="params.image" />
|
||||
<UploadImage :maxNumber="1" v-model:value="formValue.image" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="附件" path="attachfile">
|
||||
<UploadFile :maxNumber="1" v-model:value="params.attachfile" />
|
||||
<UploadFile :maxNumber="1" v-model:value="formValue.attachfile" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="所在城市" path="cityId">
|
||||
<CitySelector v-model:value="params.cityId" />
|
||||
<CitySelector v-model:value="formValue.cityId" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="显示开关" path="switch">
|
||||
<n-switch :unchecked-value="2" :checked-value="1" v-model:value="params.switch"
|
||||
<n-switch :unchecked-value="2" :checked-value="1" v-model:value="formValue.switch"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="排序" path="sort">
|
||||
<n-input-number placeholder="请输入排序" v-model:value="params.sort" />
|
||||
<n-input-number placeholder="请输入排序" v-model:value="formValue.sort" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="状态" path="status">
|
||||
<n-select v-model:value="params.status" :options="options.sys_normal_disable" />
|
||||
<n-select v-model:value="formValue.status" :options="options.sys_normal_disable" />
|
||||
</n-form-item>
|
||||
|
||||
|
||||
</n-form>
|
||||
</n-form>
|
||||
</n-scrollbar>
|
||||
<template #action>
|
||||
<n-space>
|
||||
<n-button @click="closeForm">取消</n-button>
|
||||
@@ -73,44 +77,25 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, computed, watch } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { Edit, MaxSort, View } from '@/api/curdDemo';
|
||||
import Editor from '@/components/Editor/editor.vue';
|
||||
import UploadImage from '@/components/Upload/uploadImage.vue';
|
||||
import UploadFile from '@/components/Upload/uploadFile.vue';
|
||||
import CitySelector from '@/components/CitySelector/citySelector.vue';
|
||||
import { rules, options, State, newState } from './model';
|
||||
import { useProjectSettingStore } from '@/store/modules/projectSetting';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { adaModalWidth } from '@/utils/hotgo';
|
||||
|
||||
const emit = defineEmits(['reloadTable', 'updateShowModal']);
|
||||
|
||||
interface Props {
|
||||
showModal: boolean;
|
||||
formParams?: State;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showModal: false,
|
||||
formParams: () => {
|
||||
return newState(null);
|
||||
},
|
||||
});
|
||||
|
||||
const isShowModal = computed({
|
||||
get: () => {
|
||||
return props.showModal;
|
||||
},
|
||||
set: (value) => {
|
||||
emit('updateShowModal', value);
|
||||
},
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const params = ref<State>(props.formParams);
|
||||
const emit = defineEmits(['reloadTable']);
|
||||
const message = useMessage();
|
||||
const formRef = ref<any>({});
|
||||
const settingStore = useProjectSettingStore();
|
||||
const dialogWidth = ref('75%');
|
||||
const loading = ref(false);
|
||||
const showModal = ref(false);
|
||||
const formValue = ref<State>(newState(null));
|
||||
const formRef = ref<any>({});
|
||||
const formBtnLoading = ref(false);
|
||||
|
||||
function confirmForm(e) {
|
||||
@@ -118,10 +103,10 @@
|
||||
formBtnLoading.value = true;
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
Edit(params.value).then((_res) => {
|
||||
Edit(formValue.value).then((_res) => {
|
||||
message.success('操作成功');
|
||||
setTimeout(() => {
|
||||
isShowModal.value = false;
|
||||
showModal.value = false;
|
||||
emit('reloadTable');
|
||||
});
|
||||
});
|
||||
@@ -132,23 +117,22 @@
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
adaModalWidth(dialogWidth);
|
||||
});
|
||||
|
||||
function closeForm() {
|
||||
isShowModal.value = false;
|
||||
showModal.value = false;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
function loadForm(value) {
|
||||
function openModal(state: State) {
|
||||
adaModalWidth(dialogWidth);
|
||||
showModal.value = true;
|
||||
loading.value = true;
|
||||
|
||||
// 新增
|
||||
if (value.id < 1) {
|
||||
params.value = newState(value);
|
||||
if (!state || state.id < 1) {
|
||||
formValue.value = newState(state);
|
||||
MaxSort()
|
||||
.then((res) => {
|
||||
params.value.sort = res.sort;
|
||||
formValue.value.sort = res.sort;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
@@ -157,21 +141,18 @@
|
||||
}
|
||||
|
||||
// 编辑
|
||||
View({ id: value.id })
|
||||
View({ id: state.id })
|
||||
.then((res) => {
|
||||
params.value = res;
|
||||
formValue.value = res;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.formParams,
|
||||
(value) => {
|
||||
loadForm(value);
|
||||
}
|
||||
);
|
||||
defineExpose({
|
||||
openModal,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
@@ -76,12 +76,8 @@
|
||||
</template>
|
||||
</BasicTable>
|
||||
</n-card>
|
||||
<Edit
|
||||
@reloadTable="reloadTable"
|
||||
@updateShowModal="updateShowModal"
|
||||
:showModal="showModal"
|
||||
:formParams="formParams"
|
||||
/>
|
||||
<Edit @reloadTable="reloadTable" ref="editRef" />
|
||||
<View ref="viewRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -92,21 +88,21 @@
|
||||
import { BasicForm, useForm } from '@/components/Form/index';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { List, Export, Delete, Status } from '@/api/curdDemo';
|
||||
import { State, columns, schemas, options, newState } from './model';
|
||||
import { columns, schemas, options } from './model';
|
||||
import { PlusOutlined, ExportOutlined, DeleteOutlined } from '@vicons/antd';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { getOptionLabel } from '@/utils/hotgo';
|
||||
import Edit from './edit.vue';
|
||||
const { hasPermission } = usePermission();
|
||||
const router = useRouter();
|
||||
const actionRef = ref();
|
||||
import View from './view.vue';
|
||||
|
||||
const dialog = useDialog();
|
||||
const message = useMessage();
|
||||
const { hasPermission } = usePermission();
|
||||
const actionRef = ref();
|
||||
const searchFormRef = ref<any>({});
|
||||
const viewRef = ref();
|
||||
const editRef = ref();
|
||||
const batchDeleteDisabled = ref(true);
|
||||
const checkedIds = ref([]);
|
||||
const showModal = ref(false);
|
||||
const formParams = ref<State>();
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 300,
|
||||
@@ -170,15 +166,6 @@
|
||||
return await List({ ...searchFormRef.value?.formModel, ...res });
|
||||
};
|
||||
|
||||
function addTable() {
|
||||
showModal.value = true;
|
||||
formParams.value = newState(null);
|
||||
}
|
||||
|
||||
function updateShowModal(value) {
|
||||
showModal.value = value;
|
||||
}
|
||||
|
||||
function onCheckedRow(rowKeys) {
|
||||
batchDeleteDisabled.value = rowKeys.length <= 0;
|
||||
checkedIds.value = rowKeys;
|
||||
@@ -188,13 +175,16 @@
|
||||
actionRef.value.reload();
|
||||
}
|
||||
|
||||
function handleView(record: Recordable) {
|
||||
router.push({ name: 'curdDemoView', params: { id: record.id } });
|
||||
function addTable() {
|
||||
editRef.value.openModal(null);
|
||||
}
|
||||
|
||||
function handleEdit(record: Recordable) {
|
||||
showModal.value = true;
|
||||
formParams.value = newState(record as State);
|
||||
editRef.value.openModal(record);
|
||||
}
|
||||
|
||||
function handleView(record: Recordable) {
|
||||
viewRef.value.openModal(record);
|
||||
}
|
||||
|
||||
function handleDelete(record: Recordable) {
|
||||
@@ -209,9 +199,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -229,9 +216,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -8,59 +8,46 @@ import { isArray, isNullObject } from '@/utils/is';
|
||||
import { getFileExt } from '@/utils/urlUtils';
|
||||
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
|
||||
import { validate } from '@/utils/validateUtil';
|
||||
import { getOptionLabel, getOptionTag, Options, errorImg } from '@/utils/hotgo';
|
||||
import { getOptionLabel, getOptionTag, Option, Options, errorImg } from '@/utils/hotgo';
|
||||
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
const { hasPermission } = usePermission();
|
||||
const $message = window['$message'];
|
||||
|
||||
|
||||
export interface State {
|
||||
id: number;
|
||||
categoryId: number;
|
||||
title: string;
|
||||
description: string;
|
||||
content: string;
|
||||
image: string;
|
||||
attachfile: string;
|
||||
cityId: number;
|
||||
switch: number;
|
||||
sort: number;
|
||||
status: number;
|
||||
createdBy: number;
|
||||
updatedBy: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: string;
|
||||
export class State {
|
||||
public id = 0; // ID
|
||||
public categoryId = 0; // 分类ID
|
||||
public title = ''; // 标题
|
||||
public description = ''; // 描述
|
||||
public content = ''; // 内容
|
||||
public image = ''; // 单图
|
||||
public attachfile = ''; // 附件
|
||||
public cityId = 0; // 所在城市
|
||||
public switch = 1; // 显示开关
|
||||
public sort = 0; // 排序
|
||||
public status = 1; // 状态
|
||||
public createdBy = 0; // 创建者
|
||||
public updatedBy = 0; // 更新者
|
||||
public createdAt = ''; // 创建时间
|
||||
public updatedAt = ''; // 修改时间
|
||||
public deletedAt = ''; // 删除时间
|
||||
}
|
||||
|
||||
export const defaultState: State = {
|
||||
id: 0,
|
||||
categoryId: 0,
|
||||
title: '',
|
||||
description: '',
|
||||
content: '',
|
||||
image: '',
|
||||
attachfile: '',
|
||||
cityId: 0,
|
||||
switch: 1,
|
||||
sort: 0,
|
||||
status: 1,
|
||||
createdBy: 0,
|
||||
updatedBy: 0,
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
deletedAt: '',
|
||||
export function newState(state: State | Record<string, any> | null): State {
|
||||
if (state !== null) {
|
||||
if (state instanceof State) {
|
||||
return cloneDeep(state);
|
||||
}
|
||||
return new State(state);
|
||||
}
|
||||
return new State();
|
||||
}
|
||||
|
||||
export interface IOptions extends Options {
|
||||
sys_normal_disable: Option[];
|
||||
};
|
||||
|
||||
export function newState(state: State | null): State {
|
||||
if (state !== null) {
|
||||
return cloneDeep(state);
|
||||
}
|
||||
return cloneDeep(defaultState);
|
||||
}
|
||||
|
||||
export const options = ref<Options>({
|
||||
export const options = ref<IOptions>({
|
||||
sys_normal_disable: [],
|
||||
});
|
||||
|
||||
|
@@ -1,11 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="n-layout-page-header">
|
||||
<n-card :bordered="false" title="生成演示详情"> <!-- CURD详情页--> </n-card>
|
||||
</div>
|
||||
<n-card :bordered="false" class="proCard mt-4" size="small" :segmented="{ content: true }">
|
||||
<n-descriptions label-placement="left" class="py-2" column="4">
|
||||
<n-descriptions-item>
|
||||
<n-spin :show="loading" description="请稍候...">
|
||||
<n-drawer v-model:show="showModal" :width="dialogWidth">
|
||||
<n-drawer-content>
|
||||
<template #header> 生成演示详情 </template>
|
||||
<template #footer>
|
||||
<n-button @click="showModal = false"> 关闭 </n-button>
|
||||
</template>
|
||||
<n-descriptions label-placement="left" class="py-2" column="1">
|
||||
<n-descriptions-item>
|
||||
<template #label>分类ID</template>
|
||||
{{ formValue.categoryId }}
|
||||
</n-descriptions-item>
|
||||
@@ -69,23 +72,25 @@
|
||||
</n-descriptions-item>
|
||||
|
||||
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
</n-descriptions>
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
</n-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { View } from '@/api/curdDemo';
|
||||
import { newState, options } from './model';
|
||||
import { getOptionLabel, getOptionTag } from '@/utils/hotgo';
|
||||
import { State, newState, options } from './model';
|
||||
import { adaModalWidth, getOptionLabel, getOptionTag } from '@/utils/hotgo';
|
||||
import { getFileExt } from '@/utils/urlUtils';
|
||||
|
||||
const message = useMessage();
|
||||
const router = useRouter();
|
||||
const id = Number(router.currentRoute.value.params.id);
|
||||
const dialogWidth = ref('75%');
|
||||
const loading = ref(false);
|
||||
const showModal = ref(false);
|
||||
const formValue = ref(newState(null));
|
||||
const fileAvatarCSS = computed(() => {
|
||||
return {
|
||||
@@ -99,12 +104,21 @@
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (id < 1) {
|
||||
message.error('ID不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
formValue.value = await View({ id: id });
|
||||
function openModal(state: State) {
|
||||
adaModalWidth(dialogWidth, 580);
|
||||
showModal.value = true;
|
||||
loading.value = true;
|
||||
View({ id: state.id })
|
||||
.then((res) => {
|
||||
formValue.value = res;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openModal,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@@ -234,7 +234,7 @@
|
||||
|
||||
<n-form ref="formRef" :model="formValue">
|
||||
<n-alert :show-icon="false">关联表数量建议在三个以下</n-alert>
|
||||
|
||||
<div class="mt-4"></div>
|
||||
<n-row :gutter="6" v-for="(join, index) in formValue.options.join" :key="index">
|
||||
<n-col :span="6" style="min-width: 200px">
|
||||
<n-form-item label="关联表" path="join.linkTable">
|
||||
|
@@ -69,6 +69,7 @@
|
||||
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
:mask-closable="false"
|
||||
:show-icon="false"
|
||||
preset="dialog"
|
||||
:title="formParams?.id > 0 ? '编辑用户 #' + formParams?.id : '添加用户'"
|
||||
|
@@ -25,7 +25,13 @@
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-modal v-model:show="showModal" :show-icon="false" preset="dialog" :title="editRoleTitle">
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
:show-icon="false"
|
||||
:mask-closable="false"
|
||||
preset="dialog"
|
||||
:title="editRoleTitle"
|
||||
>
|
||||
<div class="py-3 menu-list" :style="{ maxHeight: '90vh', height: '70vh' }">
|
||||
<n-tree
|
||||
block-line
|
||||
@@ -164,10 +170,10 @@
|
||||
DataScopeSelect,
|
||||
DataScopeEdit,
|
||||
} from '@/api/system/role';
|
||||
import { getMenuList } from '@/api/system/menu';
|
||||
import { EditMenu, getMenuList } from '@/api/system/menu';
|
||||
import { columns } from './columns';
|
||||
import { PlusOutlined } from '@vicons/antd';
|
||||
import { getTreeAll } from '@/utils';
|
||||
import { getAllExpandKeys, getTreeAll } from '@/utils';
|
||||
import { statusOptions } from '@/enums/optionsiEnum';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { getDeptList } from '@/api/org/dept';
|
||||
@@ -338,9 +344,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -394,7 +397,7 @@
|
||||
if (expandedKeys.value.length) {
|
||||
expandedKeys.value = [];
|
||||
} else {
|
||||
expandedKeys.value = treeData.value.map((item: any) => item.key) as [];
|
||||
expandedKeys.value = getAllExpandKeys(treeData) as [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,45 +412,49 @@
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadDataList();
|
||||
await loadMenuList();
|
||||
await loadDeptList();
|
||||
await loadDataScopeSelect();
|
||||
loadDataList();
|
||||
loadMenuList();
|
||||
loadDeptList();
|
||||
loadDataScopeSelect();
|
||||
await loadDataTable({});
|
||||
});
|
||||
|
||||
async function loadDataList() {
|
||||
const data = await getRoleList({ pageSize: 100, page: 1 });
|
||||
optionTreeData.value = [
|
||||
{
|
||||
id: 0,
|
||||
key: 0,
|
||||
label: '顶级角色',
|
||||
pid: 0,
|
||||
name: '顶级角色',
|
||||
},
|
||||
];
|
||||
optionTreeData.value = optionTreeData.value.concat(data.list);
|
||||
function loadDataList() {
|
||||
getRoleList({ pageSize: 100, page: 1 }).then((res) => {
|
||||
optionTreeData.value = [
|
||||
{
|
||||
id: 0,
|
||||
key: 0,
|
||||
label: '顶级角色',
|
||||
pid: 0,
|
||||
name: '顶级角色',
|
||||
},
|
||||
];
|
||||
optionTreeData.value = optionTreeData.value.concat(res.list);
|
||||
});
|
||||
}
|
||||
|
||||
async function loadMenuList() {
|
||||
const treeMenuList = await getMenuList();
|
||||
expandedKeys.value = treeMenuList.list.map((item) => item.key);
|
||||
treeData.value = treeMenuList.list;
|
||||
function loadMenuList() {
|
||||
getMenuList().then((res) => {
|
||||
expandedKeys.value = getAllExpandKeys(res.list) as [];
|
||||
treeData.value = res.list;
|
||||
});
|
||||
}
|
||||
|
||||
async function loadDeptList() {
|
||||
const tmp = await getDeptList({});
|
||||
if (tmp.list) {
|
||||
deptList.value = tmp.list;
|
||||
}
|
||||
function loadDeptList() {
|
||||
getDeptList({}).then((res) => {
|
||||
if (res.list) {
|
||||
deptList.value = res.list;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function loadDataScopeSelect() {
|
||||
const option = await DataScopeSelect();
|
||||
if (option.list) {
|
||||
dataScopeOption.value = option.list;
|
||||
}
|
||||
function loadDataScopeSelect() {
|
||||
DataScopeSelect().then((res) => {
|
||||
if (res.list) {
|
||||
dataScopeOption.value = res.list;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onUpdateValuePid(value: string | number) {
|
||||
|
@@ -12,15 +12,23 @@
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="提现最低手续费(元)" path="cashMinFee">
|
||||
<n-input placeholder="" v-model:value="formValue.cashMinFee" />
|
||||
<n-input-number placeholder="" v-model:value="formValue.cashMinFee" style="width: 100%" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="提现最低手续费比率" path="cashMinFeeRatio">
|
||||
<n-input placeholder="" v-model:value="formValue.cashMinFeeRatio" />
|
||||
<n-input-number
|
||||
placeholder=""
|
||||
v-model:value="formValue.cashMinFeeRatio"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="提现最低金额" path="cashMinMoney">
|
||||
<n-input placeholder="" v-model:value="formValue.cashMinMoney" />
|
||||
<n-input-number
|
||||
placeholder=""
|
||||
v-model:value="formValue.cashMinMoney"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="提现提示信息" path="cashTips">
|
||||
@@ -50,8 +58,8 @@
|
||||
const message = useMessage();
|
||||
const formValue = ref({
|
||||
cashSwitch: '',
|
||||
cashMinFee: '',
|
||||
cashMinFeeRatio: '',
|
||||
cashMinFee: 0,
|
||||
cashMinFeeRatio: 0,
|
||||
cashMinMoney: 0,
|
||||
cashTips: '',
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<n-spin :show="show" description="请稍候...">
|
||||
<n-form
|
||||
:label-width="110"
|
||||
:label-width="150"
|
||||
:model="formValue"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
@@ -41,7 +41,7 @@
|
||||
</n-input-number>
|
||||
</n-form-item>
|
||||
|
||||
<n-tabs type="segment" v-model:value="tabName">
|
||||
<n-tabs type="card" size="small" v-model:value="tabName">
|
||||
<n-tab-pane name="aliyun">
|
||||
<template #tab> 阿里云 </template>
|
||||
<n-divider title-placement="left"> 阿里云</n-divider>
|
||||
@@ -74,7 +74,7 @@
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="短信模板" path="smsAliYunTemplate" label-placement="top">
|
||||
<n-form-item label="短信模板" path="smsAliYunTemplate">
|
||||
<n-dynamic-input
|
||||
v-model:value="formValue.smsAliYunTemplate"
|
||||
preset="pair"
|
||||
@@ -87,14 +87,14 @@
|
||||
<n-tab-pane name="tencent">
|
||||
<template #tab> 腾讯云 </template>
|
||||
<n-divider title-placement="left"> 腾讯云</n-divider>
|
||||
<n-form-item label="SecretId" path="smsTencentSecretId">
|
||||
<n-form-item label="APPID" path="smsTencentSecretId">
|
||||
<n-input v-model:value="formValue.smsTencentSecretId" placeholder="" />
|
||||
<template #feedback>
|
||||
应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak 获取
|
||||
子账号密钥获取地址:https://cloud.tencent.com/document/product/598/37140
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="SecretKey" path="smsTencentSecretKey">
|
||||
<n-form-item label="密钥" path="smsTencentSecretKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.smsTencentSecretKey"
|
||||
@@ -140,7 +140,7 @@
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="短信模板" path="smsTencentTemplate" label-placement="top">
|
||||
<n-form-item label="短信模板" path="smsTencentTemplate">
|
||||
<n-dynamic-input
|
||||
v-model:value="formValue.smsTencentTemplate"
|
||||
preset="pair"
|
||||
@@ -179,10 +179,7 @@
|
||||
class="py-4"
|
||||
>
|
||||
<n-form-item label="事件模板" path="event">
|
||||
<n-select
|
||||
:options="options.config_sms_template"
|
||||
v-model:value="formParams.event"
|
||||
/>
|
||||
<n-select :options="options.config_sms_template" v-model:value="formParams.event" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="手机号" path="mobile">
|
||||
@@ -205,9 +202,7 @@
|
||||
<template #action>
|
||||
<n-space>
|
||||
<n-button @click="() => (showModal = false)">关闭</n-button>
|
||||
<n-button type="info" :loading="formBtnLoading" @click="confirmForm">
|
||||
发送
|
||||
</n-button>
|
||||
<n-button type="info" :loading="formBtnLoading" @click="confirmForm"> 发送 </n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
@@ -215,125 +210,124 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { useMessage } from "naive-ui";
|
||||
import { getConfig, sendTestSms, updateConfig } from "@/api/sys/config";
|
||||
import { Dicts } from "@/api/dict/dict";
|
||||
import { Options } from "@/utils/hotgo";
|
||||
import { GlassesOutline, Glasses } from "@vicons/ionicons5";
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { getConfig, sendTestSms, updateConfig } from '@/api/sys/config';
|
||||
import { Dicts } from '@/api/dict/dict';
|
||||
import { Options } from '@/utils/hotgo';
|
||||
import { GlassesOutline, Glasses } from '@vicons/ionicons5';
|
||||
|
||||
const group = ref("sms");
|
||||
const show = ref(false);
|
||||
const showModal = ref(false);
|
||||
const formBtnLoading = ref(false);
|
||||
const formParams = ref({ mobile: "", event: "", code: "1234" });
|
||||
const group = ref('sms');
|
||||
const show = ref(false);
|
||||
const showModal = ref(false);
|
||||
const formBtnLoading = ref(false);
|
||||
const formParams = ref({ mobile: '', event: '', code: '1234' });
|
||||
|
||||
const rules = {
|
||||
smsDrive: {
|
||||
required: true,
|
||||
message: "请输入默认驱动",
|
||||
trigger: "blur",
|
||||
},
|
||||
};
|
||||
const rules = {
|
||||
smsDrive: {
|
||||
required: true,
|
||||
message: '请输入默认驱动',
|
||||
trigger: 'blur',
|
||||
},
|
||||
};
|
||||
|
||||
const formTestRef = ref<any>();
|
||||
const formRef: any = ref(null);
|
||||
const message = useMessage();
|
||||
const formTestRef = ref<any>();
|
||||
const formRef: any = ref(null);
|
||||
const message = useMessage();
|
||||
|
||||
const options = ref<Options>({
|
||||
config_sms_template: [],
|
||||
config_sms_drive: [],
|
||||
});
|
||||
const options = ref<Options>({
|
||||
config_sms_template: [],
|
||||
config_sms_drive: [],
|
||||
});
|
||||
|
||||
/** 默认选项卡 */
|
||||
const defaultTabName = "aliyun";
|
||||
/** 选项卡名称 */
|
||||
const tabName = ref<string>(defaultTabName);
|
||||
/** 默认选项卡 */
|
||||
const defaultTabName = 'aliyun';
|
||||
/** 选项卡名称 */
|
||||
const tabName = ref<string>(defaultTabName);
|
||||
|
||||
const formValue = ref({
|
||||
smsDrive: defaultTabName,
|
||||
smsMinInterval: 60,
|
||||
smsMaxIpLimit: 10,
|
||||
smsCodeExpire: 600,
|
||||
smsAliYunAccessKeyID: "",
|
||||
smsAliYunAccessKeySecret: "",
|
||||
smsAliYunSign: "",
|
||||
smsAliYunTemplate: null,
|
||||
smsTencentSecretId: "",
|
||||
smsTencentSecretKey: "",
|
||||
smsTencentEndpoint: "sms.tencentcloudapi.com",
|
||||
smsTencentRegion: "ap-guangzhou",
|
||||
smsTencentAppId: "",
|
||||
smsTencentSign: "",
|
||||
smsTencentTemplate: null,
|
||||
});
|
||||
const formValue = ref({
|
||||
smsDrive: defaultTabName,
|
||||
smsMinInterval: 60,
|
||||
smsMaxIpLimit: 10,
|
||||
smsCodeExpire: 600,
|
||||
smsAliYunAccessKeyID: '',
|
||||
smsAliYunAccessKeySecret: '',
|
||||
smsAliYunSign: '',
|
||||
smsAliYunTemplate: null,
|
||||
smsTencentSecretId: '',
|
||||
smsTencentSecretKey: '',
|
||||
smsTencentEndpoint: 'sms.tencentcloudapi.com',
|
||||
smsTencentRegion: 'ap-guangzhou',
|
||||
smsTencentAppId: '',
|
||||
smsTencentSign: '',
|
||||
smsTencentTemplate: null,
|
||||
});
|
||||
|
||||
/** 监听类型变化,同步到选项卡中 */
|
||||
watch(
|
||||
() => formValue.value.smsDrive,
|
||||
(smsDrive: string) => {
|
||||
console.error(smsDrive);
|
||||
tabName.value = smsDrive;
|
||||
}
|
||||
);
|
||||
|
||||
function sendTest() {
|
||||
showModal.value = true;
|
||||
formBtnLoading.value = false;
|
||||
}
|
||||
|
||||
function formSubmit() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
|
||||
message.success("更新成功");
|
||||
load();
|
||||
});
|
||||
} else {
|
||||
message.error("验证失败,请填写完整信息");
|
||||
/** 监听类型变化,同步到选项卡中 */
|
||||
watch(
|
||||
() => formValue.value.smsDrive,
|
||||
(smsDrive: string) => {
|
||||
tabName.value = smsDrive;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
});
|
||||
|
||||
async function load() {
|
||||
show.value = true;
|
||||
await loadOptions();
|
||||
new Promise((_resolve, _reject) => {
|
||||
getConfig({ group: group.value })
|
||||
.then((res) => {
|
||||
res.list.smsAliYunTemplate = JSON.parse(res.list.smsAliYunTemplate);
|
||||
res.list.smsTencentTemplate = JSON.parse(res.list.smsTencentTemplate);
|
||||
formValue.value = res.list;
|
||||
})
|
||||
.finally(() => {
|
||||
show.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Dicts({
|
||||
types: ["config_sms_template", "config_sms_drive"],
|
||||
});
|
||||
}
|
||||
|
||||
function confirmForm(e) {
|
||||
e.preventDefault();
|
||||
formBtnLoading.value = true;
|
||||
formTestRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
sendTestSms(formParams.value).then((_res) => {
|
||||
message.success("发送成功");
|
||||
showModal.value = false;
|
||||
});
|
||||
} else {
|
||||
message.error("请填写完整信息");
|
||||
}
|
||||
function sendTest() {
|
||||
showModal.value = true;
|
||||
formBtnLoading.value = false;
|
||||
}
|
||||
|
||||
function formSubmit() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
|
||||
message.success('更新成功');
|
||||
load();
|
||||
});
|
||||
} else {
|
||||
message.error('验证失败,请填写完整信息');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
async function load() {
|
||||
show.value = true;
|
||||
await loadOptions();
|
||||
new Promise((_resolve, _reject) => {
|
||||
getConfig({ group: group.value })
|
||||
.then((res) => {
|
||||
res.list.smsAliYunTemplate = JSON.parse(res.list.smsAliYunTemplate);
|
||||
res.list.smsTencentTemplate = JSON.parse(res.list.smsTencentTemplate);
|
||||
formValue.value = res.list;
|
||||
})
|
||||
.finally(() => {
|
||||
show.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Dicts({
|
||||
types: ['config_sms_template', 'config_sms_drive'],
|
||||
});
|
||||
}
|
||||
|
||||
function confirmForm(e) {
|
||||
e.preventDefault();
|
||||
formBtnLoading.value = true;
|
||||
formTestRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
sendTestSms(formParams.value).then((_res) => {
|
||||
message.success('发送成功');
|
||||
showModal.value = false;
|
||||
});
|
||||
} else {
|
||||
message.error('请填写完整信息');
|
||||
}
|
||||
formBtnLoading.value = false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<n-spin :show="show" description="请稍候...">
|
||||
<n-form
|
||||
:label-width="100"
|
||||
:label-width="150"
|
||||
:model="formValue"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
@@ -42,11 +42,7 @@
|
||||
<n-form-item label="文件类型限制" path="uploadFileType">
|
||||
<n-input v-model:value="formValue.uploadFileType" placeholder="" />
|
||||
</n-form-item>
|
||||
<n-tabs
|
||||
type="card"
|
||||
tab-style="min-width: 120px; text-aling:center;"
|
||||
v-model:value="tabName"
|
||||
>
|
||||
<n-tabs type="card" size="small" v-model:value="tabName">
|
||||
<n-tab-pane name="local">
|
||||
<template #tab> 本地存储</template>
|
||||
<n-divider title-placement="left">本地存储</n-divider>
|
||||
@@ -56,111 +52,6 @@
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="ucloud">
|
||||
<template #tab> ucloud对象存储</template>
|
||||
<n-divider title-placement="left">ucloud对象存储</n-divider>
|
||||
<n-form-item label="公钥" path="uploadUCloudPublicKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadUCloudPublicKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
<template #feedback>
|
||||
获取地址:https://console.ucloud.cn/ufile/token
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="私钥" path="uploadUCloudPrivateKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadUCloudPrivateKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储路径" path="uploadUCloudPath">
|
||||
<n-input v-model:value="formValue.uploadUCloudPath" placeholder="" />
|
||||
<template #feedback>填对对象存储中的相对路径</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="地域API" path="uploadUCloudBucketHost">
|
||||
<n-input v-model:value="formValue.uploadUCloudBucketHost" placeholder="" />
|
||||
</n-form-item>
|
||||
<n-form-item label="存储桶名称" path="uploadUCloudBucketName">
|
||||
<n-input v-model:value="formValue.uploadUCloudBucketName" placeholder="" />
|
||||
<template #feedback>存储空间名称</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储桶地域host" path="uploadUCloudFileHost">
|
||||
<n-input v-model:value="formValue.uploadUCloudFileHost" placeholder="" />
|
||||
<template #feedback>不需要包含桶名称</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="访问域名" path="uploadUCloudEndpoint">
|
||||
<n-input v-model:value="formValue.uploadUCloudEndpoint" placeholder="" />
|
||||
<template #feedback>
|
||||
格式,http://abc.com 或 https://abc.com,不可为空
|
||||
</template>
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="cos">
|
||||
<template #tab> 腾讯云COS存储</template>
|
||||
<n-divider title-placement="left">腾讯云COS存储</n-divider>
|
||||
<n-form-item label="secretId" path="uploadCosSecretId">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadCosSecretId"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
<template #feedback>
|
||||
子账号密钥获取地址:https://cloud.tencent.com/document/product/598/37140
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="secretKey" path="uploadCosSecretKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadCosSecretKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储路径" path="uploadCosBucketURL">
|
||||
<n-input v-model:value="formValue.uploadCosBucketURL" placeholder="" />
|
||||
<template #feedback>填对对象存储中的相对路径</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="地域API" path="uploadCosPath">
|
||||
<n-input v-model:value="formValue.uploadCosPath" placeholder="" />
|
||||
<template #feedback>
|
||||
控制台查看地址:https://console.cloud.tencent.com/cos5/bucket
|
||||
</template>
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="oss">
|
||||
<template #tab> 阿里云OSS存储</template>
|
||||
<n-divider title-placement="left">阿里云OSS存储</n-divider>
|
||||
@@ -177,9 +68,7 @@
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
<template #feedback>
|
||||
创建地址:https://ram.console.aliyun.com/manage/ak
|
||||
</template>
|
||||
<template #feedback> 创建地址:https://ram.console.aliyun.com/manage/ak </template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="AccessKey Secret" path="uploadOssSecretKey">
|
||||
@@ -212,6 +101,42 @@
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="cos">
|
||||
<template #tab> 腾讯云COS存储</template>
|
||||
<n-divider title-placement="left">腾讯云COS存储</n-divider>
|
||||
<n-form-item label="APPID" path="uploadCosSecretId">
|
||||
<n-input v-model:value="formValue.uploadCosSecretId" />
|
||||
<template #feedback>
|
||||
子账号密钥获取地址:https://cloud.tencent.com/document/product/598/37140
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="密钥" path="uploadCosSecretKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadCosSecretKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储路径" path="uploadCosPath">
|
||||
<n-input v-model:value="formValue.uploadCosPath" placeholder="" />
|
||||
<template #feedback>填对对象存储中的相对路径</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="访问域名" path="uploadCosBucketURL">
|
||||
<n-input v-model:value="formValue.uploadCosBucketURL" placeholder="" />
|
||||
<template #feedback
|
||||
>控制台查看地址:https://console.cloud.tencent.com/cos5/bucket</template
|
||||
>
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="qiniu">
|
||||
<template #tab> 七牛云对象存储</template>
|
||||
<n-divider title-placement="left">七牛云对象存储</n-divider>
|
||||
@@ -256,9 +181,64 @@
|
||||
<n-input v-model:value="formValue.uploadQiNiuDomain" placeholder="" />
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="ucloud">
|
||||
<template #tab> ucloud对象存储</template>
|
||||
<n-divider title-placement="left">ucloud对象存储</n-divider>
|
||||
<n-form-item label="公钥" path="uploadUCloudPublicKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadUCloudPublicKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
<template #feedback> 获取地址:https://console.ucloud.cn/ufile/token </template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="私钥" path="uploadUCloudPrivateKey">
|
||||
<n-input
|
||||
type="password"
|
||||
v-model:value="formValue.uploadUCloudPrivateKey"
|
||||
show-password-on="click"
|
||||
>
|
||||
<template #password-visible-icon>
|
||||
<n-icon :size="16" :component="GlassesOutline" />
|
||||
</template>
|
||||
<template #password-invisible-icon>
|
||||
<n-icon :size="16" :component="Glasses" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储路径" path="uploadUCloudPath">
|
||||
<n-input v-model:value="formValue.uploadUCloudPath" placeholder="" />
|
||||
<template #feedback>填对对象存储中的相对路径</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="地域API" path="uploadUCloudBucketHost">
|
||||
<n-input v-model:value="formValue.uploadUCloudBucketHost" placeholder="" />
|
||||
</n-form-item>
|
||||
<n-form-item label="存储桶名称" path="uploadUCloudBucketName">
|
||||
<n-input v-model:value="formValue.uploadUCloudBucketName" placeholder="" />
|
||||
<template #feedback>存储空间名称</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="存储桶地域host" path="uploadUCloudFileHost">
|
||||
<n-input v-model:value="formValue.uploadUCloudFileHost" placeholder="" />
|
||||
<template #feedback>不需要包含桶名称</template>
|
||||
</n-form-item>
|
||||
<n-form-item label="访问域名" path="uploadUCloudEndpoint">
|
||||
<n-input v-model:value="formValue.uploadUCloudEndpoint" placeholder="" />
|
||||
<template #feedback> 格式,http://abc.com 或 https://abc.com,不可为空 </template>
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
|
||||
<n-tab-pane name="minio">
|
||||
<template #tab> minio配置</template>
|
||||
<n-divider title-placement="left">minio配置</n-divider>
|
||||
<template #tab> minio对象存储</template>
|
||||
<n-divider title-placement="left">minio对象存储</n-divider>
|
||||
<n-form-item label="AccessKey ID" path="uploadMinioAccessKey">
|
||||
<n-input
|
||||
type="password"
|
||||
@@ -293,14 +273,14 @@
|
||||
<n-input v-model:value="formValue.uploadMinioEndpoint" placeholder="" />
|
||||
<template #feedback> Endpoint(不带http://和路径)</template>
|
||||
</n-form-item>
|
||||
<n-form-item path="uploadMinioUseSSL">
|
||||
<n-form-item path="uploadMinioUseSSL" label="SSL">
|
||||
<n-switch
|
||||
v-model:value="formValue.uploadMinioUseSSL"
|
||||
:checked-value="1"
|
||||
:unchecked-value="2"
|
||||
>
|
||||
<template #checked> 启用SSL</template>
|
||||
<template #unchecked> 禁用SSL</template>
|
||||
<template #checked> 已启用</template>
|
||||
<template #unchecked> 已禁用</template>
|
||||
</n-switch>
|
||||
</n-form-item>
|
||||
<n-form-item label="储存路径" path="uploadMinioPath">
|
||||
@@ -309,7 +289,7 @@
|
||||
<n-form-item label="存储桶名称" path="uploadMinioBucket">
|
||||
<n-input v-model:value="formValue.uploadMinioBucket" placeholder="" />
|
||||
</n-form-item>
|
||||
<n-form-item label="对外访问域名" path="uploadMinioDomain">
|
||||
<n-form-item label="访问域名" path="uploadMinioDomain">
|
||||
<n-input v-model:value="formValue.uploadMinioDomain" placeholder="" />
|
||||
</n-form-item>
|
||||
</n-tab-pane>
|
||||
@@ -325,115 +305,115 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { useMessage } from "naive-ui";
|
||||
import { getConfig, updateConfig } from "@/api/sys/config";
|
||||
import { Glasses, GlassesOutline } from "@vicons/ionicons5";
|
||||
import { Dicts } from "@/api/dict/dict";
|
||||
import { Options } from "@/utils/hotgo";
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { getConfig, updateConfig } from '@/api/sys/config';
|
||||
import { Glasses, GlassesOutline } from '@vicons/ionicons5';
|
||||
import { Dicts } from '@/api/dict/dict';
|
||||
import { Options } from '@/utils/hotgo';
|
||||
|
||||
const group = ref("upload");
|
||||
const show = ref(false);
|
||||
const formRef: any = ref(null);
|
||||
const message = useMessage();
|
||||
const group = ref('upload');
|
||||
const show = ref(false);
|
||||
const formRef: any = ref(null);
|
||||
const message = useMessage();
|
||||
|
||||
const rules = {
|
||||
uploadDrive: {
|
||||
required: true,
|
||||
message: "请输入默认驱动",
|
||||
trigger: "blur",
|
||||
},
|
||||
};
|
||||
const rules = {
|
||||
uploadDrive: {
|
||||
required: true,
|
||||
message: '请输入默认驱动',
|
||||
trigger: 'blur',
|
||||
},
|
||||
};
|
||||
|
||||
const options = ref<Options>({
|
||||
config_upload_drive: [],
|
||||
});
|
||||
const options = ref<Options>({
|
||||
config_upload_drive: [],
|
||||
});
|
||||
|
||||
/** 默认选项卡 */
|
||||
const defaultTabName = "local";
|
||||
/** 选项卡名称 */
|
||||
const tabName = ref<string>(defaultTabName);
|
||||
/** 默认选项卡 */
|
||||
const defaultTabName = 'local';
|
||||
/** 选项卡名称 */
|
||||
const tabName = ref<string>(defaultTabName);
|
||||
|
||||
const formValue = ref({
|
||||
uploadDrive: defaultTabName,
|
||||
uploadImageSize: 2,
|
||||
uploadImageType: "",
|
||||
uploadFileSize: 10,
|
||||
uploadFileType: "",
|
||||
uploadLocalPath: "",
|
||||
uploadUCloudPath: "",
|
||||
uploadUCloudPublicKey: "",
|
||||
uploadUCloudPrivateKey: "",
|
||||
uploadUCloudBucketHost: "api.ucloud.cn",
|
||||
uploadUCloudBucketName: "",
|
||||
uploadUCloudFileHost: "cn-bj.ufileos.com",
|
||||
uploadUCloudEndpoint: "",
|
||||
uploadCosSecretId: "",
|
||||
uploadCosSecretKey: "",
|
||||
uploadCosBucketURL: "",
|
||||
uploadCosPath: "",
|
||||
uploadOssSecretId: "",
|
||||
uploadOssSecretKey: "",
|
||||
uploadOssEndpoint: "",
|
||||
uploadOssBucketURL: "",
|
||||
uploadOssPath: "",
|
||||
uploadOssBucket: "",
|
||||
uploadQiNiuAccessKey: "",
|
||||
uploadQiNiuSecretKey: "",
|
||||
uploadQiNiuDomain: "",
|
||||
uploadQiNiuPath: "",
|
||||
uploadQiNiuBucket: "",
|
||||
uploadMinioAccessKey: "",
|
||||
uploadMinioSecretKey: "",
|
||||
uploadMinioEndpoint: "",
|
||||
uploadMinioUseSSL: 2,
|
||||
uploadMinioPath: "",
|
||||
uploadMinioBucket: "",
|
||||
uploadMinioDomain: "",
|
||||
});
|
||||
const formValue = ref({
|
||||
uploadDrive: defaultTabName,
|
||||
uploadImageSize: 2,
|
||||
uploadImageType: '',
|
||||
uploadFileSize: 10,
|
||||
uploadFileType: '',
|
||||
uploadLocalPath: '',
|
||||
uploadUCloudPath: '',
|
||||
uploadUCloudPublicKey: '',
|
||||
uploadUCloudPrivateKey: '',
|
||||
uploadUCloudBucketHost: 'api.ucloud.cn',
|
||||
uploadUCloudBucketName: '',
|
||||
uploadUCloudFileHost: 'cn-bj.ufileos.com',
|
||||
uploadUCloudEndpoint: '',
|
||||
uploadCosSecretId: '',
|
||||
uploadCosSecretKey: '',
|
||||
uploadCosBucketURL: '',
|
||||
uploadCosPath: '',
|
||||
uploadOssSecretId: '',
|
||||
uploadOssSecretKey: '',
|
||||
uploadOssEndpoint: '',
|
||||
uploadOssBucketURL: '',
|
||||
uploadOssPath: '',
|
||||
uploadOssBucket: '',
|
||||
uploadQiNiuAccessKey: '',
|
||||
uploadQiNiuSecretKey: '',
|
||||
uploadQiNiuDomain: '',
|
||||
uploadQiNiuPath: '',
|
||||
uploadQiNiuBucket: '',
|
||||
uploadMinioAccessKey: '',
|
||||
uploadMinioSecretKey: '',
|
||||
uploadMinioEndpoint: '',
|
||||
uploadMinioUseSSL: 2,
|
||||
uploadMinioPath: '',
|
||||
uploadMinioBucket: '',
|
||||
uploadMinioDomain: '',
|
||||
});
|
||||
|
||||
/** 监听类型变化,同步到选项卡中 */
|
||||
watch(
|
||||
() => formValue.value.uploadDrive,
|
||||
(uploadDrive: string) => {
|
||||
tabName.value = uploadDrive;
|
||||
}
|
||||
);
|
||||
|
||||
function formSubmit() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
|
||||
message.success("更新成功");
|
||||
load();
|
||||
});
|
||||
} else {
|
||||
message.error("验证失败,请填写完整信息");
|
||||
/** 监听类型变化,同步到选项卡中 */
|
||||
watch(
|
||||
() => formValue.value.uploadDrive,
|
||||
(uploadDrive: string) => {
|
||||
tabName.value = uploadDrive;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
load();
|
||||
await loadOptions();
|
||||
});
|
||||
function formSubmit() {
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
|
||||
message.success('更新成功');
|
||||
load();
|
||||
});
|
||||
} else {
|
||||
message.error('验证失败,请填写完整信息');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function load() {
|
||||
show.value = true;
|
||||
new Promise((_resolve, _reject) => {
|
||||
getConfig({ group: group.value })
|
||||
.then((res) => {
|
||||
formValue.value = res.list;
|
||||
})
|
||||
.finally(() => {
|
||||
show.value = false;
|
||||
});
|
||||
onMounted(async () => {
|
||||
load();
|
||||
await loadOptions();
|
||||
});
|
||||
}
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Dicts({
|
||||
types: ["config_upload_drive"],
|
||||
});
|
||||
}
|
||||
function load() {
|
||||
show.value = true;
|
||||
new Promise((_resolve, _reject) => {
|
||||
getConfig({ group: group.value })
|
||||
.then((res) => {
|
||||
formValue.value = res.list;
|
||||
})
|
||||
.finally(() => {
|
||||
show.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadOptions() {
|
||||
options.value = await Dicts({
|
||||
types: ['config_upload_drive'],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
@@ -34,41 +34,41 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent, reactive, toRefs } from "vue";
|
||||
/** 异步加载的组件,用到的时候再加载组件 */
|
||||
const BasicSetting = defineAsyncComponent(() => {
|
||||
return import("./BasicSetting.vue");
|
||||
}),
|
||||
RevealSetting = defineAsyncComponent(() => {
|
||||
return import("./RevealSetting.vue");
|
||||
}),
|
||||
EmailSetting = defineAsyncComponent(() => {
|
||||
return import("./EmailSetting.vue");
|
||||
}),
|
||||
ThemeSetting = defineAsyncComponent(() => {
|
||||
return import("./ThemeSetting.vue");
|
||||
}),
|
||||
CashSetting = defineAsyncComponent(() => {
|
||||
return import("./CashSetting.vue");
|
||||
}),
|
||||
UploadSetting = defineAsyncComponent(() => {
|
||||
return import("./UploadSetting.vue");
|
||||
}),
|
||||
GeoSetting = defineAsyncComponent(() => {
|
||||
return import("./GeoSetting.vue");
|
||||
}),
|
||||
SmsSetting = defineAsyncComponent(() => {
|
||||
return import("./SmsSetting.vue");
|
||||
}),
|
||||
PaySetting = defineAsyncComponent(() => {
|
||||
return import("./PaySetting.vue");
|
||||
}),
|
||||
WechatSetting = defineAsyncComponent(() => {
|
||||
return import("./WechatSetting.vue");
|
||||
}),
|
||||
LoginSetting = defineAsyncComponent(() => {
|
||||
return import("./LoginSetting.vue");
|
||||
});
|
||||
import { defineAsyncComponent, defineComponent, reactive, toRefs } from 'vue';
|
||||
/** 异步加载的组件,用到的时候再加载组件 */
|
||||
const BasicSetting = defineAsyncComponent(() => {
|
||||
return import('./BasicSetting.vue');
|
||||
}),
|
||||
RevealSetting = defineAsyncComponent(() => {
|
||||
return import('./RevealSetting.vue');
|
||||
}),
|
||||
EmailSetting = defineAsyncComponent(() => {
|
||||
return import('./EmailSetting.vue');
|
||||
}),
|
||||
ThemeSetting = defineAsyncComponent(() => {
|
||||
return import('./ThemeSetting.vue');
|
||||
}),
|
||||
CashSetting = defineAsyncComponent(() => {
|
||||
return import('./CashSetting.vue');
|
||||
}),
|
||||
UploadSetting = defineAsyncComponent(() => {
|
||||
return import('./UploadSetting.vue');
|
||||
}),
|
||||
GeoSetting = defineAsyncComponent(() => {
|
||||
return import('./GeoSetting.vue');
|
||||
}),
|
||||
SmsSetting = defineAsyncComponent(() => {
|
||||
return import('./SmsSetting.vue');
|
||||
}),
|
||||
PaySetting = defineAsyncComponent(() => {
|
||||
return import('./PaySetting.vue');
|
||||
}),
|
||||
WechatSetting = defineAsyncComponent(() => {
|
||||
return import('./WechatSetting.vue');
|
||||
}),
|
||||
LoginSetting = defineAsyncComponent(() => {
|
||||
return import('./LoginSetting.vue');
|
||||
});
|
||||
const typeTabList = [
|
||||
{
|
||||
name: '基本设置',
|
||||
|
@@ -106,7 +106,8 @@
|
||||
import { statusOptions } from '@/enums/optionsiEnum';
|
||||
import { TypeSelect } from '@/api/sys/config';
|
||||
import { Option } from '@/utils/hotgo';
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import { findTreeDataById } from '@/utils';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
const options = ref<Option>();
|
||||
interface Props {
|
||||
checkedId?: number;
|
||||
@@ -320,11 +321,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpdateTypeIdValue(
|
||||
value: string | number | Array<string | number> | null,
|
||||
_option: TreeSelectOption | null | Array<TreeSelectOption | null>
|
||||
) {
|
||||
function handleUpdateTypeIdValue(value) {
|
||||
const row = findTreeDataById(typeList.value, value);
|
||||
if (!row) {
|
||||
message.error('未找到该节点数据');
|
||||
return;
|
||||
}
|
||||
formParams.value.typeId = value;
|
||||
formParams.value.type = row.type;
|
||||
}
|
||||
|
||||
async function loadOptions() {
|
||||
|
@@ -22,8 +22,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
const root = process.cwd();
|
||||
const env = loadEnv(mode, root);
|
||||
const viteEnv = wrapperEnv(env);
|
||||
const { VITE_PUBLIC_PATH, VITE_DROP_CONSOLE, VITE_PORT, VITE_PROXY } =
|
||||
viteEnv;
|
||||
const { VITE_PUBLIC_PATH, VITE_DROP_CONSOLE, VITE_PORT, VITE_PROXY } = viteEnv;
|
||||
const isBuild = command === 'build';
|
||||
return {
|
||||
base: VITE_PUBLIC_PATH,
|
||||
@@ -44,6 +43,9 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
plugins: createVitePlugins(viteEnv, isBuild),
|
||||
define: {
|
||||
__APP_INFO__: JSON.stringify(__APP_INFO__),
|
||||
__VUE_OPTIONS_API__: true,
|
||||
__VUE_PROD_DEVTOOLS__: false,
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true,
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
|
Reference in New Issue
Block a user