wanggang 1 year ago
parent
commit
8493d5f7c5
  1. 17
      code/src/Modules/BaseService/BaseService.Application/UserManagement/UserAppService.cs
  2. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/api/site.js
  3. 14
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/layouts/header.js
  4. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/layouts/logo.js
  5. 14
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/locale/index.js
  6. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/main.js
  7. 38
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/account.js
  8. 27
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory-detail.js
  9. 9
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/request/index.js
  10. 8
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/index.js
  11. 3
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/styles/site.css
  12. 17
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/utils/index.js
  13. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/utils/validation.js
  14. 64
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/account.js
  15. 7
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/login.js

17
code/src/Modules/BaseService/BaseService.Application/UserManagement/UserAppService.cs

@ -1,3 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BaseService.BaseData; using BaseService.BaseData;
using BaseService.BaseData.Permissions.Dto; using BaseService.BaseData.Permissions.Dto;
using BaseService.RelationBaseData; using BaseService.RelationBaseData;
@ -6,10 +10,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Omu.ValueInjecter; using Omu.ValueInjecter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
@ -25,7 +25,6 @@ using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace BaseService.Systems.UserManagement namespace BaseService.Systems.UserManagement
{ {
[Route("api/base/user")] [Route("api/base/user")]
//[Authorize(IdentityPermissions.Users.Default)]
public class UserAppService : ApplicationService, IUserAppService public class UserAppService : ApplicationService, IUserAppService
{ {
protected IdentityUserManager UserManager { get; } protected IdentityUserManager UserManager { get; }
@ -417,5 +416,13 @@ namespace BaseService.Systems.UserManagement
await UserManager.DeleteAsync(entity).ConfigureAwait(false); await UserManager.DeleteAsync(entity).ConfigureAwait(false);
return new OkResult(); return new OkResult();
} }
[Route("{userId}/change-password")]
public async Task ChangePassword(Guid userId, ChangePasswordInput input)
{
var user = await UserManager.GetByIdAsync(userId).ConfigureAwait(false);
var result = await UserManager.ChangePasswordAsync(user, input.CurrentPassword, input.NewPassword).ConfigureAwait(false);
result.CheckErrors();
}
} }
} }

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/api/site.js

@ -2,6 +2,7 @@ async function getLocalizationAsync() {
// const url = "abp/application-configuration"; // const url = "abp/application-configuration";
// const data = (await get(url, null, null, true, true)).data; // const data = (await get(url, null, null, true, true)).data;
return { return {
legacy: false,
options: [ options: [
{ {
value: "zh", value: "zh",
@ -144,6 +145,9 @@ async function getLocalizationAsync() {
isOnline: "在线", isOnline: "在线",
heartbeat: "心跳", heartbeat: "心跳",
userAgent: "用户代理", userAgent: "用户代理",
["Invalid username or password!"]: "用户名或密码错误",
["The user account has been locked out due to invalid login attempts. Please wait a while and try again."]: "用户已锁定,请稍后重试",
["Volo.Abp.Identity:PasswordMismatch"]: "密码错误",
}, },
en: { en: {
application: "WTA Framework", application: "WTA Framework",

14
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/layouts/header.js

@ -41,13 +41,7 @@ export default {
v-model="searchModel" v-model="searchModel"
:loading="searchLoading" :loading="searchLoading"
> >
<el-option <el-option v-for="item in searchOptions" :key="item.meta.path" :value="item.meta.path" :label="item.meta.fullName" @click="searchChange(item)" />
v-for="item in searchOptions"
:key="item.meta.path"
:value="item.meta.path"
:label="item.meta.fullName"
@click="searchChange(item)"
/>
</el-select> </el-select>
<el-icon v-model="isDark" @click="toggleDark()" :size="18" class="cursor-pointer"> <el-icon v-model="isDark" @click="toggleDark()" :size="18" class="cursor-pointer">
<ep-sunny v-if="isDark" /> <ep-sunny v-if="isDark" />
@ -63,7 +57,7 @@ export default {
<img v-if="appStore.user.avatar" /> <img v-if="appStore.user.avatar" />
<ep-user v-else /> <ep-user v-else />
</el-icon> </el-icon>
{{ appStore.user.name }} {{ appStore.user.userName }}
<el-icon class="el-icon--right"> <el-icon class="el-icon--right">
<ep-arrow-down /> <ep-arrow-down />
</el-icon> </el-icon>
@ -112,9 +106,7 @@ export default {
try { try {
searchLoading.value = true; searchLoading.value = true;
const menus = treeToList(router.getRoutes().find((o) => o.path === "/").children); const menus = treeToList(router.getRoutes().find((o) => o.path === "/").children);
searchOptions.value = menus searchOptions.value = menus.filter((o) => !o.children || o.children.length === 0).filter((o) => o.meta.fullName.indexOf(query) > -1);
.filter((o) => !o.children || o.children.length === 0)
.filter((o) => o.meta.fullName.indexOf(query) > -1);
} finally { } finally {
searchLoading.value = false; searchLoading.value = false;
} }

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/layouts/logo.js

@ -1,8 +1,9 @@
import html from "html"; import html from "html";
import { useAppStore } from "../store/index.js"; import { useAppStore } from "../store/index.js";
import { reload } from "../utils/index.js";
export default { export default {
template: html`<a href="javascript:location.reload(true)" class="logo"> template: html`<a href="javascript:;" @click="reload" class="logo">
<div class="flex h-full items-center"> <div class="flex h-full items-center">
<img src="/assets/logo.svg" /> <img src="/assets/logo.svg" />
<h1 v-if="!appStore.isMenuCollapse">{{$t('application')}}</h1> <h1 v-if="!appStore.isMenuCollapse">{{$t('application')}}</h1>
@ -12,6 +13,7 @@ export default {
const appStore = useAppStore(); const appStore = useAppStore();
return { return {
appStore, appStore,
reload,
}; };
}, },
}; };

14
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/locale/index.js

@ -1,13 +1,7 @@
import { createI18n } from "vue-i18n"; import { createI18n } from "vue-i18n";
import { useAppStore } from "../store/index.js"; import { getLocalizationAsync } from "../api/site.js";
function useLocale() { const localization = await getLocalizationAsync();
const appStore = useAppStore(); const i18n = createI18n(localization);
const i18n = createI18n({
legacy: false,
...appStore.localization,
});
return i18n;
}
export default useLocale; export default i18n;

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/main.js

@ -5,12 +5,12 @@ import router from "./router/index.js";
import ElementPlus from "element-plus"; import ElementPlus from "element-plus";
import * as ElementPlusIconsVue from "@element-plus/icons-vue"; import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import App from "/app.js"; import App from "/app.js";
import useLocale from "./locale/index.js"; import i18n from "./locale/index.js";
const app = createApp(App); const app = createApp(App);
app.use(store); app.use(store);
app.use(i18n);
await useAppStore().init(); await useAppStore().init();
app.use(useLocale());
app.use(router); app.use(router);
app.use(ElementPlus); app.use(ElementPlus);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {

38
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/account.js

@ -0,0 +1,38 @@
export default function () {
return {
title: "登录",
type: "object",
properties: {
currentPassword: {
title: "当前密码",
type: "string",
input: "password",
rules: [
{
required: true,
},
],
},
newPassword: {
title: "新密码",
type: "string",
input: "password",
rules: [
{
required: true,
},
],
},
newPassword2: {
title: "确认新密码",
type: "string",
input: "password",
rules: [
{
required: true,
},
],
},
},
};
}

27
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory-detail.js

@ -6,23 +6,36 @@ const schema = {
type: "object", type: "object",
properties: { properties: {
version, version,
state: state3,
billNum: { billNum: {
title: "发票号", title: "发票号",
type: "string", type: "string",
link: true, },
invGroupNum: {
title: "发票分组号",
type: "string",
},
groupNum: {
title: "结算分组号",
type: "string",
}, },
settleBillNum: { settleBillNum: {
title: "关联结算单号", title: "关联结算单号",
type: "string", type: "string",
}, },
invGroupNum: { lu: {
title: "发票分组号", title: "厂内零件号",
type: "string",
},
pn: {
title: "生产码",
type: "string",
},
relu: {
title: "替换零件号",
type: "string", type: "string",
link: true,
}, },
site: { extend4: {
title: "地点", title: "客户零件号",
type: "string", type: "string",
}, },
}, },

9
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/request/index.js

@ -4,10 +4,7 @@ import { useAppStore } from "../store/index.js";
import { getFileName } from "../utils/index.js"; import { getFileName } from "../utils/index.js";
import settings from "../config/settings.js"; import settings from "../config/settings.js";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import i18n from "../locale/index.js";
// const requestSettings = {
// baseURL: "/api",
// };
async function addToken(options) { async function addToken(options) {
if (await isLogin()) { if (await isLogin()) {
@ -57,7 +54,9 @@ async function getResult(response) {
result.errors = error; result.errors = error;
console.log(error); console.log(error);
} }
ElMessageBox.alert(`${result.errors?.error?.message ?? messages.get(response.status) ?? result.status}`, `${result.errors?.error?.code ?? "错误"}`);
const message = i18n.global.t(result.errors?.error?.code ?? "错误");
ElMessageBox({ title: "提示", message, type: "warning" });
} }
return result; return result;
} }

8
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/index.js

@ -19,6 +19,14 @@ const routes = [
isHidden: true, isHidden: true,
}, },
}, },
{
path: "/account",
component: () => import("../views/account.js"),
meta: {
title: "用户中心",
isHidden: true,
},
},
{ {
path: "/403", path: "/403",
component: () => import("../views/403.js"), component: () => import("../views/403.js"),

3
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/styles/site.css

@ -144,7 +144,8 @@ a.logo {
display: none; display: none;
} }
.el-aside *, .el-aside *,
.el-header { .el-header,
.el-header .el-dropdown-link {
background-color: #141414; background-color: #141414;
color: #e5eaf3; color: #e5eaf3;
} }

17
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/utils/index.js

@ -137,16 +137,9 @@ async function importFunction(input) {
return result; return result;
} }
function reload() {
location.href = `${location.protocol}//${location.host}${location.pathname}`;
}
export default html; export default html;
export { export { delay, persentFormat, bytesFormat, format, schemaToModel, listToTree, treeToList, getProp, getFileName, importFunction, reload };
delay,
persentFormat,
bytesFormat,
format,
schemaToModel,
listToTree,
treeToList,
getProp,
getFileName,
importFunction,
};

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/utils/validation.js

@ -118,9 +118,7 @@ const getRules = (parentSchema, property, data) => {
if (!property.rules) { if (!property.rules) {
return null; return null;
} }
const rules = [...(Array.isArray(property.rules) ? property.rules : [property.rules])].map((o) => const rules = [...(Array.isArray(property.rules) ? property.rules : [property.rules])].map((o) => Object.assign({}, o));
JSON.parse(JSON.stringify(o))
);
Object.values(rules).forEach((rule) => { Object.values(rules).forEach((rule) => {
rule.data = data; rule.data = data;
rule.schema = parentSchema; rule.schema = parentSchema;

64
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/account.js

@ -0,0 +1,64 @@
import html, { schemaToModel } from "html";
import { reactive } from "vue";
import AppForm from "../components/form/index.js";
import { getUser, setAccessToken } from "../api/user.js";
import router, { refreshRouter } from "../router/index.js";
import request from "../request/index.js";
import LayoutLogo from "../layouts/logo.js";
import LayoutLocale from "../layouts/locale.js";
import LayoutFooter from "../layouts/footer.js";
import { useAppStore } from "../store/index.js";
import useConfig from "../models/account.js";
import { ElMessage } from "element-plus";
export default {
components: { AppForm, LayoutLogo, LayoutLocale, LayoutFooter },
template: html`<el-container>
<el-main class="flex justify-center">
<div>
<div class="flex items-center justify-center">
<layout-logo />
<layout-locale />
</div>
<el-card class="box-card" style="width:400px;">
<app-form :schema="schema" v-model="model" @submit="submit">
<template #submitText>确定</template>
</app-form>
</el-card>
<layout-footer />
</div>
</el-main>
</el-container>`,
setup() {
const schema = useConfig();
const model = reactive(schemaToModel(schema));
schema.properties.newPassword2.rules.push({
validator: (rule, value, callback) => {
if (value !== model.newPassword) {
callback(new Error("确认新密码和新密码必须一致"));
} else {
callback();
}
},
});
const submit = async (callback, loading) => {
try {
const appStore = useAppStore();
const url = `base/user/${appStore.user.id}/change-password`;
const result = await request(url, model, { method: "POST" });
if (!result.errors) {
ElMessage.success("密码修改成功");
}
} catch (error) {
console.log(error);
} finally {
loading.value = false;
}
};
return {
schema,
model,
submit,
};
},
};

7
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/login.js

@ -9,6 +9,8 @@ import LayoutLocale from "../layouts/locale.js";
import LayoutFooter from "../layouts/footer.js"; import LayoutFooter from "../layouts/footer.js";
import { useAppStore } from "../store/index.js"; import { useAppStore } from "../store/index.js";
import useLoginModel from "../models/login.js"; import useLoginModel from "../models/login.js";
import { ElMessage } from "element-plus";
import { useI18n } from "vue-i18n";
export default { export default {
components: { AppForm, LayoutLogo, LayoutLocale, LayoutFooter }, components: { AppForm, LayoutLogo, LayoutLocale, LayoutFooter },
@ -31,12 +33,14 @@ export default {
setup() { setup() {
const schema = reactive(useLoginModel()); const schema = reactive(useLoginModel());
const model = reactive(schemaToModel(schema)); const model = reactive(schemaToModel(schema));
const { t } = useI18n();
const submit = async (callback, loading) => { const submit = async (callback, loading) => {
try { try {
const url = "base/token"; const url = "base/token";
const appStore = useAppStore(); const appStore = useAppStore();
const result = await request(url, model, { method: "POST" }); const result = await request(url, model, { method: "POST" });
if (!result.errors) { if (!result.errors) {
if (result.data?.accessToken) {
appStore.token = result.data.accessToken; appStore.token = result.data.accessToken;
if (appStore.token) { if (appStore.token) {
setAccessToken(appStore.token); setAccessToken(appStore.token);
@ -46,6 +50,9 @@ export default {
const redirect = router.currentRoute.value.query?.redirect ?? "/"; const redirect = router.currentRoute.value.query?.redirect ?? "/";
router.push(redirect); router.push(redirect);
} }
} else {
ElMessage.error(t(result.data.errorDescription));
}
} }
callback(result.errors); callback(result.errors);
} catch (error) { } catch (error) {

Loading…
Cancel
Save