backend增加租户简称登录
This commit is contained in:
@@ -15,6 +15,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-toolbar">
|
||||
<el-switch
|
||||
v-model="pinned"
|
||||
inline-prompt
|
||||
active-text="置顶"
|
||||
inactive-text="置顶"
|
||||
:disabled="loading"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="editor-body">
|
||||
<UmoEditor v-model="noteContent" />
|
||||
</div>
|
||||
@@ -38,6 +48,7 @@ const emit = defineEmits(['save-success', 'create-success']);
|
||||
|
||||
const noteTitle = ref('');
|
||||
const noteContent = ref('');
|
||||
const pinned = ref(false);
|
||||
const loading = ref(false);
|
||||
const isNew = ref(false);
|
||||
|
||||
@@ -47,6 +58,7 @@ const loadNote = async () => {
|
||||
isNew.value = true;
|
||||
noteTitle.value = '新建笔记';
|
||||
noteContent.value = '';
|
||||
pinned.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,6 +70,7 @@ const loadNote = async () => {
|
||||
if (response.code === 200) {
|
||||
noteTitle.value = response.data.title || '无标题';
|
||||
noteContent.value = response.data.content || '';
|
||||
pinned.value = Number(response.data.pinned) === 1;
|
||||
} else {
|
||||
ElMessage.error('加载笔记失败');
|
||||
}
|
||||
@@ -84,6 +97,7 @@ const handleSave = async () => {
|
||||
const response = await createNotebook({
|
||||
title: noteTitle.value,
|
||||
content: noteContent.value,
|
||||
pinned: pinned.value ? 1 : 0,
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
@@ -98,6 +112,7 @@ const handleSave = async () => {
|
||||
const response = await updateNotebook(props.noteId, {
|
||||
title: noteTitle.value,
|
||||
content: noteContent.value,
|
||||
pinned: pinned.value ? 1 : 0,
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
@@ -175,6 +190,15 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
min-height: 42px;
|
||||
padding: 8px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.editor-body {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
>
|
||||
<div class="note-item-header">
|
||||
<span class="note-title">{{ note.title || '无标题' }}</span>
|
||||
<el-tag
|
||||
v-if="Number(note.pinned) === 1"
|
||||
class="pinned-tag"
|
||||
size="small"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
>
|
||||
置顶
|
||||
</el-tag>
|
||||
<el-dropdown trigger="click" @command="(cmd) => handleNoteAction(cmd, note)">
|
||||
<el-icon class="note-more"><MoreFilled /></el-icon>
|
||||
<template #dropdown>
|
||||
@@ -305,6 +314,7 @@ onMounted(() => {
|
||||
|
||||
.note-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
@@ -313,6 +323,11 @@ onMounted(() => {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.pinned-tag {
|
||||
flex-shrink: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.note-more {
|
||||
margin-left: 8px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
@@ -78,7 +78,7 @@ func (c *BackendNotebookController) List() {
|
||||
total, _ := qs.Count()
|
||||
|
||||
var list []models.BackendNotebook
|
||||
_, err = qs.OrderBy("-update_time", "-create_time").
|
||||
_, err = qs.OrderBy("-pinned", "-id").
|
||||
Limit(pageSize).Offset((page - 1) * pageSize).
|
||||
All(&list)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
@@ -137,6 +137,7 @@ func (c *BackendNotebookController) Create() {
|
||||
var payload struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Pinned int8 `json:"pinned"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
c.nbJsonErr(400, 400, "参数错误")
|
||||
@@ -153,6 +154,7 @@ func (c *BackendNotebookController) Create() {
|
||||
Tid: claims.TenantId,
|
||||
Title: payload.Title,
|
||||
Content: payload.Content,
|
||||
Pinned: payload.Pinned,
|
||||
UserID: &userID,
|
||||
UserName: &claims.Username,
|
||||
IsDeleted: 0,
|
||||
@@ -190,6 +192,7 @@ func (c *BackendNotebookController) Update() {
|
||||
var payload struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Pinned int8 `json:"pinned"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
c.nbJsonErr(400, 400, "参数错误")
|
||||
@@ -219,6 +222,7 @@ func (c *BackendNotebookController) Update() {
|
||||
Update(map[string]interface{}{
|
||||
"title": payload.Title,
|
||||
"content": payload.Content,
|
||||
"pinned": payload.Pinned,
|
||||
"update_time": now,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -228,6 +232,7 @@ func (c *BackendNotebookController) Update() {
|
||||
|
||||
note.Title = payload.Title
|
||||
note.Content = payload.Content
|
||||
note.Pinned = payload.Pinned
|
||||
note.UpdateTime = &now
|
||||
c.nbOk(note)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func (c *PlatformNotebookController) List() {
|
||||
}
|
||||
|
||||
var list []models.PlatformNotebook
|
||||
_, err = qs.OrderBy("-update_time", "-create_time").
|
||||
_, err = qs.OrderBy("-pinned", "-id").
|
||||
Limit(pageSize).
|
||||
Offset((page - 1) * pageSize).
|
||||
All(&list)
|
||||
@@ -158,6 +158,7 @@ func (c *PlatformNotebookController) Create() {
|
||||
var payload struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Pinned int8 `json:"pinned"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
@@ -174,6 +175,7 @@ func (c *PlatformNotebookController) Create() {
|
||||
note := &models.PlatformNotebook{
|
||||
Title: payload.Title,
|
||||
Content: payload.Content,
|
||||
Pinned: payload.Pinned,
|
||||
UserID: &userID,
|
||||
UserName: &claims.Username,
|
||||
IsDeleted: 0,
|
||||
@@ -213,6 +215,7 @@ func (c *PlatformNotebookController) Update() {
|
||||
var payload struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Pinned int8 `json:"pinned"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
@@ -248,6 +251,7 @@ func (c *PlatformNotebookController) Update() {
|
||||
Update(map[string]interface{}{
|
||||
"title": payload.Title,
|
||||
"content": payload.Content,
|
||||
"pinned": payload.Pinned,
|
||||
"update_time": now,
|
||||
})
|
||||
|
||||
@@ -258,6 +262,7 @@ func (c *PlatformNotebookController) Update() {
|
||||
|
||||
note.Title = payload.Title
|
||||
note.Content = payload.Content
|
||||
note.Pinned = payload.Pinned
|
||||
note.UpdateTime = &now
|
||||
|
||||
jsonResponse(&c.Controller, 200, 200, "更新成功", note)
|
||||
|
||||
@@ -7,6 +7,7 @@ type PlatformNotebook struct {
|
||||
ID uint64 `orm:"column(id);pk;auto" json:"id"`
|
||||
Title string `orm:"column(title);size(255)" json:"title"`
|
||||
Content string `orm:"column(content);type(longtext);null" json:"content"`
|
||||
Pinned int8 `orm:"column(pinned);default(0)" json:"pinned"`
|
||||
UserID *uint64 `orm:"column(user_id);null" json:"user_id"`
|
||||
UserName *string `orm:"column(user_name);size(100);null" json:"user_name"`
|
||||
IsDeleted int8 `orm:"column(is_deleted);default(0)" json:"is_deleted"`
|
||||
|
||||
+14
-13
@@ -3,19 +3,20 @@ package models
|
||||
import "time"
|
||||
|
||||
type SystemTenant struct {
|
||||
ID uint64 `orm:"column(id);pk;auto" json:"id"`
|
||||
TenantCode string `orm:"column(tenant_code);size(32)" json:"tenant_code"`
|
||||
TenantName string `orm:"column(tenant_name);size(128)" json:"tenant_name"`
|
||||
ContactPerson *string `orm:"column(contact_person);size(64);null" json:"contact_person"`
|
||||
ContactPhone *string `orm:"column(contact_phone);size(20);null" json:"contact_phone"`
|
||||
ContactEmail *string `orm:"column(contact_email);size(128);null" json:"contact_email"`
|
||||
Address *string `orm:"column(address);size(255);null" json:"address"`
|
||||
Worktime *string `orm:"column(worktime);size(255);null" json:"worktime"`
|
||||
Status int8 `orm:"column(status);default(1)" json:"status"`
|
||||
Remark *string `orm:"column(remark);size(512);null" json:"remark"`
|
||||
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time"`
|
||||
ID uint64 `orm:"column(id);pk;auto" json:"id"`
|
||||
TenantCode string `orm:"column(tenant_code);size(32)" json:"tenant_code"`
|
||||
TenantName string `orm:"column(tenant_name);size(128)" json:"tenant_name"`
|
||||
TenantShortName *string `orm:"column(tenant_short_name);size(128);null" json:"tenant_short_name"`
|
||||
ContactPerson *string `orm:"column(contact_person);size(64);null" json:"contact_person"`
|
||||
ContactPhone *string `orm:"column(contact_phone);size(20);null" json:"contact_phone"`
|
||||
ContactEmail *string `orm:"column(contact_email);size(128);null" json:"contact_email"`
|
||||
Address *string `orm:"column(address);size(255);null" json:"address"`
|
||||
Worktime *string `orm:"column(worktime);size(255);null" json:"worktime"`
|
||||
Status int8 `orm:"column(status);default(1)" json:"status"`
|
||||
Remark *string `orm:"column(remark);size(512);null" json:"remark"`
|
||||
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"update_time"`
|
||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time"`
|
||||
}
|
||||
|
||||
func (m *SystemTenant) TableName() string {
|
||||
|
||||
@@ -98,8 +98,8 @@ func SendBackendLoginCode(tenantName, account, channel string) error {
|
||||
return errors.New("仅支持短信或邮箱验证码")
|
||||
}
|
||||
|
||||
var tenant models.SystemTenant
|
||||
if err := models.Orm.QueryTable(new(models.SystemTenant)).Filter("tenant_name", tenantName).One(&tenant); err != nil {
|
||||
tenant, err := findTenantByLoginName(tenantName)
|
||||
if err != nil {
|
||||
return errors.New("租户不存在")
|
||||
}
|
||||
|
||||
|
||||
@@ -93,10 +93,7 @@ func BackendLogin(tenantName, account, password string) (string, *PlatformLoginU
|
||||
return "", nil, errors.New("租户名称、用户名或密码不能为空")
|
||||
}
|
||||
|
||||
var tenant models.SystemTenant
|
||||
err := models.Orm.QueryTable(new(models.SystemTenant)).
|
||||
Filter("tenant_name", tenantName).
|
||||
One(&tenant)
|
||||
tenant, err := findTenantByLoginName(tenantName)
|
||||
if err != nil {
|
||||
return "", nil, errors.New("租户不存在")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
|
||||
"server/models"
|
||||
)
|
||||
|
||||
/* findTenantByLoginName 根据租户简称、短名或编码查找租户。
|
||||
*
|
||||
* 当前表结构中 tenant_name 的业务含义就是“租户简称”,同时兼容
|
||||
* tenant_short_name 和 tenant_code 两个历史/备用登录标识。
|
||||
*/
|
||||
func findTenantByLoginName(loginName string) (*models.SystemTenant, error) {
|
||||
loginName = strings.TrimSpace(loginName)
|
||||
if loginName == "" {
|
||||
return nil, orm.ErrNoRows
|
||||
}
|
||||
|
||||
// tenant_name 的业务含义是租户简称。使用 TRIM 兼容历史数据中字段值
|
||||
// 前后存在空格的情况;参数通过 SetArgs 绑定,避免 SQL 注入。
|
||||
tenant := &models.SystemTenant{}
|
||||
query := `
|
||||
SELECT id, tenant_code, tenant_name, tenant_short_name,
|
||||
contact_person, contact_phone, contact_email, address,
|
||||
worktime, status, remark, create_time, update_time, delete_time
|
||||
FROM yz_system_tenant
|
||||
WHERE (TRIM(tenant_name) = TRIM(?) OR
|
||||
TRIM(tenant_short_name) = TRIM(?) OR
|
||||
TRIM(tenant_code) = TRIM(?))
|
||||
AND status <> 0
|
||||
ORDER BY id ASC
|
||||
LIMIT 1`
|
||||
err := models.Orm.Raw(query).
|
||||
SetArgs(loginName, loginName, loginName).
|
||||
QueryRow(tenant)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tenant, nil
|
||||
}
|
||||
@@ -15,6 +15,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-toolbar">
|
||||
<el-switch
|
||||
v-model="pinned"
|
||||
inline-prompt
|
||||
active-text="置顶"
|
||||
inactive-text="置顶"
|
||||
:disabled="loading"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="editor-body">
|
||||
<UmoEditor v-model="noteContent" />
|
||||
</div>
|
||||
@@ -38,6 +48,7 @@ const emit = defineEmits(['save-success', 'create-success']);
|
||||
|
||||
const noteTitle = ref('');
|
||||
const noteContent = ref('');
|
||||
const pinned = ref(false);
|
||||
const loading = ref(false);
|
||||
const isNew = ref(false);
|
||||
|
||||
@@ -47,6 +58,7 @@ const loadNote = async () => {
|
||||
isNew.value = true;
|
||||
noteTitle.value = '新建笔记';
|
||||
noteContent.value = '';
|
||||
pinned.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,6 +70,7 @@ const loadNote = async () => {
|
||||
if (response.code === 200) {
|
||||
noteTitle.value = response.data.title || '无标题';
|
||||
noteContent.value = response.data.content || '';
|
||||
pinned.value = Number(response.data.pinned) === 1;
|
||||
} else {
|
||||
ElMessage.error('加载笔记失败');
|
||||
}
|
||||
@@ -84,6 +97,7 @@ const handleSave = async () => {
|
||||
const response = await createNotebook({
|
||||
title: noteTitle.value,
|
||||
content: noteContent.value,
|
||||
pinned: pinned.value ? 1 : 0,
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
@@ -98,6 +112,7 @@ const handleSave = async () => {
|
||||
const response = await updateNotebook(props.noteId, {
|
||||
title: noteTitle.value,
|
||||
content: noteContent.value,
|
||||
pinned: pinned.value ? 1 : 0,
|
||||
});
|
||||
|
||||
if (response.code === 200) {
|
||||
@@ -175,6 +190,15 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
min-height: 42px;
|
||||
padding: 8px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.editor-body {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
>
|
||||
<div class="note-item-header">
|
||||
<span class="note-title">{{ note.title || '无标题' }}</span>
|
||||
<el-tag
|
||||
v-if="Number(note.pinned) === 1"
|
||||
class="pinned-tag"
|
||||
size="small"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
>
|
||||
置顶
|
||||
</el-tag>
|
||||
<el-dropdown trigger="click" @command="(cmd) => handleNoteAction(cmd, note)">
|
||||
<el-icon class="note-more"><MoreFilled /></el-icon>
|
||||
<template #dropdown>
|
||||
@@ -305,6 +314,7 @@ onMounted(() => {
|
||||
|
||||
.note-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
@@ -313,6 +323,11 @@ onMounted(() => {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.pinned-tag {
|
||||
flex-shrink: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.note-more {
|
||||
margin-left: 8px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
-- 记事本表增加置顶字段(兼容已有数据库)
|
||||
-- 已存在字段时请跳过对应 ALTER 语句。
|
||||
|
||||
ALTER TABLE `yz_platform_notebook`
|
||||
ADD COLUMN `pinned` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否置顶 0-否 1-是' AFTER `content`;
|
||||
|
||||
ALTER TABLE `yz_platform_notebook`
|
||||
ADD KEY `idx_pinned` (`pinned`);
|
||||
|
||||
ALTER TABLE `yz_backend_notebook`
|
||||
ADD COLUMN `pinned` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否置顶 0-否 1-是' AFTER `content`;
|
||||
|
||||
ALTER TABLE `yz_backend_notebook`
|
||||
ADD KEY `idx_pinned` (`pinned`);
|
||||
@@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS `yz_platform_notebook` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '笔记标题',
|
||||
`content` longtext COMMENT '笔记内容(HTML格式)',
|
||||
`pinned` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否置顶 0-否 1-是',
|
||||
`user_id` bigint(20) unsigned DEFAULT NULL COMMENT '创建用户ID',
|
||||
`user_name` varchar(100) DEFAULT NULL COMMENT '创建用户名',
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 0-否 1-是',
|
||||
@@ -11,6 +12,7 @@ CREATE TABLE IF NOT EXISTS `yz_platform_notebook` (
|
||||
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_pinned` (`pinned`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_is_deleted` (`is_deleted`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='平台记事本表';
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/controllers [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/middleware [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/models [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/pkg/jwtutil [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/pkg/tokenprobe [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers/api [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers/app [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers/backend [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers/index [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/routers/platform [setup failed]
|
||||
FAIL _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/services [setup failed]
|
||||
FAIL backend [setup failed]
|
||||
FAIL docs [setup failed]
|
||||
FAIL frontend [setup failed]
|
||||
FAIL go [setup failed]
|
||||
FAIL platform [setup failed]
|
||||
FAIL sql [setup failed]
|
||||
FAIL uniapp [setup failed]
|
||||
? _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/pkg/passwordutil [no test files]
|
||||
? _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/pkg/versionutil [no test files]
|
||||
? _/E_/Demos/DemoOwns/Go/yunzerwebsiteallinone/go/version [no test files]
|
||||
FAIL
|
||||
Reference in New Issue
Block a user