Compare commits

..

5 Commits

Author SHA1 Message Date
橙子
fa1d68848f Update README.md 2022-05-12 23:40:27 +08:00
橙子
bce955a1e1 添加按钮权限 2022-05-12 23:39:42 +08:00
chenchun
82f70e0ac9 Update menuDic.js 2022-05-12 19:37:33 +08:00
chenchun
fc9b78cfef jwt授权不在需要添加bear 2022-05-11 16:24:36 +08:00
chenchun
72400a48da 添加sql参数 2022-05-11 12:21:59 +08:00
16 changed files with 161 additions and 106 deletions

View File

@@ -22,7 +22,7 @@ Yi框架-一套与SqlSugar一样爽的.Net6低代码开源框架。
适合.Net6学习、Sqlsugar学习 、项目二次开发。 适合.Net6学习、Sqlsugar学习 、项目二次开发。
集大成者,终究轮子 集大成者,终究轮子
Yi框架最新版本标签`v1.1.4`,具体版本可以查看标签迭代 Yi框架最新版本标签`v1.1.5`,具体版本可以查看标签迭代
项目与Sqlsugar同步更新但这作者老杰哥代码天天爆肝到凌晨两点我们也尽量会跟上他的脚步。更新频繁所以可watching持续关注。 项目与Sqlsugar同步更新但这作者老杰哥代码天天爆肝到凌晨两点我们也尽量会跟上他的脚步。更新频繁所以可watching持续关注。

View File

@@ -32,7 +32,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[Permission($"{nameof(T)}:get:list")] [Permission($"{nameof(T)}:get")]
[HttpGet] [HttpGet]
public virtual async Task<Result> GetById(long id) public virtual async Task<Result> GetById(long id)
{ {
@@ -43,7 +43,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// 列表查询 /// 列表查询
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[Permission($"{nameof(T)}:get:list")] [Permission($"{nameof(T)}:get")]
[HttpPost] [HttpPost]
public virtual async Task<Result> GetList(QueryCondition queryCondition) public virtual async Task<Result> GetList(QueryCondition queryCondition)
{ {
@@ -55,7 +55,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// </summary> /// </summary>
/// <param name="queryCondition"></param> /// <param name="queryCondition"></param>
/// <returns></returns> /// <returns></returns>
[Permission($"{nameof(T)}:get:list")] [Permission($"{nameof(T)}:get")]
[HttpPost] [HttpPost]
public virtual async Task<Result> PageList(QueryPageCondition queryCondition) public virtual async Task<Result> PageList(QueryPageCondition queryCondition)
{ {

View File

@@ -20,6 +20,16 @@
<None Remove="wwwrooot\**" /> <None Remove="wwwrooot\**" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Remove="yi-sqlsugar-dev.db" />
</ItemGroup>
<ItemGroup>
<Content Include="yi-sqlsugar-dev.db">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Yi.Framework.DTOModel\Yi.Framework.DTOModel.csproj" /> <ProjectReference Include="..\Yi.Framework.DTOModel\Yi.Framework.DTOModel.csproj" />
<ProjectReference Include="..\Yi.Framework.Interface\Yi.Framework.Interface.csproj" /> <ProjectReference Include="..\Yi.Framework.Interface\Yi.Framework.Interface.csproj" />

View File

@@ -1,5 +1,5 @@
{ {
"StartUrl": "http://localohost:19001", "StartUrl": "http://*:19001",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",

View File

@@ -1,5 +1,5 @@
{ {
"StartUrl": "http://localohost:19001", "StartUrl": "http://*:19001",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",

View File

@@ -21,8 +21,8 @@ namespace Yi.Framework.Repository
public Task<List<T>> GetListAsync(QueryCondition pars); public Task<List<T>> GetListAsync(QueryCondition pars);
public Task<bool> DeleteByLogicAsync(List<long> ids); public Task<bool> DeleteByLogicAsync(List<long> ids);
public Task<bool> UpdateIgnoreNullAsync(T entity); public Task<bool> UpdateIgnoreNullAsync(T entity);
public Task<List<S>> UseSqlAsync<S>(string sql); public Task<List<S>> UseSqlAsync<S>(string sql, object parameters = null);
public Task<bool> UseSqlAsync(string sql); public Task<bool> UseSqlAsync(string sql, object parameters = null);
ISugarQueryable<T> QueryConditionHandler(QueryCondition pars); ISugarQueryable<T> QueryConditionHandler(QueryCondition pars);
} }
} }

View File

@@ -42,24 +42,21 @@ namespace Yi.Framework.Repository
/// <typeparam name="S"></typeparam> /// <typeparam name="S"></typeparam>
/// <param name="sql"></param> /// <param name="sql"></param>
/// <returns></returns> /// <returns></returns>
public async Task<List<S>> UseSqlAsync<S>(string sql) public async Task<List<S>> UseSqlAsync<S>(string sql, object parameters = null)
{ {
return await _Db.Ado.SqlQueryAsync<S>(sql); return await _Db.Ado.SqlQueryAsync<S>(sql, parameters);
} }
/// <summary> /// <summary>
/// 执行增删改sql返回状态 /// 执行增删改sql返回状态
/// </summary> /// </summary>
/// <param name="sql"></param> /// <param name="sql"></param>
/// <returns></returns> /// <returns></returns>
public async Task<bool> UseSqlAsync(string sql) public async Task<bool> UseSqlAsync(string sql, object parameters)
{ {
return await _Db.Ado.ExecuteCommandAsync(sql)>0; return await _Db.Ado.ExecuteCommandAsync(sql, parameters) >0;
} }
/// <summary> /// <summary>
/// 添加返回实体 /// 添加返回实体
/// </summary> /// </summary>

View File

@@ -34,7 +34,7 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
var apiXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//控制器层注释 var apiXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//控制器层注释
//var entityXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//实体注释 //var entityXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//实体注释
//c.IncludeXmlComments(apiXmlPath, true);//true表示显示控制器注释 //c.IncludeXmlComments(apiXmlPath, true);//true表示显示控制器注释
c.IncludeXmlComments(apiXmlPath,true); c.IncludeXmlComments(apiXmlPath, true);
//添加控制器注释 //添加控制器注释
//c.DocumentFilter<SwaggerDocTag>(); //c.DocumentFilter<SwaggerDocTag>();
@@ -42,25 +42,40 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
//添加header验证信息 //添加header验证信息
//c.OperationFilter<SwaggerHeader>(); //c.OperationFilter<SwaggerHeader>();
//var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, }; //var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
c.AddSecurityDefinition("JwtBearer", new OpenApiSecurityScheme()
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{ {
Description = "文本框里输入从服务器获取的Token。格式为Bearer + 空格+token",//JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\" Description = "直接输入Token即可",
Name = "Authorization",////jwt默认的参数名称 Name = "Authorization",
In = ParameterLocation.Header,////jwt默认存放Authorization信息的位置(请求头中) In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey, Type = SecuritySchemeType.Http,
Scheme = "bearer"
}); });
c.AddSecurityRequirement(new OpenApiSecurityRequirement var scheme = new OpenApiSecurityScheme()
{ {
{ new OpenApiSecurityScheme Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "JwtBearer" }
{ };
Reference = new OpenApiReference() c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{ {
Id = "Bearer", [scheme] = new string[0]
Type = ReferenceType.SecurityScheme
}
}, Array.Empty<string>() }
}); });
//c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
//{
// Description = "文本框里输入从服务器获取的Token。格式为Bearer + 空格+token",//JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"
// Name = "Authorization",////jwt默认的参数名称
// In = ParameterLocation.Header,////jwt默认存放Authorization信息的位置(请求头中)
// Type = SecuritySchemeType.ApiKey,
//});
//c.AddSecurityRequirement(new OpenApiSecurityRequirement
//{
// { new OpenApiSecurityScheme
// {
// Reference = new OpenApiReference()
// {
// Id = "Bearer",
// Type = ReferenceType.SecurityScheme
// }
// }, Array.Empty<string>() }
//});
//c.AddServer(new OpenApiServer() //c.AddServer(new OpenApiServer()
//{ //{

View File

@@ -24,7 +24,7 @@
></v-text-field> ></v-text-field>
<v-btn <v-btn
v-if="axiosUrls.add != null" v-if="btnEnable.add==true"
color="primary" color="primary"
dark dark
class="mb-2 mx-2" class="mb-2 mx-2"
@@ -35,7 +35,7 @@
<!-- 添加提示框 --> <!-- 添加提示框 -->
<v-dialog <v-dialog
v-if="axiosUrls.add != null" v-if="btnEnable.add ==true"
v-model="dialog" v-model="dialog"
max-width="500px" max-width="500px"
> >
@@ -72,7 +72,7 @@
</v-dialog> </v-dialog>
<v-btn <v-btn
v-if="axiosUrls.del != null" v-if="btnEnable.del == true"
color="secondary" color="secondary"
class="mb-2" class="mb-2"
@click="deleteItem(null)" @click="deleteItem(null)"
@@ -87,14 +87,14 @@
<slot name="action" :item="item"></slot> <slot name="action" :item="item"></slot>
<v-icon <v-icon
v-if="axiosUrls.update != null" v-if="btnEnable.update ==true"
small small
class="mr-2" class="mr-2"
@click="editItem(item)" @click="editItem(item)"
> >
mdi-pencil mdi-pencil
</v-icon> </v-icon>
<v-icon v-if="axiosUrls.del != null" small @click="deleteItem(item)"> <v-icon v-if="btnEnable.del ==true" small @click="deleteItem(item)">
mdi-delete mdi-delete
</v-icon> </v-icon>
</template> </template>
@@ -119,6 +119,9 @@ export default {
axiosUrls: { axiosUrls: {
type: Object, type: Object,
}, },
btnEnable: {
type: Object,
},
}, },
data: () => ({ data: () => ({
page: 1, page: 1,
@@ -166,7 +169,7 @@ export default {
}); });
}, },
initialize() { initialize() {
if(this.axiosUrls.get!=undefined && this.axiosUrls.get!=null ) if(this.btnEnable.get==true )
{ {
this.dataInit(this.axiosUrls.get) this.dataInit(this.axiosUrls.get)
} }

View File

@@ -107,9 +107,9 @@ export default {
editedIndex: -1, editedIndex: -1,
defaultItem: { defaultItem: {
menuIcon: "mdi-view-dashboard", menuIcon: "mdi-view-dashboard",
permissionCode: "test", permissionCode: "",
menuName: "管理", menuName: "",
router:"/", router:"",
parentId: 0, parentId: 0,
MenuType:0 MenuType:0
}, },

View File

@@ -1,15 +1,6 @@
<template> <template>
<v-navigation-drawer <v-navigation-drawer id="default-drawer" v-model="$store.state.home.drawer" :dark="dark" :right="$vuetify.rtl"
id="default-drawer" :src="drawerImage ? image : ''" :mini-variant.sync="$store.state.home.mini" mini-variant-width="80" app width="260">
v-model="$store.state.home.drawer"
:dark="dark"
:right="$vuetify.rtl"
:src="drawerImage ? image : ''"
:mini-variant.sync="$store.state.home.mini"
mini-variant-width="80"
app
width="260"
>
<template v-if="drawerImage" #img="props"> <template v-if="drawerImage" #img="props">
<v-img :key="image" :gradient="gradient" v-bind="props" /> <v-img :key="image" :gradient="gradient" v-bind="props" />
</template> </template>
@@ -24,13 +15,7 @@
<template #append> <template #append>
<div class="pa-4 text-center"> <div class="pa-4 text-center">
<app-btn <app-btn class="text-none mb-4" color="white" href="https://vuetifyjs.com" small text>
class="text-none mb-4"
color="white"
href="https://vuetifyjs.com"
small
text
>
Documentation Documentation
</app-btn> </app-btn>
@@ -54,11 +39,14 @@ import { toTree } from "@/util/menuHandle";
export default { export default {
methods: { methods: {
init() { init() {
this.items=toTree( store.state.user.user.menus); const menus = store.state.user.user.menus.filter((m) => {
return m.menuType == 0;
});
this.items = toTree(menus);
}, },
logout() { logout() {
this.$store.dispatch("Logout") this.$store.dispatch("Logout")
this.$router.push({ path: "/login/" }); this.$router.push({ path: "/login/" });
}, },
}, },
created() { created() {

View File

@@ -0,0 +1,77 @@
import store from '../store/index'
//匹配按钮,判断是否有按钮存在
function getBtn(par) {
var axiosEnable = {
get: false,
update: false,
del: false,
add: false,
};
const per = store.state.user.per;
switch (par) {
case "user":
per.forEach(p => {
if(p=="user:get")
{
axiosEnable.get=true;
}
else if(p=="user:update")
{
axiosEnable.update=true;
}
else if(p=="user:del")
{
axiosEnable.del=true;
}
else if(p=="user:add")
{
axiosEnable.add=true;
}
});
break;
case "role":
if(p=="role:get")
{
axiosEnable.get=true;
}
else if(p=="role:update")
{
axiosEnable.update=true;
}
else if(p=="role:del")
{
axiosEnable.del=true;
}
else if(p=="role:add")
{
axiosEnable.add=true;
}
break;
case "menu":
if(p=="menu:get")
{
axiosEnable.get=true;
}
else if(p=="menu:update")
{
axiosEnable.update=true;
}
else if(p=="menu:del")
{
axiosEnable.del=true;
}
else if(p=="menu:add")
{
axiosEnable.add=true;
}
break;
default: console.log("未发现合法路由")
}
return axiosEnable;
}
export {getBtn};

View File

@@ -1,31 +0,0 @@
//匹配菜单让code变成路由
const menuDic=
{
"user:get:list": "/admuser",
"role:get:list": "/admrole",
"menu:get:list":"/admmenu",
"rolemenu:set:list":"/admrolemenu"
}
//匹配按钮,判断是否有按钮存在
const btnDic=
{
"user:add":"",
"user:update":"",
"user:del":"",
}
export default {menuDic,btnDic};
//菜单可以区分使用code来进行匹配
//记得:关于*的使用,要单独判断
//比如,
//按钮是user:*或者*:*:*直接全部放行即可
//菜单就不一样了,如果是*:*:*
//有两种方案:
//1:直接使用一个默认的全部菜单(会和后端给的菜单冲突)
//2:前端直接无视,*:*:*相当于只管后端权限(如果后端没有配置菜单前端将没有菜单了)
//如果查询找到的是user:*,可以先把*全部替换成get:list再进行比对即可
//等待持续更新中

View File

@@ -7,17 +7,20 @@
:defaultItem="defaultItem" :defaultItem="defaultItem"
:headers="headers" :headers="headers"
:axiosUrls="axiosUrls" :axiosUrls="axiosUrls"
:btnEnable="btnEnable"
> >
</ccTable> </ccTable>
</material-card> </material-card>
</template> </template>
<script> <script>
import { getBtn } from "../util/btnHandle";
export default { export default {
created() { created() {
this.init(); this.init();
}, },
methods: { methods: {
init() { init() {
this.btnEnable = getBtn("user")
this.axiosUrls = { this.axiosUrls = {
get: "/role/GetList", get: "/role/GetList",
update: "/role/Update", update: "/role/Update",
@@ -30,6 +33,7 @@ export default {
start: true, start: true,
axiosUrls: { axiosUrls: {
}, },
btnEnable:{},
headers: [ headers: [
// { text: "编号", align: "start", value: "id" }, // { text: "编号", align: "start", value: "id" },
{ text: "角色编号", value: "roleCode", sortable: false }, { text: "角色编号", value: "roleCode", sortable: false },

View File

@@ -3,22 +3,13 @@
<template #title> <template #title>
用户管理 <small class="text-body-1">用户可拥有多个角色</small> 用户管理 <small class="text-body-1">用户可拥有多个角色</small>
</template> </template>
<ccCombobox <ccCombobox headers="设置角色" :items="roleItems" @select="getSelect" itemText="roleName">
headers="设置角色"
:items="roleItems"
@select="getSelect"
itemText="roleName"
>
<template v-slot:save> <template v-slot:save>
<v-btn @click="setRole" color="blue darken-1" text> 保存</v-btn> <v-btn @click="setRole" color="blue darken-1" text> 保存</v-btn>
</template> </template>
</ccCombobox> </ccCombobox>
<ccTable <ccTable :defaultItem="defaultItem" :headers="headers" :axiosUrls="axiosUrls" :btnEnable="btnEnable"
:defaultItem="defaultItem" @selected="getTableSelect">
:headers="headers"
:axiosUrls="axiosUrls"
@selected="getTableSelect"
>
<template v-slot:action="{ item }"> <template v-slot:action="{ item }">
<v-icon small class="mr-2" @click="showItem(item)"> mdi-eye </v-icon> <v-icon small class="mr-2" @click="showItem(item)"> mdi-eye </v-icon>
</template> </template>
@@ -28,6 +19,7 @@
<script> <script>
import userApi from "../api/userApi"; import userApi from "../api/userApi";
import roleApi from "../api/roleApi"; import roleApi from "../api/roleApi";
import { getBtn } from "../util/btnHandle";
export default { export default {
created() { created() {
this.init(); this.init();
@@ -61,7 +53,7 @@ export default {
}, },
init() { init() {
//这里可以遍历后台的菜单code根据对应的菜单code来给axiosUrls的增删改查赋值即可 //这里可以遍历后台的菜单code根据对应的菜单code来给axiosUrls的增删改查赋值即可
this.btnEnable = getBtn("user")
this.axiosUrls = { this.axiosUrls = {
get: "/user/GetList", get: "/user/GetList",
update: "/user/Update", update: "/user/Update",
@@ -70,8 +62,7 @@ export default {
}; };
roleApi.getList().then((resp) => { roleApi.getList().then((resp) => {
console.log(resp.data) this.roleItems = JSON.parse(JSON.stringify(resp.data));
this.roleItems=JSON.parse(JSON.stringify(resp.data));
}); });
}, },
setRole() { setRole() {
@@ -99,6 +90,7 @@ export default {
}, },
}, },
data: () => ({ data: () => ({
btnEnable: [],
TableSelect: [], TableSelect: [],
select: [], select: [],
roleItems: [], roleItems: [],