mirror of
				https://github.com/bufanyun/hotgo.git
				synced 2025-11-04 08:13:45 +08:00 
			
		
		
		
	hotgo2.1.3版本发布
This commit is contained in:
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							@@ -20,7 +20,7 @@
 | 
			
		||||
		<a href="https://vitejs.dev/" target="_blank">
 | 
			
		||||
		    <img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite">
 | 
			
		||||
		</a>
 | 
			
		||||
		<a href="https://raw.githubusercontent.com/tusen-ai/naive-ui/main/LICENSE" target="_blank">
 | 
			
		||||
		<a href="https://github.com/bufanyun/hotgo/blob/v2.0/LICENSE" target="_blank">
 | 
			
		||||
		    <img src="https://img.shields.io/badge/license-MIT-success" alt="license">
 | 
			
		||||
		</a>
 | 
			
		||||
	</p>
 | 
			
		||||
@@ -47,20 +47,20 @@
 | 
			
		||||
2. 部门管理:配置系统组织机构(公司、部门、岗位),树结构展现支持数据权限。
 | 
			
		||||
3. 岗位管理:配置系统用户所属担任职务。
 | 
			
		||||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
 | 
			
		||||
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
 | 
			
		||||
5. 角色管理:角色菜单权限分配、设置角色按机构或按上下级关系进行数据范围权限划分。
 | 
			
		||||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
 | 
			
		||||
7. 配置管理:对系统动态配置常用参数。
 | 
			
		||||
8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
 | 
			
		||||
9. 登录日志:系统登录日志记录查询包含登录异常。
 | 
			
		||||
10. 调度日志:服务端运行所产生的警告、异常、崩溃日志的详细数据和堆栈信息。
 | 
			
		||||
10. 服务日志:服务端运行所产生的警告、异常、崩溃日志的详细数据和堆栈信息。
 | 
			
		||||
11. 在线用户:当前系统中活跃用户状态监控。
 | 
			
		||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
 | 
			
		||||
13. 代码生成:支持自动化生成前后端代码。CURD关联表、树表、消息队列、定时任务一键生成等。
 | 
			
		||||
14. 服务监控:监视当前系统CPU、内存、磁盘、网络、堆栈等相关信息。
 | 
			
		||||
15. 附件管理:文件上传,多种上传方式适配。
 | 
			
		||||
16. 消息队列:同时兼容 kafka、redis、rocketmq,一键配置切换到自己想用的MQ。
 | 
			
		||||
17. 通知公告:采用websocket及时推送在线用户最新公告。
 | 
			
		||||
18. 地区编码:整合国内通用省市区编码,运用于项目于一身。
 | 
			
		||||
16. 消息队列:同时兼容 kafka、redis、rocketmq、磁盘队列,一键配置切换到场景适用的MQ。
 | 
			
		||||
17. 通知公告:采用websocket实时推送在线用户最新通知、公告、私信消息。
 | 
			
		||||
18. 地区编码:整合国内通用省市区编码,运用于项目于一身,支持动态省市区选项。
 | 
			
		||||
19. 常用工具:集成常用的工具包和命令行工具,可以快速开发自定义命令行,多种启动入口。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -201,7 +201,7 @@ web端:
 | 
			
		||||
 | 
			
		||||
* 本项目包含的第三方源码和二进制文件之版权信息另行标注。
 | 
			
		||||
 | 
			
		||||
* 版权所有Copyright © 2020-2024 by Ms (https://github.com/bufanyun/hotgo)
 | 
			
		||||
* 版权所有Copyright © 2020-2023 by Ms (https://github.com/bufanyun/hotgo)
 | 
			
		||||
 | 
			
		||||
* All rights reserved。
 | 
			
		||||
 | 
			
		||||
@@ -223,7 +223,7 @@ web端:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
[MIT © HotGo-2021](./LICENSE)
 | 
			
		||||
[MIT © HotGo-2023](./LICENSE)
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,36 +49,11 @@ func TableColumns(ctx context.Context, in sysin.GenCodesColumnListInp) (fields [
 | 
			
		||||
 | 
			
		||||
func TableSelects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error) {
 | 
			
		||||
	res = new(sysin.GenCodesSelectsModel)
 | 
			
		||||
	for k, v := range consts.GenCodesTypeNameMap {
 | 
			
		||||
		row := &sysin.GenTypeSelect{
 | 
			
		||||
			Value:     k,
 | 
			
		||||
			Name:      v,
 | 
			
		||||
			Label:     v,
 | 
			
		||||
			Templates: make(form.Selects, 0),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		confName, ok := consts.GenCodesTypeConfMap[k]
 | 
			
		||||
		if ok {
 | 
			
		||||
			var temps []*model.GenerateAppCrudTemplate
 | 
			
		||||
			err = g.Cfg().MustGet(ctx, "hggen.application."+confName+".templates").Scan(&temps)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if len(temps) > 0 {
 | 
			
		||||
				for index, temp := range temps {
 | 
			
		||||
					row.Templates = append(row.Templates, &form.Select{
 | 
			
		||||
						Value: index,
 | 
			
		||||
						Label: temp.Group,
 | 
			
		||||
						Name:  temp.Group,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
				sort.Sort(row.Templates)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res.GenType = append(res.GenType, row)
 | 
			
		||||
	res.GenType, err = GenTypeSelect(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(res.GenType)
 | 
			
		||||
 | 
			
		||||
	res.Db = DbSelect(ctx)
 | 
			
		||||
 | 
			
		||||
	for k, v := range consts.GenCodesStatusNameMap {
 | 
			
		||||
@@ -126,9 +101,12 @@ func TableSelects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(res.FormRole)
 | 
			
		||||
 | 
			
		||||
	dictMode, _ := service.SysDictType().TreeSelect(ctx, sysin.DictTreeSelectInp{})
 | 
			
		||||
 | 
			
		||||
	dictMode, err := service.SysDictType().TreeSelect(ctx, sysin.DictTreeSelectInp{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	res.DictMode = dictMode
 | 
			
		||||
 | 
			
		||||
	for _, v := range views.WhereModes {
 | 
			
		||||
		res.WhereMode = append(res.WhereMode, &form.Select{
 | 
			
		||||
			Value: v,
 | 
			
		||||
@@ -140,6 +118,42 @@ func TableSelects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenTypeSelect 获取生成类型选项
 | 
			
		||||
func GenTypeSelect(ctx context.Context) (res sysin.GenTypeSelects, err error) {
 | 
			
		||||
	for k, v := range consts.GenCodesTypeNameMap {
 | 
			
		||||
		row := &sysin.GenTypeSelect{
 | 
			
		||||
			Value:     k,
 | 
			
		||||
			Name:      v,
 | 
			
		||||
			Label:     v,
 | 
			
		||||
			Templates: make(form.Selects, 0),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		confName, ok := consts.GenCodesTypeConfMap[k]
 | 
			
		||||
		if ok {
 | 
			
		||||
			var temps []*model.GenerateAppCrudTemplate
 | 
			
		||||
			err = g.Cfg().MustGet(ctx, "hggen.application."+confName+".templates").Scan(&temps)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if len(temps) > 0 {
 | 
			
		||||
				for index, temp := range temps {
 | 
			
		||||
					row.Templates = append(row.Templates, &form.Select{
 | 
			
		||||
						Value: index,
 | 
			
		||||
						Label: temp.Group,
 | 
			
		||||
						Name:  temp.Group,
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
				sort.Sort(row.Templates)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res = append(res, row)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(res)
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DbSelect db选项
 | 
			
		||||
func DbSelect(ctx context.Context) (res form.Selects) {
 | 
			
		||||
	dbs := g.Cfg().MustGet(ctx, "hggen.selectDbs")
 | 
			
		||||
 
 | 
			
		||||
@@ -146,14 +146,17 @@ func (s *sAdminNotice) Status(ctx context.Context, in adminin.NoticeStatusInp) (
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxSort 最大排序
 | 
			
		||||
func (s *sAdminNotice) MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (*adminin.NoticeMaxSortModel, error) {
 | 
			
		||||
	var res adminin.NoticeMaxSortModel
 | 
			
		||||
	if err := s.Model(ctx).Order("sort desc").Scan(&res); err != nil {
 | 
			
		||||
		err = gerror.Wrap(err, consts.ErrorORM)
 | 
			
		||||
		return nil, err
 | 
			
		||||
func (s *sAdminNotice) MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error) {
 | 
			
		||||
	if err = dao.AdminNotice.Ctx(ctx).Order("sort desc").Scan(&res); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		res = new(adminin.NoticeMaxSortModel)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res.Sort = form.DefaultMaxSort(ctx, res.Sort)
 | 
			
		||||
	return &res, nil
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// View 获取指定字典类型信息
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"github.com/gogf/gf/v2/errors/gerror"
 | 
			
		||||
	"github.com/gogf/gf/v2/frame/g"
 | 
			
		||||
	"github.com/gogf/gf/v2/os/gtime"
 | 
			
		||||
	"github.com/gogf/gf/v2/text/gstr"
 | 
			
		||||
	"github.com/gogf/gf/v2/util/gconv"
 | 
			
		||||
	"hotgo/internal/consts"
 | 
			
		||||
	"hotgo/internal/dao"
 | 
			
		||||
@@ -22,6 +23,13 @@ import (
 | 
			
		||||
	"hotgo/internal/service"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var MaskDemoField = []string{
 | 
			
		||||
	"smtpUser", "smtpPass", // 邮箱
 | 
			
		||||
	"uploadUCloudPublicKey", "uploadUCloudPrivateKey", // 云存储
 | 
			
		||||
	"geoAmapWebKey",                                    // 地图
 | 
			
		||||
	"smsAliyunAccessKeyID", "smsAliyunAccessKeySecret", // 短信
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sSysConfig struct{}
 | 
			
		||||
 | 
			
		||||
func NewSysConfig() *sSysConfig {
 | 
			
		||||
@@ -156,7 +164,12 @@ func (s *sSysConfig) GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			res.List[v.Key] = val
 | 
			
		||||
			if isDemo.Bool() && (v.Key == "smtpUser" || v.Key == "smtpPass") {
 | 
			
		||||
			//if isDemo.Bool() && (v.Key == "smtpUser" || v.Key == "smtpPass") {
 | 
			
		||||
			//	res.List[v.Key] = consts.DemoTips
 | 
			
		||||
			//	res.List[v.Key] = consts.DemoTips
 | 
			
		||||
			//}
 | 
			
		||||
 | 
			
		||||
			if isDemo.Bool() && gstr.InArray(MaskDemoField, v.Key) {
 | 
			
		||||
				res.List[v.Key] = consts.DemoTips
 | 
			
		||||
				res.List[v.Key] = consts.DemoTips
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -162,6 +162,34 @@ func (s *sSysGenCodes) List(ctx context.Context, in sysin.GenCodesListInp) (list
 | 
			
		||||
		return list, totalCount, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	typeSelect, err := hggen.GenTypeSelect(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	getTemplateGroup := func(row *sysin.GenCodesListModel) string {
 | 
			
		||||
		if row == nil {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
		for _, v := range typeSelect {
 | 
			
		||||
			if v.Value == int(row.GenType) {
 | 
			
		||||
				for index, template := range v.Templates {
 | 
			
		||||
					if index == row.GenTemplate {
 | 
			
		||||
						return template.Label
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(list) > 0 {
 | 
			
		||||
		for _, v := range list {
 | 
			
		||||
			v.GenTemplateGroup = getTemplateGroup(v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return list, totalCount, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,7 @@ type GenCodesListInp struct {
 | 
			
		||||
 | 
			
		||||
type GenCodesListModel struct {
 | 
			
		||||
	entity.SysGenCodes
 | 
			
		||||
	GenTemplateGroup string `json:"genTemplateGroup" dc:"生成模板组名"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenCodesStatusInp 更新状态
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								web/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								web/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -4,6 +4,8 @@ node_modules
 | 
			
		||||
/dist
 | 
			
		||||
dist.zip
 | 
			
		||||
dist_electron
 | 
			
		||||
package-lock.json
 | 
			
		||||
yarn.lock
 | 
			
		||||
 | 
			
		||||
# local env files
 | 
			
		||||
.env.local
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,11 @@ export const notificationStore = defineStore({
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    getUnreadCount() {
 | 
			
		||||
      return this.notifyUnread + this.noticeUnread + this.letterUnread;
 | 
			
		||||
      const count = this.notifyUnread + this.noticeUnread + this.letterUnread;
 | 
			
		||||
      if (count > 0) {
 | 
			
		||||
        return count;
 | 
			
		||||
      }
 | 
			
		||||
      return 0;
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,6 @@ export function encodeParams(obj) {
 | 
			
		||||
 * @param obj1
 | 
			
		||||
 */
 | 
			
		||||
export function copyObj(obj2: any, obj1: any) {
 | 
			
		||||
  console.log('obj1:' + JSON.stringify(obj1));
 | 
			
		||||
  for (const key in obj1) {
 | 
			
		||||
    if (obj2[key] !== undefined) {
 | 
			
		||||
      obj2[key] = obj1[key];
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,17 @@
 | 
			
		||||
import { h, unref } from 'vue';
 | 
			
		||||
import type { App, Plugin } from 'vue';
 | 
			
		||||
import { NIcon, NTag } from 'naive-ui';
 | 
			
		||||
import { NIcon, NTag, NTooltip } from 'naive-ui';
 | 
			
		||||
import { PageEnum } from '@/enums/pageEnum';
 | 
			
		||||
import { isObject } from './is/index';
 | 
			
		||||
import { cloneDeep } from 'lodash-es';
 | 
			
		||||
 | 
			
		||||
export const renderTooltip = (trigger, content) => {
 | 
			
		||||
  return h(NTooltip, null, {
 | 
			
		||||
    trigger: () => trigger,
 | 
			
		||||
    default: () => content,
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * render 图标
 | 
			
		||||
 * */
 | 
			
		||||
 
 | 
			
		||||
@@ -134,6 +134,7 @@
 | 
			
		||||
            <template v-if="formParams.type === 1">
 | 
			
		||||
              <n-input
 | 
			
		||||
                type="textarea"
 | 
			
		||||
                :autosize="{ minRows: 3, maxRows: 30 }"
 | 
			
		||||
                placeholder="请输入通知内容"
 | 
			
		||||
                v-model:value="formParams.content"
 | 
			
		||||
              />
 | 
			
		||||
 
 | 
			
		||||
@@ -174,6 +174,26 @@
 | 
			
		||||
      },
 | 
			
		||||
      width: 180,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '生成模板',
 | 
			
		||||
      key: 'genTemplate',
 | 
			
		||||
      render(row) {
 | 
			
		||||
        return h(
 | 
			
		||||
          NTag,
 | 
			
		||||
          {
 | 
			
		||||
            style: {
 | 
			
		||||
              marginRight: '6px',
 | 
			
		||||
            },
 | 
			
		||||
            type: 'default',
 | 
			
		||||
            bordered: false,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            default: () => row.genTemplateGroup,
 | 
			
		||||
          }
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
      width: 120,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '实体命名',
 | 
			
		||||
      key: 'varName',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,10 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <n-spin :show="loading">
 | 
			
		||||
    <n-empty v-show="dataSource.list?.length === 0" description="无数据" />
 | 
			
		||||
    <n-empty
 | 
			
		||||
      v-show="dataSource.list?.length === undefined || dataSource.list?.length === 0"
 | 
			
		||||
      description="无数据"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <n-list hoverable clickable class="list-item">
 | 
			
		||||
      <n-list-item v-for="item in dataSource.list" :key="item.id" @click="UnRead(item)">
 | 
			
		||||
        <n-thing
 | 
			
		||||
@@ -30,7 +34,7 @@
 | 
			
		||||
          </template>
 | 
			
		||||
 | 
			
		||||
          <template #footer>
 | 
			
		||||
            <span v-html="item.content"></span>
 | 
			
		||||
            <span v-html="filters(item.content)"></span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </n-thing>
 | 
			
		||||
      </n-list-item>
 | 
			
		||||
@@ -139,6 +143,10 @@
 | 
			
		||||
  onMounted(() => {
 | 
			
		||||
    loadDataSource();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  function filters(data) {
 | 
			
		||||
    return data.replace(/\n/g, '<br>');
 | 
			
		||||
  }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { h, ref } from 'vue';
 | 
			
		||||
import { NAvatar, NImage, NTag, NSwitch, NRate } from 'naive-ui';
 | 
			
		||||
import { NAvatar, NImage, NTag, NSwitch, NRate, NButton } from 'naive-ui';
 | 
			
		||||
import { cloneDeep } from 'lodash-es';
 | 
			
		||||
import { FormSchema } from '@/components/Form';
 | 
			
		||||
import { Dicts } from '@/api/dict/dict';
 | 
			
		||||
@@ -9,6 +9,8 @@ import { getFileExt } from '@/utils/urlUtils';
 | 
			
		||||
import { defRangeShortcuts, defShortcuts, formatToDate } from '@/utils/dateUtil';
 | 
			
		||||
import { format } from 'date-fns';
 | 
			
		||||
import { getOptionLabel, getOptionTag, Options, errorImg } from '@/utils/hotgo';
 | 
			
		||||
import { renderIcon, renderTooltip } from '@/utils';
 | 
			
		||||
import { HelpCircleOutline } from '@vicons/ionicons5';
 | 
			
		||||
 | 
			
		||||
export interface State {
 | 
			
		||||
  id: number;
 | 
			
		||||
@@ -99,7 +101,23 @@ export const columns = [
 | 
			
		||||
    width: 80,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '链路ID',
 | 
			
		||||
    title(_column) {
 | 
			
		||||
      return renderTooltip(
 | 
			
		||||
        h(
 | 
			
		||||
          NButton,
 | 
			
		||||
          {
 | 
			
		||||
            ghost: true,
 | 
			
		||||
            strong: true,
 | 
			
		||||
            tertiary: true,
 | 
			
		||||
            size: 'small',
 | 
			
		||||
            text: true,
 | 
			
		||||
            iconPlacement: 'right',
 | 
			
		||||
          },
 | 
			
		||||
          { default: () => '链路ID', icon: renderIcon(HelpCircleOutline) }
 | 
			
		||||
        ),
 | 
			
		||||
        'hotgo默认支持链路追踪,如果是web请求产生的日志则还可以关联对应的访问日志'
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    key: 'traceId',
 | 
			
		||||
    width: 280,
 | 
			
		||||
    render(row) {
 | 
			
		||||
 
 | 
			
		||||
@@ -117,6 +117,8 @@
 | 
			
		||||
  import { statusActions, statusOptions } from '@/enums/optionsiEnum';
 | 
			
		||||
  import { Delete, Edit, getDeptList, Status } from '@/api/org/dept';
 | 
			
		||||
  import { cloneDeep } from 'lodash-es';
 | 
			
		||||
  import { renderIcon, renderTooltip } from '@/utils';
 | 
			
		||||
  import { HelpCircleOutline } from '@vicons/ionicons5';
 | 
			
		||||
 | 
			
		||||
  const rules = {
 | 
			
		||||
    name: {
 | 
			
		||||
@@ -199,7 +201,23 @@
 | 
			
		||||
  const data = ref([]);
 | 
			
		||||
  const columns: DataTableColumns<RowData> = [
 | 
			
		||||
    {
 | 
			
		||||
      title: '部门',
 | 
			
		||||
      title(_column) {
 | 
			
		||||
        return renderTooltip(
 | 
			
		||||
          h(
 | 
			
		||||
            NButton,
 | 
			
		||||
            {
 | 
			
		||||
              ghost: true,
 | 
			
		||||
              strong: true,
 | 
			
		||||
              tertiary: true,
 | 
			
		||||
              size: 'small',
 | 
			
		||||
              text: true,
 | 
			
		||||
              iconPlacement: 'right',
 | 
			
		||||
            },
 | 
			
		||||
            { default: () => '部门', icon: renderIcon(HelpCircleOutline) }
 | 
			
		||||
          ),
 | 
			
		||||
          '支持上下级部门,点击列表中左侧 > 按钮可展开下级部门列表'
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
      key: 'name',
 | 
			
		||||
      render(row) {
 | 
			
		||||
        return h(
 | 
			
		||||
 
 | 
			
		||||
@@ -290,7 +290,6 @@
 | 
			
		||||
      negativeText: '取消',
 | 
			
		||||
      onPositiveClick: () => {
 | 
			
		||||
        Delete({ id: checkedIds.value }).then((_res) => {
 | 
			
		||||
          console.log('_res:' + JSON.stringify(_res));
 | 
			
		||||
          message.success('操作成功');
 | 
			
		||||
          reloadTable();
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,30 @@
 | 
			
		||||
import { h } from 'vue';
 | 
			
		||||
import { NTag } from 'naive-ui';
 | 
			
		||||
 | 
			
		||||
import { NTag, NButton } from 'naive-ui';
 | 
			
		||||
import { HelpCircleOutline } from '@vicons/ionicons5';
 | 
			
		||||
import { renderTooltip, renderIcon } from '@/utils';
 | 
			
		||||
export const columns = [
 | 
			
		||||
  // {
 | 
			
		||||
  //   title: '角色ID',
 | 
			
		||||
  //   key: 'id',
 | 
			
		||||
  // },
 | 
			
		||||
  {
 | 
			
		||||
    title: '角色',
 | 
			
		||||
    title(_column) {
 | 
			
		||||
      return renderTooltip(
 | 
			
		||||
        h(
 | 
			
		||||
          NButton,
 | 
			
		||||
          {
 | 
			
		||||
            ghost: true,
 | 
			
		||||
            strong: true,
 | 
			
		||||
            tertiary: true,
 | 
			
		||||
            size: 'small',
 | 
			
		||||
            text: true,
 | 
			
		||||
            iconPlacement: 'right',
 | 
			
		||||
          },
 | 
			
		||||
          { default: () => '角色', icon: renderIcon(HelpCircleOutline) }
 | 
			
		||||
        ),
 | 
			
		||||
        '支持上下级角色,点击列表中左侧 > 按钮可展开下级角色列表'
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    key: 'name',
 | 
			
		||||
    render(row) {
 | 
			
		||||
      return h(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,133 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <n-grid cols="2 s:2 m:2 l:3 xl:3 2xl:3" responsive="screen">
 | 
			
		||||
    <n-grid-item>
 | 
			
		||||
      <n-form :label-width="80" :model="formValue" :rules="rules" ref="formRef">
 | 
			
		||||
        <n-form-item label="网站名称" path="name">
 | 
			
		||||
          <n-input v-model:value="formValue.name" placeholder="请输入网站名称" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="备案编号" path="icpCode">
 | 
			
		||||
          <n-input placeholder="请输入备案编号" v-model:value="formValue.icpCode" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="联系电话" path="mobile">
 | 
			
		||||
          <n-input placeholder="请输入联系电话" v-model:value="formValue.mobile" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="联系地址" path="address">
 | 
			
		||||
          <n-input v-model:value="formValue.address" type="textarea" placeholder="请输入联系地址" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="登录验证码" path="loginCode">
 | 
			
		||||
          <n-radio-group v-model:value="formValue.loginCode" name="loginCode">
 | 
			
		||||
            <n-space>
 | 
			
		||||
              <n-radio :value="1">开启</n-radio>
 | 
			
		||||
              <n-radio :value="0">关闭</n-radio>
 | 
			
		||||
            </n-space>
 | 
			
		||||
          </n-radio-group>
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="网站开启访问" path="systemOpen">
 | 
			
		||||
          <n-switch
 | 
			
		||||
            size="large"
 | 
			
		||||
            v-model:value="formValue.systemOpen"
 | 
			
		||||
            @update:value="systemOpenChange"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="网站关闭提示" path="closeText">
 | 
			
		||||
          <n-input
 | 
			
		||||
            v-model:value="formValue.closeText"
 | 
			
		||||
            type="textarea"
 | 
			
		||||
            placeholder="请输入网站关闭提示"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <n-space>
 | 
			
		||||
            <n-button type="primary" @click="formSubmit">更新基本信息</n-button>
 | 
			
		||||
          </n-space>
 | 
			
		||||
        </div>
 | 
			
		||||
      </n-form>
 | 
			
		||||
    </n-grid-item>
 | 
			
		||||
  </n-grid>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import { defineComponent, reactive, ref, toRefs } from 'vue';
 | 
			
		||||
  import { useDialog, useMessage } from 'naive-ui';
 | 
			
		||||
 | 
			
		||||
  const rules = {
 | 
			
		||||
    name: {
 | 
			
		||||
      required: true,
 | 
			
		||||
      message: '请输入网站名称',
 | 
			
		||||
      trigger: 'blur',
 | 
			
		||||
    },
 | 
			
		||||
    mobile: {
 | 
			
		||||
      required: true,
 | 
			
		||||
      message: '请输入联系电话',
 | 
			
		||||
      trigger: 'input',
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  export default defineComponent({
 | 
			
		||||
    setup() {
 | 
			
		||||
      const formRef: any = ref(null);
 | 
			
		||||
      const message = useMessage();
 | 
			
		||||
      const dialog = useDialog();
 | 
			
		||||
 | 
			
		||||
      const state = reactive({
 | 
			
		||||
        formValue: {
 | 
			
		||||
          name: '',
 | 
			
		||||
          mobile: '',
 | 
			
		||||
          icpCode: '',
 | 
			
		||||
          address: '',
 | 
			
		||||
          loginCode: 0,
 | 
			
		||||
          closeText:
 | 
			
		||||
            '网站维护中,暂时无法访问!本网站正在进行系统维护和技术升级,网站暂时无法访问,敬请谅解!',
 | 
			
		||||
          systemOpen: true,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      function systemOpenChange(value) {
 | 
			
		||||
        if (!value) {
 | 
			
		||||
          dialog.warning({
 | 
			
		||||
            title: '提示',
 | 
			
		||||
            content: '您确定要关闭系统访问吗?该操作立马生效,请慎重操作!',
 | 
			
		||||
            positiveText: '确定',
 | 
			
		||||
            negativeText: '取消',
 | 
			
		||||
            onPositiveClick: () => {
 | 
			
		||||
              message.success('操作成功');
 | 
			
		||||
            },
 | 
			
		||||
            onNegativeClick: () => {
 | 
			
		||||
              state.formValue.systemOpen = true;
 | 
			
		||||
            },
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function formSubmit() {
 | 
			
		||||
        formRef.value.validate((errors) => {
 | 
			
		||||
          if (!errors) {
 | 
			
		||||
            message.success('验证成功');
 | 
			
		||||
          } else {
 | 
			
		||||
            message.error('验证失败,请填写完整信息');
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function resetForm() {
 | 
			
		||||
        formRef.value.restoreValidation();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        formRef,
 | 
			
		||||
        ...toRefs(state),
 | 
			
		||||
        rules,
 | 
			
		||||
        formSubmit,
 | 
			
		||||
        resetForm,
 | 
			
		||||
        systemOpenChange,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,79 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <n-grid cols="2 s:2 m:2 l:3 xl:3 2xl:3" responsive="screen">
 | 
			
		||||
    <n-grid-item>
 | 
			
		||||
      <n-form :label-width="120" :model="formValue" :rules="rules" ref="formRef">
 | 
			
		||||
        <n-form-item label="发件人邮箱" path="originator">
 | 
			
		||||
          <n-input v-model:value="formValue.originator" placeholder="请输入发件人邮箱" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="SMTP服务器地址">
 | 
			
		||||
          <n-input placeholder="请输入SMTP服务器地址" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="SMTP服务器端口">
 | 
			
		||||
          <n-input placeholder="请输入SMTP服务器端口" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="SMTP用户名">
 | 
			
		||||
          <n-input placeholder="请输入SMTP用户名" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="SMTP密码">
 | 
			
		||||
          <n-input type="password" placeholder="请输入SMTP密码" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="邮件测试">
 | 
			
		||||
          <n-button>邮件测试</n-button>
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <n-space>
 | 
			
		||||
            <n-button type="primary" @click="formSubmit">更新邮件信息</n-button>
 | 
			
		||||
          </n-space>
 | 
			
		||||
        </div>
 | 
			
		||||
      </n-form>
 | 
			
		||||
    </n-grid-item>
 | 
			
		||||
  </n-grid>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import { defineComponent, reactive, ref, toRefs } from 'vue';
 | 
			
		||||
  import { useMessage } from 'naive-ui';
 | 
			
		||||
 | 
			
		||||
  const rules = {
 | 
			
		||||
    originator: {
 | 
			
		||||
      required: true,
 | 
			
		||||
      message: '请输入发件人邮箱',
 | 
			
		||||
      trigger: 'blur',
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  export default defineComponent({
 | 
			
		||||
    setup() {
 | 
			
		||||
      const formRef: any = ref(null);
 | 
			
		||||
      const message = useMessage();
 | 
			
		||||
 | 
			
		||||
      const state = reactive({
 | 
			
		||||
        formValue: {
 | 
			
		||||
          originator: '',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      function formSubmit() {
 | 
			
		||||
        formRef.value.validate((errors) => {
 | 
			
		||||
          if (!errors) {
 | 
			
		||||
            message.success('验证成功');
 | 
			
		||||
          } else {
 | 
			
		||||
            message.error('验证失败,请填写完整信息');
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        formRef,
 | 
			
		||||
        ...toRefs(state),
 | 
			
		||||
        rules,
 | 
			
		||||
        formSubmit,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,198 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <n-grid cols="2 s:2 m:2 l:3 xl:3 2xl:3" responsive="screen">
 | 
			
		||||
    <n-grid-item>
 | 
			
		||||
      <n-form :label-width="120" :model="formValue" :rules="rules" ref="formRef">
 | 
			
		||||
        <n-form-item label="商品图片(大)">
 | 
			
		||||
          <n-space align="center">
 | 
			
		||||
            <span>宽度:</span>
 | 
			
		||||
            <n-input
 | 
			
		||||
              v-model:value="formValue.bigWidth"
 | 
			
		||||
              style="width: 80px"
 | 
			
		||||
              placeholder="宽度像素"
 | 
			
		||||
            />
 | 
			
		||||
            <span>高度:</span>
 | 
			
		||||
            <n-input
 | 
			
		||||
              v-model:value="formValue.bigHeight"
 | 
			
		||||
              style="width: 80px"
 | 
			
		||||
              placeholder="高度像素"
 | 
			
		||||
            />
 | 
			
		||||
          </n-space>
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="商品图片(小)">
 | 
			
		||||
          <n-space align="center">
 | 
			
		||||
            <span>宽度:</span>
 | 
			
		||||
            <n-input
 | 
			
		||||
              v-model:value="formValue.smallWidth"
 | 
			
		||||
              style="width: 80px"
 | 
			
		||||
              placeholder="宽度像素"
 | 
			
		||||
            />
 | 
			
		||||
            <span>高度:</span>
 | 
			
		||||
            <n-input
 | 
			
		||||
              v-model:value="formValue.smallHeight"
 | 
			
		||||
              style="width: 80px"
 | 
			
		||||
              placeholder="高度像素"
 | 
			
		||||
            />
 | 
			
		||||
          </n-space>
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="水印透明度" path="watermarkClarity">
 | 
			
		||||
          <n-input-number
 | 
			
		||||
            v-model:value="formValue.watermarkClarity"
 | 
			
		||||
            :show-button="false"
 | 
			
		||||
            placeholder="请输入水印透明度"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="水印图片" path="watermarkClarity">
 | 
			
		||||
          <n-upload action="http://www.mocky.io/v2/5e4bafc63100007100d8b70f">
 | 
			
		||||
            <n-button>上传文件</n-button>
 | 
			
		||||
          </n-upload>
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="水印位置" path="watermarkPlace">
 | 
			
		||||
          <n-select
 | 
			
		||||
            placeholder="请选择价格精确方式"
 | 
			
		||||
            :options="watermarkPlaceList"
 | 
			
		||||
            v-model:value="formValue.watermarkPlace"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="价格精确位数" path="pricePreciseNum">
 | 
			
		||||
          <n-select
 | 
			
		||||
            placeholder="请选择价格精确位数"
 | 
			
		||||
            :options="pricePreciseNumList"
 | 
			
		||||
            v-model:value="formValue.pricePreciseNum"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="价格精确方式" path="pricePrecise">
 | 
			
		||||
          <n-select
 | 
			
		||||
            placeholder="请选择价格精确方式"
 | 
			
		||||
            :options="pricePreciseList"
 | 
			
		||||
            v-model:value="formValue.pricePrecise"
 | 
			
		||||
          />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <n-form-item label="前台显示市场价" path="isMarketPrice">
 | 
			
		||||
          <n-switch size="large" v-model:value="formValue.isMarketPrice" />
 | 
			
		||||
        </n-form-item>
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <n-space>
 | 
			
		||||
            <n-button type="primary" @click="formSubmit">更新显示信息</n-button>
 | 
			
		||||
          </n-space>
 | 
			
		||||
        </div>
 | 
			
		||||
      </n-form>
 | 
			
		||||
    </n-grid-item>
 | 
			
		||||
  </n-grid>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import { defineComponent, reactive, ref, toRefs } from 'vue';
 | 
			
		||||
  import { useMessage } from 'naive-ui';
 | 
			
		||||
 | 
			
		||||
  const rules = {
 | 
			
		||||
    name: {
 | 
			
		||||
      required: true,
 | 
			
		||||
      message: '请输入网站名称',
 | 
			
		||||
      trigger: 'blur',
 | 
			
		||||
    },
 | 
			
		||||
    mobile: {
 | 
			
		||||
      required: true,
 | 
			
		||||
      message: '请输入联系电话',
 | 
			
		||||
      trigger: 'input',
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  const watermarkPlaceList = [
 | 
			
		||||
    {
 | 
			
		||||
      label: '左上',
 | 
			
		||||
      value: 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '右上',
 | 
			
		||||
      value: 2,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '居中',
 | 
			
		||||
      value: 3,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '右下',
 | 
			
		||||
      value: 4,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  const pricePreciseNumList = [
 | 
			
		||||
    {
 | 
			
		||||
      label: '2位',
 | 
			
		||||
      value: 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '3位',
 | 
			
		||||
      value: 2,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '4位',
 | 
			
		||||
      value: 3,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
  const pricePreciseList = [
 | 
			
		||||
    {
 | 
			
		||||
      label: '四舍五入',
 | 
			
		||||
      value: 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '向上取整',
 | 
			
		||||
      value: 2,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: '向下取整',
 | 
			
		||||
      value: 3,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  export default defineComponent({
 | 
			
		||||
    setup() {
 | 
			
		||||
      const formRef: any = ref(null);
 | 
			
		||||
      const message = useMessage();
 | 
			
		||||
      const state = reactive({
 | 
			
		||||
        formValue: {
 | 
			
		||||
          bigWidth: '',
 | 
			
		||||
          bigHeight: '',
 | 
			
		||||
          smallWidth: '',
 | 
			
		||||
          smallHeight: '',
 | 
			
		||||
          watermarkClarity: null,
 | 
			
		||||
          pricePrecise: 1,
 | 
			
		||||
          isMarketPrice: true,
 | 
			
		||||
          pricePreciseNum: null,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      function formSubmit() {
 | 
			
		||||
        formRef.value.validate((errors) => {
 | 
			
		||||
          if (!errors) {
 | 
			
		||||
            message.success('验证成功');
 | 
			
		||||
          } else {
 | 
			
		||||
            message.error('验证失败,请填写完整信息');
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function resetForm() {
 | 
			
		||||
        formRef.value.restoreValidation();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        formRef,
 | 
			
		||||
        ...toRefs(state),
 | 
			
		||||
        pricePreciseList,
 | 
			
		||||
        watermarkPlaceList,
 | 
			
		||||
        pricePreciseNumList,
 | 
			
		||||
        rules,
 | 
			
		||||
        formSubmit,
 | 
			
		||||
        resetForm,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <n-grid :x-gap="24">
 | 
			
		||||
      <n-grid-item span="6">
 | 
			
		||||
        <n-card :bordered="false" size="small" class="proCard">
 | 
			
		||||
          <n-thing
 | 
			
		||||
            class="thing-cell"
 | 
			
		||||
            v-for="item in typeTabList"
 | 
			
		||||
            :key="item.key"
 | 
			
		||||
            :class="{ 'thing-cell-on': type === item.key }"
 | 
			
		||||
            @click="switchType(item)"
 | 
			
		||||
          >
 | 
			
		||||
            <template #header>{{ item.name }}</template>
 | 
			
		||||
            <template #description>{{ item.desc }}</template>
 | 
			
		||||
          </n-thing>
 | 
			
		||||
        </n-card>
 | 
			
		||||
      </n-grid-item>
 | 
			
		||||
      <n-grid-item span="18">
 | 
			
		||||
        <n-card :bordered="false" size="small" :title="typeTitle" class="proCard">
 | 
			
		||||
          <BasicSetting v-if="type === 1" />
 | 
			
		||||
          <RevealSetting v-if="type === 2" />
 | 
			
		||||
          <EmailSetting v-if="type === 3" />
 | 
			
		||||
        </n-card>
 | 
			
		||||
      </n-grid-item>
 | 
			
		||||
    </n-grid>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import { defineComponent, reactive, toRefs } from 'vue';
 | 
			
		||||
  import BasicSetting from './BasicSetting.vue';
 | 
			
		||||
  import RevealSetting from './RevealSetting.vue';
 | 
			
		||||
  import EmailSetting from './EmailSetting.vue';
 | 
			
		||||
 | 
			
		||||
  const typeTabList = [
 | 
			
		||||
    {
 | 
			
		||||
      name: '基本设置',
 | 
			
		||||
      desc: '系统常规设置',
 | 
			
		||||
      key: 1,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: '显示设置',
 | 
			
		||||
      desc: '系统显示设置',
 | 
			
		||||
      key: 2,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: '邮件设置',
 | 
			
		||||
      desc: '系统邮件设置',
 | 
			
		||||
      key: 3,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
  export default defineComponent({
 | 
			
		||||
    components: { BasicSetting, RevealSetting, EmailSetting },
 | 
			
		||||
    setup() {
 | 
			
		||||
      const state = reactive({
 | 
			
		||||
        type: 1,
 | 
			
		||||
        typeTitle: '基本设置',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      function switchType(e) {
 | 
			
		||||
        state.type = e.key;
 | 
			
		||||
        state.typeTitle = e.name;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        ...toRefs(state),
 | 
			
		||||
        switchType,
 | 
			
		||||
        typeTabList,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
  .thing-cell {
 | 
			
		||||
    margin: 0 -16px 10px;
 | 
			
		||||
    padding: 5px 16px;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background: #f3f3f3;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .thing-cell-on {
 | 
			
		||||
    background: #f0faff;
 | 
			
		||||
    color: #2d8cf0;
 | 
			
		||||
 | 
			
		||||
    ::v-deep(.n-thing-main .n-thing-header .n-thing-header__title) {
 | 
			
		||||
      color: #2d8cf0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background: #f0faff;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -157,17 +157,10 @@
 | 
			
		||||
  function formSubmit() {
 | 
			
		||||
    formRef.value.validate((errors) => {
 | 
			
		||||
      if (!errors) {
 | 
			
		||||
        console.log('formValue.value:' + JSON.stringify(formValue.value));
 | 
			
		||||
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value })
 | 
			
		||||
          .then((res) => {
 | 
			
		||||
            console.log('res:' + JSON.stringify(res));
 | 
			
		||||
            message.success('更新成功');
 | 
			
		||||
            load();
 | 
			
		||||
          })
 | 
			
		||||
          .catch((error) => {
 | 
			
		||||
            message.error(error.toString());
 | 
			
		||||
          });
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
 | 
			
		||||
          message.success('更新成功');
 | 
			
		||||
          load();
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('验证失败,请填写完整信息');
 | 
			
		||||
      }
 | 
			
		||||
@@ -192,14 +185,10 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          // state.formValue.watermarkClarity = res;
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
          console.log('res:' + JSON.stringify(res));
 | 
			
		||||
        })
 | 
			
		||||
        .catch((error) => {
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          message.error(error.toString());
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,19 @@
 | 
			
		||||
            </n-form-item>
 | 
			
		||||
 | 
			
		||||
            <n-form-item label="SMTP密码" path="smtpPass">
 | 
			
		||||
              <n-input v-model:value="formValue.smtpPass" placeholder="" type="password" />
 | 
			
		||||
              <n-input
 | 
			
		||||
                v-model:value="formValue.smtpPass"
 | 
			
		||||
                placeholder=""
 | 
			
		||||
                type="password"
 | 
			
		||||
                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>填写您的密码</template>
 | 
			
		||||
            </n-form-item>
 | 
			
		||||
 | 
			
		||||
@@ -120,6 +132,7 @@
 | 
			
		||||
  import { onMounted, ref } from 'vue';
 | 
			
		||||
  import { useMessage } from 'naive-ui';
 | 
			
		||||
  import { getConfig, sendTestEmail, updateConfig } from '@/api/sys/config';
 | 
			
		||||
  import { GlassesOutline, Glasses } from '@vicons/ionicons5';
 | 
			
		||||
 | 
			
		||||
  const group = ref('smtp');
 | 
			
		||||
  const show = ref(false);
 | 
			
		||||
@@ -194,7 +207,6 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          res.list.smtpTemplate = JSON.parse(res.list.smtpTemplate);
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,19 @@
 | 
			
		||||
        <n-grid-item>
 | 
			
		||||
          <n-form :label-width="100" :model="formValue" :rules="rules" ref="formRef">
 | 
			
		||||
            <n-form-item label="高德Web服务key" path="geoAmapWebKey">
 | 
			
		||||
              <n-input v-model:value="formValue.geoAmapWebKey" placeholder="" type="password" />
 | 
			
		||||
              <n-input
 | 
			
		||||
                v-model:value="formValue.geoAmapWebKey"
 | 
			
		||||
                placeholder=""
 | 
			
		||||
                type="password"
 | 
			
		||||
                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.amap.com/dev/key/app</template>
 | 
			
		||||
            </n-form-item>
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +37,7 @@
 | 
			
		||||
  import { ref, onMounted } from 'vue';
 | 
			
		||||
  import { useMessage } from 'naive-ui';
 | 
			
		||||
  import { getConfig, updateConfig } from '@/api/sys/config';
 | 
			
		||||
  import { GlassesOutline, Glasses } from '@vicons/ionicons5';
 | 
			
		||||
 | 
			
		||||
  const group = ref('geo');
 | 
			
		||||
  const show = ref(false);
 | 
			
		||||
@@ -47,17 +60,10 @@
 | 
			
		||||
  function formSubmit() {
 | 
			
		||||
    formRef.value.validate((errors) => {
 | 
			
		||||
      if (!errors) {
 | 
			
		||||
        console.log('formValue.value:' + JSON.stringify(formValue.value));
 | 
			
		||||
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value })
 | 
			
		||||
          .then((res) => {
 | 
			
		||||
            console.log('res:' + JSON.stringify(res));
 | 
			
		||||
            message.success('更新成功');
 | 
			
		||||
            load();
 | 
			
		||||
          })
 | 
			
		||||
          .catch((error) => {
 | 
			
		||||
            message.error(error.toString());
 | 
			
		||||
          });
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
 | 
			
		||||
          message.success('更新成功');
 | 
			
		||||
          load();
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('验证失败,请填写完整信息');
 | 
			
		||||
      }
 | 
			
		||||
@@ -73,14 +79,10 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          // state.formValue.watermarkClarity = res;
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
          console.log('res:' + JSON.stringify(res));
 | 
			
		||||
        })
 | 
			
		||||
        .catch((error) => {
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          message.error(error.toString());
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -179,10 +179,6 @@
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function resetForm() {
 | 
			
		||||
        formRef.value.restoreValidation();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        formRef,
 | 
			
		||||
        ...toRefs(state),
 | 
			
		||||
@@ -191,7 +187,6 @@
 | 
			
		||||
        pricePreciseNumList,
 | 
			
		||||
        rules,
 | 
			
		||||
        formSubmit,
 | 
			
		||||
        resetForm,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 
 | 
			
		||||
@@ -184,15 +184,10 @@
 | 
			
		||||
  function formSubmit() {
 | 
			
		||||
    formRef.value.validate((errors) => {
 | 
			
		||||
      if (!errors) {
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value })
 | 
			
		||||
          .then((res) => {
 | 
			
		||||
            console.log('res:' + JSON.stringify(res));
 | 
			
		||||
            message.success('更新成功');
 | 
			
		||||
            load();
 | 
			
		||||
          })
 | 
			
		||||
          .catch((error) => {
 | 
			
		||||
            message.error(error.toString());
 | 
			
		||||
          });
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
 | 
			
		||||
          message.success('更新成功');
 | 
			
		||||
          load();
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('验证失败,请填写完整信息');
 | 
			
		||||
      }
 | 
			
		||||
@@ -209,13 +204,11 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          res.list.smsAliyunTemplate = JSON.parse(res.list.smsAliyunTemplate);
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
        })
 | 
			
		||||
        .catch((error) => {
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          message.error(error.toString());
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -58,17 +58,10 @@
 | 
			
		||||
  function formSubmit() {
 | 
			
		||||
    formRef.value.validate((errors) => {
 | 
			
		||||
      if (!errors) {
 | 
			
		||||
        console.log('formValue.value:' + JSON.stringify(formValue.value));
 | 
			
		||||
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value })
 | 
			
		||||
          .then((res) => {
 | 
			
		||||
            console.log('res:' + JSON.stringify(res));
 | 
			
		||||
            message.success('更新成功');
 | 
			
		||||
            load();
 | 
			
		||||
          })
 | 
			
		||||
          .catch((error) => {
 | 
			
		||||
            message.error(error.toString());
 | 
			
		||||
          });
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
 | 
			
		||||
          message.success('更新成功');
 | 
			
		||||
          load();
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        message.error('验证失败,请填写完整信息');
 | 
			
		||||
      }
 | 
			
		||||
@@ -84,14 +77,10 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          // state.formValue.watermarkClarity = res;
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
          console.log('res:' + JSON.stringify(res));
 | 
			
		||||
        })
 | 
			
		||||
        .catch((error) => {
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          message.error(error.toString());
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
                placeholder="请输入"
 | 
			
		||||
                v-model:value="formValue.uploadImageSize"
 | 
			
		||||
              >
 | 
			
		||||
                <template #suffix> MB </template>
 | 
			
		||||
                <template #suffix> MB</template>
 | 
			
		||||
              </n-input-number>
 | 
			
		||||
            </n-form-item>
 | 
			
		||||
            <n-form-item label="图片类型限制" path="uploadImageType">
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
                placeholder="请输入"
 | 
			
		||||
                v-model:value="formValue.uploadFileSize"
 | 
			
		||||
              >
 | 
			
		||||
                <template #suffix> MB </template>
 | 
			
		||||
                <template #suffix> MB</template>
 | 
			
		||||
              </n-input-number>
 | 
			
		||||
            </n-form-item>
 | 
			
		||||
            <n-form-item label="文件类型限制" path="uploadFileType">
 | 
			
		||||
@@ -48,19 +48,33 @@
 | 
			
		||||
            <n-divider title-placement="left">UCloud存储</n-divider>
 | 
			
		||||
            <n-form-item label="公钥" path="uploadUCloudPublicKey">
 | 
			
		||||
              <n-input
 | 
			
		||||
                v-model:value="formValue.uploadUCloudPublicKey"
 | 
			
		||||
                placeholder=""
 | 
			
		||||
                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
 | 
			
		||||
                v-model:value="formValue.uploadUCloudPrivateKey"
 | 
			
		||||
                placeholder=""
 | 
			
		||||
                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="" />
 | 
			
		||||
@@ -94,9 +108,10 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
  import { ref, onMounted } from 'vue';
 | 
			
		||||
  import { onMounted, ref } from 'vue';
 | 
			
		||||
  import { useMessage } from 'naive-ui';
 | 
			
		||||
  import { getConfig, updateConfig } from '@/api/sys/config';
 | 
			
		||||
  import { Glasses, GlassesOutline } from '@vicons/ionicons5';
 | 
			
		||||
 | 
			
		||||
  const group = ref('upload');
 | 
			
		||||
  const show = ref(false);
 | 
			
		||||
@@ -142,10 +157,7 @@
 | 
			
		||||
  function formSubmit() {
 | 
			
		||||
    formRef.value.validate((errors) => {
 | 
			
		||||
      if (!errors) {
 | 
			
		||||
        console.log('formValue.value:' + JSON.stringify(formValue.value));
 | 
			
		||||
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((res) => {
 | 
			
		||||
          console.log('res:' + JSON.stringify(res));
 | 
			
		||||
        updateConfig({ group: group.value, list: formValue.value }).then((_res) => {
 | 
			
		||||
          message.success('更新成功');
 | 
			
		||||
          load();
 | 
			
		||||
        });
 | 
			
		||||
@@ -164,13 +176,10 @@
 | 
			
		||||
    new Promise((_resolve, _reject) => {
 | 
			
		||||
      getConfig({ group: group.value })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          formValue.value = res.list;
 | 
			
		||||
          console.log('res:' + JSON.stringify(res));
 | 
			
		||||
        })
 | 
			
		||||
        .catch((error) => {
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          show.value = false;
 | 
			
		||||
          message.error(error.toString());
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -420,7 +420,6 @@ export const columns = [
 | 
			
		||||
        checked: '开启',
 | 
			
		||||
        unchecked: '关闭',
 | 
			
		||||
        onUpdateValue: function (e) {
 | 
			
		||||
          console.log('onUpdateValue e:' + JSON.stringify(e));
 | 
			
		||||
          row.switch = e ? 1 : 2;
 | 
			
		||||
          Switch({ id: row.id, key: 'switch', value: row.switch }).then((_res) => {
 | 
			
		||||
            $message.success('操作成功');
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user