1.

 sync Sqlite structure started
 sync Sqlite structure succeed

 sync data started
 table: ai_template sync data succeed
 table: ad_dictionary_type sync data succeed
 table: ad_dictionary sync data succeed
 table: ad_user sync data succeed
 table: ad_user_staff sync data succeed
 table: ad_org sync data succeed
 table: ad_role sync data succeed
 table: ad_api sync data succeed
 table: ad_view sync data succeed
 table: ad_permission sync data succeed
 table: ad_user_role sync data succeed
 table: ad_user_org sync data succeed
 table: ad_role_permission sync data succeed
 table: ad_tenant sync data succeed
 table: ad_tenant_permission import data []
 table: ad_permission_api sync data succeed
 sync data succeed

SELECT a."Id", a."Topic", a."Body", a."Round", a."Interval", a."IntervalArgument", a."CreateTime", a."LastRunTime", a."CurrentRound", a."ErrorTimes", a."Status"
FROM "app_task" a
WHERE (a."Status" = 0 AND (a."Round" < 0 OR a."CurrentRound" < a."Round"))

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:8000
info: ZhonTai.Admin.Core.Auth.ResponseAuthenticationHandler[12]
      AuthenticationScheme: ResponseAuthenticationHandler was challenged.
AuthenticationScheme: ResponseAuthenticationHandler was challenged.
info: ZhonTai.Admin.Core.Auth.ResponseAuthenticationHandler[12]
      AuthenticationScheme: ResponseAuthenticationHandler was challenged.
AuthenticationScheme: ResponseAuthenticationHandler was challenged.
fail: ZhonTai.Admin.Core.Filters.ValidateInputFilter[0]
      Password:密码不能为空!|UserName:用户名不能为空!
Password:密码不能为空!|UserName:用户名不能为空!
SELECT a."Id", a."CreatedUserId", a."CreatedUserName", a."CreatedTime", a."ModifiedUserId", a."ModifiedUserName", a."ModifiedTime", a."IsDeleted", a."UserName", a."Password", a."Name", a."Mobile", a."Email", a."OrgId", a."ManagerUserId", a."NickName", a."Avatar", a."Status", a."Type"
FROM "ad_user" a
WHERE (a."UserName" = 'admin' AND a."Password" = '96E79218965EB72C92A549DD5A330112')
limit 0,1

INSERT INTO "ad_login_log"("Id", "CreatedUserId", "CreatedUserName", "CreatedTime", "Name", "IP", "Browser", "Os", "Device", "BrowserInfo", "ElapsedMilliseconds", "Status", "Msg", "Result") VALUES(479375531114565, 161223411986501, 'admin', datetime(current_timestamp,'localtime'), 'admin', '127.0.0.1', 'Edge', 'Windows', '', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0', 157, 1, NULL, NULL)

2.

D:\terrywork\aibpm.ui.plus-main>npm install
npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "^6.1@.9" of package "@codemirror/lang-javascript@^6.1@.9": Tags may not have any characters that encodeURIComponent encodes.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\user\AppData\Local\npm-cache\_logs\2023-11-05T16_08_05_000Z-debug-0.log
  "dependencies": {
    "@codemirror/lang-javascript": "^6.1.9",
 
先建接口,再建视图,再添加菜单

 添加菜单,在【权限管理】-【权限管理】里. 可以添加【分组】,【菜单】,【权限点】

 

后端菜单权限在【权限管理】-》【角色管理】-》【菜单权限】

 有些图标显示不了,应该是css font字体被block了,

src\utils\setIconfont.ts 里面的

// 字体图标 url
const cssCdnUrlList: Array<string> = [
  '//at.alicdn.com/t/c/font_2298093_rnp72ifj3ba.css',
  '//cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css',
]

 src\utils\getStyleSheets.ts 里的,改一下网址 cdn.staticfile.org

 for (let i = 0; i < styles.length; i++) {
        if (styles[i].href && styles[i].href.indexOf('netdna.bootstrapcdn.com') > -1) {
          sheetsList.push(styles[i])
        }
      }

 菜单权限是后端控制的

 

 

更改左边顶部的logo

import logoMini from '/@/assets/logo-mini.svg'
 
多语言实现 src\i18n\lang\zh-cn.ts
 
 
====================================================================
给现有实体增加字段的步骤: XXXentity.cs 里增加字段,XXXAddInput的DTO也要增加字段
新增实体和后端权限和前端页面步骤:(以新增product为例)
====================================================================
1.  在后端项目里Domain, Repositories,Services 三个目录新建实体相关的类,利用DynamicAPI生成动态接口
 
using FreeSql.DataAnnotations;
using ZhonTai.Admin.Core.Entities;
namespace Fox.ERP.Model
{
    /// <summary>
    /// 料品
    /// </summary>
    [Table(Name = "erp_product")]
    [Index("idx_{tablename}_01", nameof(TenantId), true)]
    public class ProductEntity : EntityTenant  
    {
         
        /// <summary>
        /// 料品名称
        /// </summary>
        [Column(StringLength = 100)]
        public string Name { get; set; }
        /// <summary>
        /// 料品编码
        /// </summary>
        [Column(StringLength = 100)]
        public string Sku { get; set; }
        /// <summary>
        /// 料品描述
        /// </summary>
        public string ShortDescription { get; set; }
        /// <summary>
        /// 是否虚拟点卡
        /// </summary>
        public bool IsGiftCard { get; set; }
        /// <summary>
        /// 是否可下载
        /// </summary>
        public bool IsDownload { get; set; }


    }
}
ProductEntity
using Fox.ERP.Model;
using ZhonTai.Admin.Core.Repositories;
 
namespace Fox.ERP.Repository
{
    /// <summary>
    /// 
    /// </summary>
    public interface IProductRepository : IRepositoryBase<ProductEntity>
    {
    }
}
IProductRepository
using Fox.ERP.Model;
using ZhonTai.Admin.Core.Consts;
using ZhonTai.Admin.Core.Db.Transaction;
using ZhonTai.Admin.Core.Repositories;

namespace Fox.ERP.Repository
{
    /// <summary>
    /// 
    /// </summary>
    public class ProductRepository : RepositoryBase<ProductEntity>, IProductRepository
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="muowm"></param>
        public ProductRepository(UnitOfWorkManagerCloud muowm) : base(DbKeys.AppDb, muowm)
        {
        }


    }
}
ProductRepository
using Fox.ERP.Services.ERP.Product.Dto;

namespace Fox.ERP.Services.ERP.Product
{
    /// <summary>
    /// 料品服务
    /// </summary>
    public interface IProductService
    {
        Task<ProductGetOutput> GetAsync(long id);

        Task<long> AddAsync(ProductAddInput input);

        Task UpdateAsync(ProductUpdateInput input);

        Task DeleteAsync(long id);


    }
}
IProductService
using Fox.ERP.Model;
using Fox.ERP.Repository;
using Fox.ERP.Services.ERP.Product.Dto;
using ZhonTai.Admin.Core.Attributes;
using ZhonTai.Admin.Core.Configs;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
namespace Fox.ERP.Services.ERP.Product
{
    /// <summary>
    /// 料品服务
    /// </summary>
    [DynamicApi(Area = ERPConstants.AreaName)]
    public class ProductService : BaseService,IProductService, IDynamicApi
    {
        //??究竟应该是构造函数注入,还是LazyGetRequiredService注入呢?
        private AppConfig _appConfig => LazyGetRequiredService<AppConfig>();
        private IProductRepository _productRepository => LazyGetRequiredService<IProductRepository>();
        /// <summary>
        /// 构造函数
        /// </summary>
        public ProductService()
        {


        }
        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ProductGetOutput> GetAsync(long id)
        {
            var Entity = await _productRepository.Select
                            .WhereDynamic(id)
                            .ToOneAsync();

           var output = Mapper.Map<ProductGetOutput>(Entity);
            return output;
        }


        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AdminTransaction]
        public virtual async Task<long> AddAsync(ProductAddInput input)
        {
            var entity = Mapper.Map<ProductEntity>(input);
            var prod = await _productRepository.InsertAsync(entity);
            var prodId = prod.Id;
            return prodId;
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateAsync(ProductUpdateInput input)
        {
            var entity = Mapper.Map<ProductEntity>(input);
            await _productRepository.UpdateAsync(entity);            
        }

        /// <summary>
        /// 彻底删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [AdminTransaction]
        public virtual async Task DeleteAsync(long id)
        {
            await _productRepository.DeleteAsync(a => a.Id == id);

        }

    }
}
ProductService

 

 2. appconfig.json 里 增加projects,调试后端接口

接口文档的调试出现401 未登录,是要先用authorization

 

3. 后端接口调试完成后,在【接口管理】点【同步】,自动更新接口

前端 gen 根据./templates生成api相关文件,接口更新后执行npm run gen:bpm-api会生成接口的定义和接口模型

 

  "name": "aibpm.ui",
  "version": "0.9.3.3",
  "description": "aibpm vue3 ",
  "author": "Leo",
  "license": "MIT",
  "scripts": {
    "dev": "vite --force",
    "build": "vite build",
    "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
    "format": "npx prettier --write .",
    "install:pkg": "npm install --registry https://registry.npmmirror.com",
    "gen:admin-api": "node ./gen/gen-admin-api",
    "gen:bpm-api": "node ./gen/gen-bpm-api"
  },
package.json

 

 

 

 

4.【权限管理】里新增【权限点】(查询,新增,修改,删除,批量删除... 等等),要选择API接口,

 权限点的编码(api:erp:product:get, api:erp:product:add,api:erp:product:update,api:erp:product:delete 在前端要用到)

5.【视图管理】,新建一个url路由和前端视图地址的对应关系

 

前端权限判断

<el-button v-auth="'api:erp:product:add'" type="primary" icon="ele-Plus" @click="onAdd"> 新增 </el-button>

 <el-button v-auth="'api:erp:product:update'" icon="ele-EditPen" size="small" text type="primary" 
            @click="onEdit(row)">编辑</el-button>
            <my-dropdown-more v-auths="['api:admin:permission:assign', 'api:erp:product:delete']">
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item v-if="auth('api:erp:product:delete')" 
                  @click="onDelete(row)">删除</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </my-dropdown-more>

 

 

 01.前后端分离中台框架后端 Admin.Core 学习-介绍与配置说明 - 易墨 - 博客园 (cnblogs.com)

    /// <summary>
    /// 员工服务
    /// </summary>
    [DynamicApi(Area = BPMConstants.AreaName)]
    public class MyUserService : UserService, IMyUserService

    /// <summary>
    /// 用户服务
    /// </summary>
    [Order(10)]
    [DynamicApi(Area = AdminConsts.AreaName)]
    public partial class UserService : BaseService, IUserService, IDynamicApi

 

 CodeFirst | FreeSql 官方文档

var freeSqlBuilder = new FreeSqlBuilder()
        .UseConnectionString(dbConfig.Type, dbConfig.ConnectionString, providerType)
        .UseAutoSyncStructure(false)
        .UseLazyLoading(false)
        .UseNoneCommandParameter(true);

 表实体 | Admin - 后台权限管理 (zhontai.net)

 

比如客户编码要保持唯一,

在实体的特性加上     [Index("idx_{tablename}_02", nameof(Code), true)]

但这样保持实体,会抛出异常,假如没有捕抓的话,前端就显示内部服务器错误。

需要捕捉异常

            var entity = Mapper.Map<SupplierEntity>(input);
            try
            {
                await _SupplierRepository.UpdateAsync(entity);
            }
            catch (Exception ex)
            {

                ResultOutput.NotOk(ex.Message);
                throw ResultOutput.Exception("编码不能相同!");
            }

 动态API的,在【接口管理】点【同步】,生成的接口是把驼峰改成连接线的,比如【SaleOrder】=> sale-order

 

在mac运行,uploadconfig.json 要改路径,原来的

    //上传路径 D:/upload/admin/avatar
    "uploadPath": "/upload/admin/avatar",
    //请求路径
    "requestPath": "/upload/admin/avatar",

  "document": {
    //上传路径 D:/upload/admin/document
    "uploadPath": "/upload/admin/document",

要改成

    //上传路径 D:/upload/admin/avatar
    "uploadPath": "/Users/terryzhang/upload/admin/avatar",
    //请求路径
    "requestPath": "/Users/terryzhang/upload/admin/avatar",
    //上传路径 D:/upload/admin/document
    "uploadPath": "/Users/terryzhang/upload/admin/document",

 dbconfig.json 改成 //

 "connectionString": "Data Source=|DataDirectory|//admindb.db; Pooling=true;Min Pool Size=1",

posted on 2023-11-06 22:01  Gu  阅读(89)  评论(0编辑  收藏  举报