From 0c6efc4160243699975ae880b93379818fdf44ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=89=AB=E5=9C=B0=E5=83=A7?= <357099073@qq.com>
Date: Tue, 3 Nov 2026 09:00:29 +0800
Subject: [PATCH] =?UTF-8?q?wizhi=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
go/controllers/app_password_store.go | 243 +
go/routers/api/api.go | 5 +
platform/src/views/login/index.vue | 5 -
uniapp/api/passwordStore.js | 77 +
uniapp/components/NoteRichEditor.vue | 70 +-
uniapp/pages.json | 952 +-
uniapp/pages/login/login.vue | 696 +-
uniapp/pages/nav/nav.vue | 132 +-
uniapp/pages/tools/account/edit.vue | 399 +
uniapp/pages/tools/account/index.vue | 388 +
uniapp/pages/tools/schedule/reminder-edit.vue | 377 +
uniapp/pages/tools/schedule/reminder.vue | 269 +-
uniapp/pnpm-lock.yaml | 8981 +++++++++++++++++
uniapp/src/styles/rich-content.scss | 11 +-
uniapp/utils/nav.js | 2 +
uniapp/utils/table-editor.js | 14 +
16 files changed, 11810 insertions(+), 811 deletions(-)
create mode 100644 go/controllers/app_password_store.go
create mode 100644 uniapp/api/passwordStore.js
create mode 100644 uniapp/pages/tools/account/edit.vue
create mode 100644 uniapp/pages/tools/account/index.vue
create mode 100644 uniapp/pages/tools/schedule/reminder-edit.vue
create mode 100644 uniapp/pnpm-lock.yaml
diff --git a/go/controllers/app_password_store.go b/go/controllers/app_password_store.go
new file mode 100644
index 0000000..92c0a71
--- /dev/null
+++ b/go/controllers/app_password_store.go
@@ -0,0 +1,243 @@
+package controllers
+
+import (
+ "strconv"
+ "strings"
+
+ "server/middleware"
+ "server/models"
+ "server/pkg/identity"
+ "server/pkg/jwtutil"
+
+ "github.com/beego/beego/v2/client/orm"
+ "github.com/beego/beego/v2/core/logs"
+ beego "github.com/beego/beego/v2/server/web"
+)
+
+// ==================== 移动端 PasswordStore ====================
+//
+// 移动端「账号管理」(密码库)接口。与 Web 端 /backend/passwordStore 同一套数据
+// (yz_backend_password_store,一个平台下挂多个账号),按 JWT 中的 tid + user_id
+// 隔离,小程序「账号管理」页面调用。
+
+type AppPasswordStoreController struct {
+ beego.Controller
+}
+
+// 只放行移动端与租户端令牌:/api/** 仅被 uniapp 调用,平台令牌不该能打移动端接口。
+func (c *AppPasswordStoreController) appPwdClaims() (*jwtutil.Claims, error) {
+ claims, err := identity.Claims(c.Ctx.Request.Header.Get("Authorization"), identity.EndApp, identity.EndBackend)
+ if err != nil {
+ return nil, err
+ }
+ if claims.UserID <= 0 || claims.TenantId <= 0 {
+ return nil, orm.ErrNoRows
+ }
+ return claims, nil
+}
+
+// GetList GET /api/passwordStore/list?keyword=
+func (c *AppPasswordStoreController) GetList() {
+ cl, e := c.appPwdClaims()
+ if e != nil {
+ passwordReply(&c.Controller, 401, "未登录或无权限", nil)
+ return
+ }
+ qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
+ if k := strings.TrimSpace(c.GetString("keyword")); k != "" {
+ cond := orm.NewCondition().
+ Or("platform__icontains", k).
+ Or("url__icontains", k).
+ Or("accounts__icontains", k).
+ Or("remark__icontains", k)
+ qs = qs.SetCond(orm.NewCondition().And("is_deleted", 0).And("tid", cl.TenantId).And("user_id", cl.UserID).AndCond(cond))
+ }
+ var rows []models.BackendPasswordStore
+ if _, e = qs.OrderBy("-id").All(&rows); e != nil && e != orm.ErrNoRows {
+ logs.Error("[passwordStore] app list failed: %v", e)
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ }
+ res := make([]PasswordStoreItemDTO, 0, len(rows))
+ for _, row := range rows {
+ res = append(res, PasswordStoreItemDTO{
+ ID: row.ID, Tid: row.Tid, Platform: row.Platform, URL: row.URL,
+ Accounts: accountsFromJSON(row.Accounts), Remark: row.Remark,
+ UserID: row.UserID, CreateTime: row.CreateTime, UpdateTime: row.UpdateTime,
+ })
+ }
+ passwordReply(&c.Controller, 200, "success", map[string]interface{}{"list": res, "total": len(res)})
+}
+
+// GetDetail GET /api/passwordStore/detail/:id
+func (c *AppPasswordStoreController) GetDetail() {
+ cl, e := c.appPwdClaims()
+ if e != nil {
+ passwordReply(&c.Controller, 401, "未登录或无权限", nil)
+ return
+ }
+ id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
+ if e != nil {
+ passwordReply(&c.Controller, 400, "参数错误", nil)
+ return
+ }
+ var m models.BackendPasswordStore
+ e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
+ if e == orm.ErrNoRows {
+ passwordReply(&c.Controller, 404, "记录不存在", nil)
+ return
+ }
+ if e != nil {
+ logs.Error("[passwordStore] app detail failed: %v", e)
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ }
+ passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
+ ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
+ Accounts: accountsFromJSON(m.Accounts), Remark: m.Remark,
+ UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
+ })
+}
+
+// Create POST /api/passwordStore/create
+func (c *AppPasswordStoreController) Create() {
+ cl, e := c.appPwdClaims()
+ if e != nil {
+ passwordReply(&c.Controller, 401, "未登录或无权限", nil)
+ return
+ }
+ p, e := parsePassword(&c.Controller)
+ if e != nil {
+ passwordReply(&c.Controller, 400, e.Error(), nil)
+ return
+ }
+ if !validPassword(p) {
+ passwordReply(&c.Controller, 400, "请输入平台名称", nil)
+ return
+ }
+ if e := validateAccountsUnique(p.Accounts); e != nil {
+ passwordReply(&c.Controller, 400, e.Error(), nil)
+ return
+ }
+ qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
+ if existing, e := findSamePlatformRecord(qs, 0, p.Platform, p.URL); e != nil {
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ } else if existing > 0 {
+ passwordReply(&c.Controller, 400, "同平台同网址记录已存在,请勿重复添加", nil)
+ return
+ }
+ m := models.BackendPasswordStore{
+ Tid: cl.TenantId, UserID: uint64(cl.UserID),
+ Platform: p.Platform, URL: p.URL,
+ Accounts: accountsToJSON(p.Accounts), Remark: p.Remark,
+ }
+ if _, e = models.Orm.Insert(&m); e != nil {
+ logs.Error("[passwordStore] app create failed: %v", e)
+ passwordReply(&c.Controller, 500, "创建失败: "+e.Error(), nil)
+ return
+ }
+ passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
+ ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
+ Accounts: p.Accounts, Remark: m.Remark,
+ UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
+ })
+}
+
+// Update POST /api/passwordStore/update/:id
+func (c *AppPasswordStoreController) Update() {
+ cl, e := c.appPwdClaims()
+ if e != nil {
+ passwordReply(&c.Controller, 401, "未登录或无权限", nil)
+ return
+ }
+ id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
+ if e != nil {
+ passwordReply(&c.Controller, 400, "参数错误", nil)
+ return
+ }
+ p, e := parsePassword(&c.Controller)
+ if e != nil {
+ passwordReply(&c.Controller, 400, e.Error(), nil)
+ return
+ }
+ if !validPassword(p) {
+ passwordReply(&c.Controller, 400, "请输入平台名称", nil)
+ return
+ }
+ if e := validateAccountsUnique(p.Accounts); e != nil {
+ passwordReply(&c.Controller, 400, e.Error(), nil)
+ return
+ }
+ var m models.BackendPasswordStore
+ e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
+ if e == orm.ErrNoRows {
+ passwordReply(&c.Controller, 404, "记录不存在", nil)
+ return
+ }
+ if e != nil {
+ logs.Error("[passwordStore] app update query failed: %v", e)
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ }
+ qs := models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID)
+ if existing, e := findSamePlatformRecord(qs, m.ID, p.Platform, p.URL); e != nil {
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ } else if existing > 0 {
+ passwordReply(&c.Controller, 400, "同平台同网址记录已存在,请勿重复添加", nil)
+ return
+ }
+ m.Platform = p.Platform
+ m.URL = p.URL
+ m.Remark = p.Remark
+ m.Accounts = accountsToJSON(p.Accounts)
+ if _, e = models.Orm.Update(&m); e != nil {
+ logs.Error("[passwordStore] app update failed: %v", e)
+ passwordReply(&c.Controller, 500, "更新失败: "+e.Error(), nil)
+ return
+ }
+ passwordReply(&c.Controller, 200, "success", PasswordStoreItemDTO{
+ ID: m.ID, Tid: m.Tid, Platform: m.Platform, URL: m.URL,
+ Accounts: p.Accounts, Remark: m.Remark,
+ UserID: m.UserID, CreateTime: m.CreateTime, UpdateTime: m.UpdateTime,
+ })
+}
+
+// Delete DELETE /api/passwordStore/delete/:id
+func (c *AppPasswordStoreController) Delete() {
+ cl, e := c.appPwdClaims()
+ if e != nil {
+ passwordReply(&c.Controller, 401, "未登录或无权限", nil)
+ return
+ }
+ id, e := strconv.Atoi(c.Ctx.Input.Param(":id"))
+ if e != nil {
+ passwordReply(&c.Controller, 400, "参数错误", nil)
+ return
+ }
+ var m models.BackendPasswordStore
+ e = models.Orm.QueryTable(new(models.BackendPasswordStore)).
+ Filter("id", id).Filter("is_deleted", 0).Filter("tid", cl.TenantId).Filter("user_id", cl.UserID).One(&m)
+ if e == orm.ErrNoRows {
+ passwordReply(&c.Controller, 404, "记录不存在", nil)
+ return
+ }
+ if e != nil {
+ logs.Error("[passwordStore] app delete query failed: %v", e)
+ passwordReply(&c.Controller, 500, "查询失败: "+e.Error(), nil)
+ return
+ }
+ if _, e = models.Orm.Delete(&m); e != nil {
+ logs.Error("[passwordStore] app delete failed: %v", e)
+ passwordReply(&c.Controller, 500, "删除失败: "+e.Error(), nil)
+ return
+ }
+ middleware.WriteDeleteLog(uint64(cl.UserID), cl.TenantId, "passwordStore", m.Platform)
+ passwordReply(&c.Controller, 200, "success", nil)
+}
diff --git a/go/routers/api/api.go b/go/routers/api/api.go
index 12a4bb1..b445197 100644
--- a/go/routers/api/api.go
+++ b/go/routers/api/api.go
@@ -75,6 +75,11 @@ func Register() {
beego.Router("/api/schedule/:id", &controllers.AppReminderController{}, "get:GetDetail;put:Update;delete:Delete")
beego.Router("/api/schedule/:id/toggle", &controllers.AppReminderController{}, "post:ToggleComplete")
+ // 账号管理(密码库,与 /backend/passwordStore/* 同一套数据;字面量路由在 :id 通配之前)
+ beego.Router("/api/passwordStore/list", &controllers.AppPasswordStoreController{}, "get:GetList")
+ beego.Router("/api/passwordStore", &controllers.AppPasswordStoreController{}, "post:Create")
+ beego.Router("/api/passwordStore/:id", &controllers.AppPasswordStoreController{}, "get:GetDetail;post:Update;delete:Delete")
+
// 记事本
beego.Router("/api/notebook/list", &controllers.AppNotebookController{}, "get:GetList")
beego.Router("/api/notebook", &controllers.AppNotebookController{}, "post:Create")
diff --git a/platform/src/views/login/index.vue b/platform/src/views/login/index.vue
index ac48d67..6aa45b5 100644
--- a/platform/src/views/login/index.vue
+++ b/platform/src/views/login/index.vue
@@ -519,7 +519,6 @@ onMounted(() => {
.catch(() => {});
});
-const goRegister = () => router.push("/register");
const goForget = () => router.push("/forget");
const clearCache = async () => {
@@ -892,10 +891,6 @@ const clearCache = async () => {
font-size: 13px;
}
-.register-link {
- margin-right: 0px;
-}
-
.forget-link {
margin-left: 0px;
}
diff --git a/uniapp/api/passwordStore.js b/uniapp/api/passwordStore.js
new file mode 100644
index 0000000..938e0fe
--- /dev/null
+++ b/uniapp/api/passwordStore.js
@@ -0,0 +1,77 @@
+import { request } from '@/api/request.js'
+
+/**
+ * 账号管理(密码库)——记录个人各平台账号。
+ * 与 Web 端密码存储管理同一套数据(一个平台下挂多个账号)。
+ * 服务端自动过滤当前登录用户的记录,无需传 user_id。
+ */
+export function fetchPasswordStores(keyword) {
+ return request({
+ url: '/api/passwordStore/list',
+ data: keyword ? { keyword } : {}
+ }).then(data => ({
+ list: (data.list || []).map(normalizeStore),
+ total: data.total || 0
+ }))
+}
+
+export function getPasswordStore(id) {
+ return request({
+ url: `/api/passwordStore/detail/${id}`
+ }).then(normalizeStore)
+}
+
+export function createPasswordStore(data) {
+ return request({
+ url: '/api/passwordStore/create',
+ method: 'POST',
+ data: pickStore(data)
+ }).then(normalizeStore)
+}
+
+export function updatePasswordStore(id, data) {
+ return request({
+ url: `/api/passwordStore/update/${id}`,
+ method: 'POST',
+ data: pickStore(data)
+ }).then(normalizeStore)
+}
+
+export function deletePasswordStore(id) {
+ return request({
+ url: `/api/passwordStore/delete/${id}`,
+ method: 'DELETE'
+ }).then(() => true)
+}
+
+/** 只取服务端接收的字段 */
+function pickStore(data) {
+ return {
+ platform: data.platform || '',
+ url: data.url || '',
+ remark: data.remark || '',
+ accounts: (data.accounts || []).map(a => ({
+ username: a.username || '',
+ password: a.password || '',
+ registration_info: a.registration_info || '',
+ remark: a.remark || ''
+ }))
+ }
+}
+
+/** 统一账号列表结构,避免后端缺字段导致渲染报错 */
+function normalizeStore(item) {
+ const store = item || {}
+ return {
+ ...store,
+ platform: store.platform || '',
+ url: store.url || '',
+ remark: store.remark || '',
+ accounts: (store.accounts || []).map(a => ({
+ username: a.username || '',
+ password: a.password || '',
+ registration_info: a.registration_info || '',
+ remark: a.remark || ''
+ }))
+ }
+}
diff --git a/uniapp/components/NoteRichEditor.vue b/uniapp/components/NoteRichEditor.vue
index e57bf0a..c36e2d8 100644
--- a/uniapp/components/NoteRichEditor.vue
+++ b/uniapp/components/NoteRichEditor.vue
@@ -608,52 +608,32 @@ export default {
diff --git a/uniapp/pages.json b/uniapp/pages.json
index aff884f..f82c6c3 100644
--- a/uniapp/pages.json
+++ b/uniapp/pages.json
@@ -22,381 +22,6 @@
"navigationBarTitleText": "子系统"
}
},
- {
- "path": "pages/crm/home/home",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "客户关系管理"
- }
- },
- {
- "path": "pages/crm/functions/functions",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "客户关系 · 功能"
- }
- },
- {
- "path": "pages/crm/todo/todo",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "客户关系 · 待办"
- }
- },
- {
- "path": "pages/crm/mine/mine",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "客户关系 · 我的"
- }
- },
- {
- "path": "pages/erp/home/home",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "进销存管理"
- }
- },
- {
- "path": "pages/erp/functions/functions",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "进销存 · 功能"
- }
- },
- {
- "path": "pages/erp/todo/todo",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "进销存 · 待办"
- }
- },
- {
- "path": "pages/erp/mine/mine",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "进销存 · 我的"
- }
- },
- {
- "path": "pages/erp/dashboard/index",
- "style": {
- "navigationBarTitleText": "进销存工作台",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/document/index",
- "style": {
- "navigationBarTitleText": "单据列表",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/document/detail",
- "style": {
- "navigationBarTitleText": "单据详情",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/document/edit",
- "style": {
- "navigationBarTitleText": "开单",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/basic/product",
- "style": {
- "navigationBarTitleText": "商品档案",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/basic/product-detail",
- "style": {
- "navigationBarTitleText": "商品详情",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/basic/warehouse",
- "style": {
- "navigationBarTitleText": "仓库档案",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/partner/index",
- "style": {
- "navigationBarTitleText": "客商管理",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/partner/detail",
- "style": {
- "navigationBarTitleText": "客商详情",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/stock/index",
- "style": {
- "navigationBarTitleText": "库存结存",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/stock/ledger",
- "style": {
- "navigationBarTitleText": "收发存流水",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/stock/batch",
- "style": {
- "navigationBarTitleText": "批次效期",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/stock/warning",
- "style": {
- "navigationBarTitleText": "库存预警",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/finance/bill",
- "style": {
- "navigationBarTitleText": "应收应付",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/finance/bill-detail",
- "style": {
- "navigationBarTitleText": "账单详情",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/finance/fund",
- "style": {
- "navigationBarTitleText": "收付款单",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/finance/fund-edit",
- "style": {
- "navigationBarTitleText": "收付款",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/erp/report/index",
- "style": {
- "navigationBarTitleText": "报表中心",
- "navigationBarBackgroundColor": "#F8FAFC",
- "navigationBarTextStyle": "black"
- }
- },
- {
- "path": "pages/oa/home/home",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "协同办公"
- }
- },
- {
- "path": "pages/oa/functions/functions",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "OA · 功能"
- }
- },
- {
- "path": "pages/oa/todo/todo",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "OA · 待办"
- }
- },
- {
- "path": "pages/oa/mine/mine",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "OA · 我的"
- }
- },
- {
- "path": "pages/oa/notice/index",
- "style": {
- "navigationBarTitleText": "通知公告",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/dailyreport/index",
- "style": {
- "navigationBarTitleText": "工作日报",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/dailyreport/edit",
- "style": {
- "navigationBarTitleText": "填写日报",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/dailyreport/detail",
- "style": {
- "navigationBarTitleText": "日报详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/notice/detail",
- "style": {
- "navigationBarTitleText": "公告详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/document/index",
- "style": {
- "navigationBarTitleText": "文档库",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/document/detail",
- "style": {
- "navigationBarTitleText": "文档详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/compensation/index",
- "style": {
- "navigationBarTitleText": "我的工资单",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/compensation/detail",
- "style": {
- "navigationBarTitleText": "工资单明细",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/employeefile/index",
- "style": {
- "navigationBarTitleText": "员工档案",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/employeefile/detail",
- "style": {
- "navigationBarTitleText": "档案详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/contact/index",
- "style": {
- "navigationBarTitleText": "通讯录",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/oa/contact/detail",
- "style": {
- "navigationBarTitleText": "联系人详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/cms/home/home",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "网站内容管理"
- }
- },
- {
- "path": "pages/cms/functions/functions",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "网站管理 · 功能"
- }
- },
- {
- "path": "pages/cms/todo/todo",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "网站管理 · 待办"
- }
- },
- {
- "path": "pages/cms/mine/mine",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "网站管理 · 我的"
- }
- },
- {
- "path": "pages/toolbox/home/home",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "便捷工具"
- }
- },
- {
- "path": "pages/toolbox/functions/functions",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "便捷工具 · 功能"
- }
- },
- {
- "path": "pages/toolbox/todo/todo",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "便捷工具 · 待办"
- }
- },
- {
- "path": "pages/toolbox/mine/mine",
- "style": {
- "navigationStyle": "custom",
- "navigationBarTitleText": "便捷工具 · 我的"
- }
- },
{
"path": "pages/login/login",
"style": {
@@ -475,90 +100,523 @@
"navigationStyle": "custom",
"navigationBarTitleText": "我的"
}
+ }
+ ],
+ "subPackages": [
+ {
+ "root": "pages/crm",
+ "pages": [
+ {
+ "path": "home/home",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "客户关系管理"
+ }
+ },
+ {
+ "path": "functions/functions",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "客户关系 · 功能"
+ }
+ },
+ {
+ "path": "todo/todo",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "客户关系 · 待办"
+ }
+ },
+ {
+ "path": "mine/mine",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "客户关系 · 我的"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/notepad/index",
- "style": {
- "navigationBarTitleText": "记事本",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/erp",
+ "pages": [
+ {
+ "path": "home/home",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "进销存管理"
+ }
+ },
+ {
+ "path": "functions/functions",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "进销存 · 功能"
+ }
+ },
+ {
+ "path": "todo/todo",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "进销存 · 待办"
+ }
+ },
+ {
+ "path": "mine/mine",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "进销存 · 我的"
+ }
+ },
+ {
+ "path": "dashboard/index",
+ "style": {
+ "navigationBarTitleText": "进销存工作台",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "document/index",
+ "style": {
+ "navigationBarTitleText": "单据列表",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "document/detail",
+ "style": {
+ "navigationBarTitleText": "单据详情",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "document/edit",
+ "style": {
+ "navigationBarTitleText": "开单",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "basic/product",
+ "style": {
+ "navigationBarTitleText": "商品档案",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "basic/product-detail",
+ "style": {
+ "navigationBarTitleText": "商品详情",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "basic/warehouse",
+ "style": {
+ "navigationBarTitleText": "仓库档案",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "partner/index",
+ "style": {
+ "navigationBarTitleText": "客商管理",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "partner/detail",
+ "style": {
+ "navigationBarTitleText": "客商详情",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "stock/index",
+ "style": {
+ "navigationBarTitleText": "库存结存",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "stock/ledger",
+ "style": {
+ "navigationBarTitleText": "收发存流水",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "stock/batch",
+ "style": {
+ "navigationBarTitleText": "批次效期",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "stock/warning",
+ "style": {
+ "navigationBarTitleText": "库存预警",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "finance/bill",
+ "style": {
+ "navigationBarTitleText": "应收应付",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "finance/bill-detail",
+ "style": {
+ "navigationBarTitleText": "账单详情",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "finance/fund",
+ "style": {
+ "navigationBarTitleText": "收付款单",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "finance/fund-edit",
+ "style": {
+ "navigationBarTitleText": "收付款",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ },
+ {
+ "path": "report/index",
+ "style": {
+ "navigationBarTitleText": "报表中心",
+ "navigationBarBackgroundColor": "#F8FAFC",
+ "navigationBarTextStyle": "black"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/notepad/edit",
- "style": {
- "navigationBarTitleText": "新建笔记",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/oa",
+ "pages": [
+ {
+ "path": "home/home",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "协同办公"
+ }
+ },
+ {
+ "path": "functions/functions",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "OA · 功能"
+ }
+ },
+ {
+ "path": "todo/todo",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "OA · 待办"
+ }
+ },
+ {
+ "path": "mine/mine",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "OA · 我的"
+ }
+ },
+ {
+ "path": "notice/index",
+ "style": {
+ "navigationBarTitleText": "通知公告",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "dailyreport/index",
+ "style": {
+ "navigationBarTitleText": "工作日报",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "dailyreport/edit",
+ "style": {
+ "navigationBarTitleText": "填写日报",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "dailyreport/detail",
+ "style": {
+ "navigationBarTitleText": "日报详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "notice/detail",
+ "style": {
+ "navigationBarTitleText": "公告详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "document/index",
+ "style": {
+ "navigationBarTitleText": "文档库",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "document/detail",
+ "style": {
+ "navigationBarTitleText": "文档详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "compensation/index",
+ "style": {
+ "navigationBarTitleText": "我的工资单",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "compensation/detail",
+ "style": {
+ "navigationBarTitleText": "工资单明细",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "employeefile/index",
+ "style": {
+ "navigationBarTitleText": "员工档案",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "employeefile/detail",
+ "style": {
+ "navigationBarTitleText": "档案详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "contact/index",
+ "style": {
+ "navigationBarTitleText": "通讯录",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "contact/detail",
+ "style": {
+ "navigationBarTitleText": "联系人详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/schedule/index",
- "style": {
- "navigationBarTitleText": "工作日程",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/cms",
+ "pages": [
+ {
+ "path": "home/home",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "网站内容管理"
+ }
+ },
+ {
+ "path": "functions/functions",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "网站管理 · 功能"
+ }
+ },
+ {
+ "path": "todo/todo",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "网站管理 · 待办"
+ }
+ },
+ {
+ "path": "mine/mine",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "网站管理 · 我的"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/schedule/reminder",
- "style": {
- "navigationBarTitleText": "日程提醒",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/toolbox",
+ "pages": [
+ {
+ "path": "home/home",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "便捷工具"
+ }
+ },
+ {
+ "path": "functions/functions",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "便捷工具 · 功能"
+ }
+ },
+ {
+ "path": "todo/todo",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "便捷工具 · 待办"
+ }
+ },
+ {
+ "path": "mine/mine",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "便捷工具 · 我的"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/schedule/detail",
- "style": {
- "navigationBarTitleText": "日程详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/tools",
+ "pages": [
+ {
+ "path": "notepad/index",
+ "style": {
+ "navigationBarTitleText": "记事本",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "notepad/edit",
+ "style": {
+ "navigationBarTitleText": "新建笔记",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "schedule/index",
+ "style": {
+ "navigationBarTitleText": "工作日程",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "schedule/reminder",
+ "style": {
+ "navigationBarTitleText": "日程提醒",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "schedule/reminder-edit",
+ "style": {
+ "navigationBarTitleText": "新增日程提醒",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "schedule/detail",
+ "style": {
+ "navigationBarTitleText": "日程详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "schedule/edit",
+ "style": {
+ "navigationBarTitleText": "新建日程",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "expense/index",
+ "style": {
+ "navigationBarTitleText": "报销管理",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "expense/edit",
+ "style": {
+ "navigationBarTitleText": "新建报销单",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "account/index",
+ "style": {
+ "navigationBarTitleText": "账号管理",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "account/edit",
+ "style": {
+ "navigationBarTitleText": "新增账号",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "expense/detail",
+ "style": {
+ "navigationBarTitleText": "报销详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ }
+ ]
},
{
- "path": "pages/tools/schedule/edit",
- "style": {
- "navigationBarTitleText": "新建日程",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/tools/expense/index",
- "style": {
- "navigationBarTitleText": "报销管理",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/tools/expense/edit",
- "style": {
- "navigationBarTitleText": "新建报销单",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/tools/expense/detail",
- "style": {
- "navigationBarTitleText": "报销详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/approval/index",
- "style": {
- "navigationBarTitleText": "审批列表",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/approval/detail",
- "style": {
- "navigationBarTitleText": "审批详情",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
- },
- {
- "path": "pages/approval/verify",
- "style": {
- "navigationBarTitleText": "待我审批",
- "navigationBarBackgroundColor": "#F8FAFC"
- }
+ "root": "pages/approval",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "审批列表",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "detail",
+ "style": {
+ "navigationBarTitleText": "审批详情",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ },
+ {
+ "path": "verify",
+ "style": {
+ "navigationBarTitleText": "待我审批",
+ "navigationBarBackgroundColor": "#F8FAFC"
+ }
+ }
+ ]
}
],
"globalStyle": {
diff --git a/uniapp/pages/login/login.vue b/uniapp/pages/login/login.vue
index a343c0e..2067f20 100644
--- a/uniapp/pages/login/login.vue
+++ b/uniapp/pages/login/login.vue
@@ -1,176 +1,195 @@
-
-
-
-
+
+
+
+
+
+
+
+
- 云泽统一认证
- 一次登录,全平台通行
+ {{ navTitle }}
+
-
-
-
-
- 选择企业
- 该账号已加入多家企业,请选择要进入的空间
+
+
+
+
+
+
+ 云泽统一认证
+ 一次登录,全平台通行
+
-
- {{ errorMsg }}
-
+
+
+
+
+ 欢迎登录
+ 使用微信手机号,一键完成身份认证
+
-
-
-
-
+
+ {{ errorMsg }}
+
+
+
+
+
+
+
+ 首次使用请先用账号密码登录一次,自动完成微信绑定后即可一键登录
-
- {{ item.tenant_name || `企业${item.tid}` }}
- {{ item.name ? `${item.name} · ` : '' }}企业ID {{ item.tid }}
-
-
+
+
+ 正在加载登录方式…
-
+
-
- 不是我的账号?切换账号
-
-
-
-
-
-
- 欢迎登录
- {{ panelSub }}
-
-
-
- {{ errorMsg }}
-
-
-
-
-
-
- 微信登录
-
-
-
- 账号密码登录
-
-
-
-
-
-
-
-
- 首次使用请先用账号密码登录一次,自动完成微信绑定后即可一键登录
-
-
- 使用账号密码登录
+
+
+
+ 使用账号密码登录
+
+
-
-
-
-
- 账号
-
-
+
+
+
+ 欢迎回来
+ 请输入您的账号与密码以继续
-
-
- 密码
-
-
-
-
+ {{ errorMsg }}
+
+
+
+ 账号
+
+
+
-
-
-
-
-
- 请先阅读并勾选同意《用户协议》和《隐私政策》
-
-
+
+
+
+ 请选择企业
+ 该账号已加入多家企业,请选择要进入的空间
+
+
+
+ {{ errorMsg }}
+
+
+
+
+
+
+
+
+ {{ item.tenant_name || `企业${item.tid}` }}
+ {{ item.name ? `${item.name} · ` : '' }}企业ID {{ item.tid }}
+
+
+
+
+
+
+
+
+
+
+
+ 登录即表示同意
+ 《用户协议》
+ 和
+ 《隐私政策》
+
+
+
+
+
+
+ 请先阅读并勾选同意《用户协议》和《隐私政策》
+
+
+
-
-
-
- 登录即表示同意
- 《用户协议》
- 和
- 《隐私政策》
-
+
@@ -203,9 +222,25 @@ import {
import { showGeetest4 } from '@/utils/geetest.js'
import FaIcon from '@/components/FaIcon.vue'
-const step = ref('password')
-/** 小程序端登录方式 Tab:wechat / account(其他端固定账号密码) */
-const activeTab = ref('wechat')
+/** 运行端检测:h5 / apk(app-plus) / mp-weixin,决定登录方式优先级 */
+const platform = ref('')
+// #ifdef H5
+platform.value = 'h5'
+// #endif
+// #ifdef APP-PLUS
+platform.value = 'apk'
+// #endif
+// #ifdef MP-WEIXIN
+platform.value = 'mp-weixin'
+// #endif
+
+/**
+ * 视图状态:
+ * main 微信一键登录主入口(小程序端默认视图)
+ * account 账号密码登录(独立视图,由主视图弱化入口进入)
+ * tenant 选择企业(一人多企业)
+ */
+const step = ref(platform.value === 'mp-weixin' ? 'main' : 'account')
const account = ref('')
const password = ref('')
const showPassword = ref(false)
@@ -221,33 +256,65 @@ const verifyCfg = ref({ needGeetest: false, captchaId: '' })
/** 仅微信小程序端且服务端已开通时展示「一键登录」入口 */
const showMiniLogin = ref(false)
-/** 面板副标题:随 Tab 切换提示文案 */
-const panelSub = computed(() => {
- if (platform.value === 'mp-weixin' && showMiniLogin.value && activeTab.value === 'wechat') {
- return '使用微信一键登录,或切换到账号密码登录'
- }
- return '请输入您的账号与密码以继续'
+/** 顶部导航标题 */
+const navTitle = computed(() => {
+ if (step.value === 'tenant') return '选择企业'
+ return '账号密码登录'
})
-/** 切换登录方式 Tab:清掉上一次残留的错误提示 */
-function switchTab(tab) {
+/**
+ * 状态栏高度(px)。
+ * 小程序端 env(safe-area-inset-top) 在无刘海的安卓机型返回 0,
+ * 自绘导航会被状态栏压住,因此这里取系统信息里的真实状态栏高度。
+ */
+const statusBarHeight = ref(0)
+try {
+ const info =
+ typeof uni.getWindowInfo === 'function' ? uni.getWindowInfo() : uni.getSystemInfoSync()
+ statusBarHeight.value = (info && info.statusBarHeight) || 0
+} catch (e) {
+ statusBarHeight.value = 0
+}
+
+/** 自绘导航的上内边距:状态栏高度(导航本体固定 88rpx) */
+const navPadTop = computed(() => `${statusBarHeight.value}px`)
+
+/** 品牌区上内边距:主视图需让开状态栏,紧凑视图(账号/企业)由导航栏已占位 */
+const brandPadTop = computed(() => {
+ if (step.value !== 'main') return '32rpx'
+ return `${statusBarHeight.value + uni.upx2px(88)}px`
+})
+
+/** 是否存在可返回的上级视图(账号密码视图仅在小程序端可退回主视图) */
+const canGoBack = computed(() => {
+ if (step.value === 'tenant') return true
+ if (step.value === 'account') return showMiniLogin.value
+ return false
+})
+
+/** 切换到账号密码登录视图 */
+function goAccount() {
if (submitting.value) return
- if (activeTab.value === tab) return
- activeTab.value = tab
+ step.value = 'account'
errorMsg.value = ''
}
-/** 运行端检测:h5 / apk(app-plus) / mp-weixin,决定登录方式优先级 */
-const platform = ref('')
-// #ifdef H5
-platform.value = 'h5'
-// #endif
-// #ifdef APP-PLUS
-platform.value = 'apk'
-// #endif
-// #ifdef MP-WEIXIN
-platform.value = 'mp-weixin'
-// #endif
+/** 返回微信一键登录主视图 */
+function goMain() {
+ if (submitting.value) return
+ if (!showMiniLogin.value) return
+ step.value = 'main'
+ errorMsg.value = ''
+}
+
+/** 顶部导航返回 */
+function onNavBack() {
+ if (step.value === 'tenant') {
+ backToAccount()
+ return
+ }
+ goMain()
+}
onMounted(async () => {
if (isLoggedIn()) {
@@ -259,8 +326,6 @@ onMounted(async () => {
if (remembered.rememberMe) {
rememberMe.value = true
account.value = remembered.account
- // 记住了账号,默认落在账号密码 Tab 更顺手
- activeTab.value = 'account'
}
loadVerifyConfig()
@@ -289,6 +354,10 @@ async function loadMiniLoginConfig() {
} catch {
showMiniLogin.value = false
}
+ // 服务端未开通一键登录:直接落到账号密码视图
+ if (!showMiniLogin.value && step.value === 'main') {
+ step.value = 'account'
+ }
}
/* ==================== 登录主流程 ==================== */
@@ -394,9 +463,10 @@ function chooseTenant(item) {
})
}
+/** 从「选择企业」退回账号密码视图 */
function backToAccount() {
clearAuthState()
- step.value = 'password'
+ step.value = 'account'
errorMsg.value = ''
}
@@ -524,13 +594,14 @@ function handleMiniError(err) {
confirmText: '去登录',
confirmColor: '#2563eb',
success: (res) => {
- if (res.confirm) switchTab('account')
+ if (res.confirm) goAccount()
}
})
return
}
if (reason === 'not_configured') {
showMiniLogin.value = false
+ step.value = 'account'
}
showError(err)
}
@@ -553,11 +624,14 @@ function clearAuthState() {
}
function showError(err) {
- errorMsg.value = (err && err.message) || '登录失败,请稍后重试'
-}
-
-function goRegister() {
- uni.navigateTo({ url: '/pages/login/register' })
+ const raw = (err && err.message) || ''
+ // 微信未配置 request 合法域名:原始报错是英文,给出可操作的中文提示
+ if (/url not in domain list/i.test(raw)) {
+ errorMsg.value =
+ '当前小程序未配置服务器域名,请在微信公众平台「开发管理 - 开发设置 - 服务器域名」中添加 api.yunzer.cn 为 request 合法域名'
+ return
+ }
+ errorMsg.value = raw || '登录失败,请稍后重试'
}
/** 勾选/取消用户协议:勾选后自动收起未勾选提示 */
@@ -621,53 +695,151 @@ function goForget() {
+
\ No newline at end of file
diff --git a/uniapp/pages/nav/nav.vue b/uniapp/pages/nav/nav.vue
index b450809..6586286 100644
--- a/uniapp/pages/nav/nav.vue
+++ b/uniapp/pages/nav/nav.vue
@@ -3,10 +3,18 @@
- 选择子系统
- {{ enabledCount }}/{{ cards.length }} 已开通
+
+ YUNZE WORKSPACE
+ 工作台
+
+ {{ user.account || '我的账号' }}
- {{ user.tenant || '云泽平台' }} · {{ user.account }}
+
+
+ 当前租户{{ user.tenant || '云泽平台' }}
+ 切换
+
+ 选择一个业务系统,开始高效工作
@@ -53,7 +61,8 @@ import { mpHeadPad } from '@/utils/mpHead.js'
const headPad = mpHeadPad()
import { onShow } from '@dcloudio/uni-app'
-import { isLoggedIn } from '@/utils/auth.js'
+import { isLoggedIn, getTenants, getTid, setAuthTokens, setTid, setTenantName, getUser, setUser } from '@/utils/auth.js'
+import { switchTenant } from '@/api/auth.js'
import { fetchHome } from '@/api/workspace.js'
import { openMenu } from '@/utils/nav.js'
import { getSubsystemByModule, goSubsystem } from '@/config/subsystems.js'
@@ -80,6 +89,8 @@ const loadError = ref('')
const user = ref({})
const modules = ref([])
const menus = ref([])
+const tenants = ref(getTenants())
+const switchingTenant = ref(false)
/** 叶子菜单(可直接跳转的功能页),已锁定的过滤掉 */
const leafMenus = computed(() => menus.value.filter((m) => m.leaf !== false && !m.locked))
@@ -116,7 +127,6 @@ const cards = computed(() => {
})
})
-const enabledCount = computed(() => cards.value.filter((c) => !c.locked).length)
/* ==================== 数据加载 ==================== */
@@ -138,6 +148,41 @@ async function load(force = false) {
/* ==================== 交互 ==================== */
+function chooseTenant() {
+ const list = tenants.value
+ if (list.length <= 1) { uni.showToast({ title: list.length ? '当前账号仅绑定一个租户' : '暂无可切换的租户', icon: 'none' })
+ return
+ }
+ if (switchingTenant.value) return
+ uni.showActionSheet({
+ itemList: list.map((tenant) => tenant.tenant_name || `企业${tenant.tid}`),
+ success: async ({ tapIndex }) => {
+ const tenant = list[tapIndex]
+ if (!tenant || String(tenant.tid) === String(getTid())) return
+ switchingTenant.value = true
+ uni.showLoading({ title: '正在切换...', mask: true })
+ try {
+ const res = await switchTenant({ tid: tenant.tid })
+ if (!res || !res.tokens) throw new Error((res && res.msg) || '切换租户失败')
+ setAuthTokens(res.tokens)
+ setTid(tenant.tid)
+ setTenantName(tenant.tenant_name || '')
+ const profile = getUser() || {}
+ const nextUser = { ...profile, tid: tenant.tid, tenant_name: tenant.tenant_name || '' }
+ setUser(nextUser)
+ user.value = { ...user.value, tenant: tenant.tenant_name || '', account: nextUser.account || user.value.account }
+ await load(true)
+ uni.showToast({ title: '已切换租户', icon: 'success' })
+ } catch (e) {
+ uni.showToast({ title: (e && e.message) || '切换失败,请重试', icon: 'none' })
+ } finally {
+ uni.hideLoading()
+ switchingTenant.value = false
+ }
+ }
+ })
+}
+
/**
* 点击子系统卡片 → 进入该子系统独立页面组(带自己的 tabbar)。
* 未在 config/subsystems.js 注册的模块,降级为直接打开 Web 端该模块首页。
@@ -189,42 +234,80 @@ onShow(() => {
/* ============ 顶部信息(融入页面背景) ============ */
.head {
flex-shrink: 0;
- padding: calc(var(--status-bar-height, 44px) + 32rpx) $page-padding-x 12rpx;
+ padding: calc(var(--status-bar-height, 44px) + 32rpx) $page-padding-x 28rpx;
/* #ifdef MP-WEIXIN */
- /* 小程序端 --status-bar-height 固定 25px,需真实状态栏(env)+胶囊避让 */
padding-top: calc(env(safe-area-inset-top, 25px) + 96rpx);
/* #endif */
- background: $color-bg-page;
+ background: linear-gradient(145deg, #eaf3ff 0%, #f5f9ff 58%, #ffffff 100%);
+ border-bottom: 1rpx solid #e5efff;
}
.head-row {
display: flex;
- align-items: baseline;
+ align-items: center;
justify-content: space-between;
gap: 16rpx;
}
+.head-eyebrow {
+ display: block;
+ margin-bottom: 8rpx;
+ font-size: 18rpx;
+ font-weight: 700;
+ letter-spacing: 3rpx;
+ color: #6e9de5;
+}
+
.head-title {
- font-size: 42rpx;
- font-weight: 600;
- color: $color-text;
+ display: block;
+ font-size: 44rpx;
+ font-weight: 700;
+ color: #17345f;
letter-spacing: 1rpx;
}
-.head-count {
- font-size: 23rpx;
- color: $color-text-muted;
- flex-shrink: 0;
+.account-chip {
+ display: flex;
+ align-items: center;
+ gap: 9rpx;
+ padding: 12rpx 17rpx;
+ border-radius: 30rpx;
+ background: rgba(255,255,255,.85);
+ color: #526b8d;
+ font-size: 22rpx;
}
+.tenant-switch {
+ display: flex;
+ align-items: center;
+ margin-top: 28rpx;
+ padding: 20rpx 22rpx;
+ border: 1rpx solid #dceaff;
+ border-radius: 18rpx;
+ background: #ffffff;
+ box-shadow: 0 8rpx 24rpx rgba(47, 110, 196, .08);
+}
+
+.tenant-mark {
+ width: 64rpx;
+ height: 64rpx;
+ border-radius: 16rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: linear-gradient(145deg, #69a5ff, #3478f6);
+}
+
+.tenant-copy { flex: 1; min-width: 0; margin-left: 16rpx; }
+.tenant-label { display: block; font-size: 20rpx; color: #8a9bb3; }
+.tenant-name { display: block; margin-top: 5rpx; font-size: 27rpx; font-weight: 600; color: #203b62; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.tenant-action { display: flex; align-items: center; gap: 8rpx; color: #3478f6; font-size: 22rpx; font-weight: 600; }
+
.head-sub {
display: block;
- margin-top: 8rpx;
+ margin-top: 22rpx;
font-size: 23rpx;
- color: $color-text-muted;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+ color: #8295b0;
}
/* ============ 内容区 ============ */
@@ -233,7 +316,8 @@ onShow(() => {
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
- padding: 8rpx $page-padding-x 0;
+ padding: 20rpx $page-padding-x 0;
+ background: #f5f8fd;
}
/* ============ 失败提示 ============ */
@@ -300,7 +384,9 @@ onShow(() => {
.portal-card {
@include card;
- padding: 40rpx 16rpx 34rpx;
+ padding: 34rpx 16rpx 30rpx;
+ border: 1rpx solid #e6eef9;
+ box-shadow: 0 6rpx 20rpx rgba(38, 86, 150, .045);
display: flex;
flex-direction: column;
align-items: center;
diff --git a/uniapp/pages/tools/account/edit.vue b/uniapp/pages/tools/account/edit.vue
new file mode 100644
index 0000000..a626919
--- /dev/null
+++ b/uniapp/pages/tools/account/edit.vue
@@ -0,0 +1,399 @@
+
+
+
+
+ 平台信息
+
+
+ 平台名称 *
+
+
+
+
+ 登录网址
+
+
+
+
+ 平台备注
+
+
+
+
+
+
+
+ 挂载账号列表
+
+
+ 添加账号
+
+
+
+
+
+ 账号 {{ idx + 1 }}
+
+
+ 删除
+
+
+
+
+ 账号 / 用户名
+
+
+
+
+
+ 登录密码
+
+
+ 随机生成
+
+
+
+
+
+
+
+
+
+
+
+ 注册信息
+
+
+
+
+ 账号备注
+
+
+
+
+
+ 暂无账号,点击右上角「添加账号」
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uniapp/pages/tools/account/index.vue b/uniapp/pages/tools/account/index.vue
new file mode 100644
index 0000000..2e2ffa9
--- /dev/null
+++ b/uniapp/pages/tools/account/index.vue
@@ -0,0 +1,388 @@
+
+
+
+
+
+
+
+
+
+ 共 {{ total }} 条
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ store.platform || '未命名平台' }}
+
+ {{ store.url }}
+ 未填写网址
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 账号
+ {{ acc.username || '-' }}
+
+
+
+
+
+ 密码
+ {{ shownPwd[accKey(store, idx)] ? (acc.password || '-') : '••••••••' }}
+
+
+
+
+
+
+
+
+ 注册信息
+ {{ acc.registration_info }}
+
+
+ 备注
+ {{ acc.remark }}
+
+
+ 该平台暂无账号
+
+
+
+
+
+
+ 编辑
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uniapp/pages/tools/schedule/reminder-edit.vue b/uniapp/pages/tools/schedule/reminder-edit.vue
new file mode 100644
index 0000000..32ea386
--- /dev/null
+++ b/uniapp/pages/tools/schedule/reminder-edit.vue
@@ -0,0 +1,377 @@
+
+
+
+
+ 日程内容 *
+
+
+
+
+ 日程时间 *
+
+
+
+ {{ form.date || '选择日期' }}
+
+
+
+
+
+ {{ form.time || '选择时间' }}
+
+
+
+
+
+
+
+ 提前提醒
+
+
+ {{ minutesLabels[minutesIndex] }}
+
+
+
+
+
+
+ 提醒渠道 *
+
+
+ {{ opt.label }}
+
+
+ 可多选,至少选择一个提醒渠道
+
+
+
+
+ 重复提醒间隔
+
+
+ {{ repeatLabels[repeatIndex] }}
+
+
+
+ 仅邮件 / Bark 渠道支持重复提醒
+
+
+
+ 最大发送次数
+
+
+ {{ maxSendLabels[maxSendIndex] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uniapp/pages/tools/schedule/reminder.vue b/uniapp/pages/tools/schedule/reminder.vue
index cccd4e7..5bbbd6d 100644
--- a/uniapp/pages/tools/schedule/reminder.vue
+++ b/uniapp/pages/tools/schedule/reminder.vue
@@ -14,20 +14,52 @@
-
-
-
- {{ d.name }}
+
+
+
+
+
+
{{ d.day }}
-
+ v-for="d in weekDays"
+ :key="d.key"
+ class="week-item"
+ @tap="pickWeekDay(d)"
+ >
+ {{ d.name }}
+ {{ d.day }}
+
+
+
+
+
+
+ 周{{ n }}
+
+ {{ cell.day }}
+
+
@@ -48,7 +80,7 @@
:text="range === 'week' ? '本周暂无日程提醒' : '当天暂无日程提醒'"
/>
-
+
{{ shortDayLabel(item.datetime) }}
{{ timeText(item.datetime) }}
@@ -68,11 +100,18 @@
+
+
+
+
+ 新增
+