From 01ecf9d7914ad192e20f3b255c6882ab87b1e6cb Mon Sep 17 00:00:00 2001
From: wanggang <76527413@qq.com>
Date: Wed, 12 Jul 2023 17:27:15 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9D=83=E9=99=90=E5=BA=93?=
=?UTF-8?q?=E5=A4=87=E4=BB=BDsql=EF=BC=9B=E6=9B=B4=E6=96=B0=E5=89=8D?=
=?UTF-8?q?=E7=AB=AF=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
code/WebApp/vanilla/api/user.js | 6 +-
.../vanilla/components/form/form-input.js | 9 +-
code/WebApp/vanilla/components/icon/index.js | 24 ++---
code/WebApp/vanilla/components/list/index.js | 22 +++--
code/WebApp/vanilla/models/code-setting.js | 86 +++++++++++++++++
code/WebApp/vanilla/models/role.js | 2 +-
code/WebApp/vanilla/models/user.js | 35 +++----
code/WebApp/vanilla/request/index.js | 13 ++-
code/WebApp/vanilla/router/index.js | 13 ++-
code/WebApp/vanilla/router/routes.js | 90 +++++++++++-------
code/WebApp/vanilla/utils/validation.js | 4 +-
.../vanilla/views/base-data/code-setting.js | 28 ++++++
code/WebApp/vanilla/views/base-data/user.js | 13 ++-
code/WebApp/vanilla/views/login.js | 14 +--
.../AuthServer.Host/appsettings.json | 2 +-
.../BaseService.Host/appsettings.json | 3 +-
docs/12.sql | Bin 0 -> 141416 bytes
17 files changed, 259 insertions(+), 105 deletions(-)
create mode 100644 code/WebApp/vanilla/models/code-setting.js
create mode 100644 code/WebApp/vanilla/views/base-data/code-setting.js
create mode 100644 docs/12.sql
diff --git a/code/WebApp/vanilla/api/user.js b/code/WebApp/vanilla/api/user.js
index e830bbdd..d245865a 100644
--- a/code/WebApp/vanilla/api/user.js
+++ b/code/WebApp/vanilla/api/user.js
@@ -1,5 +1,5 @@
import router from "../router/index.js";
-import { get, post } from "../request/index.js";
+import request, { get, post } from "../request/index.js";
import jwt_decode from "../lib/jwt-decode/jwt-decode.esm.js";
import qs from "../lib/qs/shim.js";
import { useAppStore } from "../store/index.js";
@@ -46,7 +46,9 @@ const logout = () => {
};
const getUser = async () => {
- const result = await get("abp/application-configuration");
+ const result = await request("abp/application-configuration", null, {
+ method: "GET",
+ });
const data = result.data;
const user = {};
user.id = data.currentUser.id;
diff --git a/code/WebApp/vanilla/components/form/form-input.js b/code/WebApp/vanilla/components/form/form-input.js
index 6d133fc6..87d16b3d 100644
--- a/code/WebApp/vanilla/components/form/form-input.js
+++ b/code/WebApp/vanilla/components/form/form-input.js
@@ -8,8 +8,9 @@ export default {
- {{dayjs(model[prop]).format('YYYY-MM-DD HH:mm:ss')}}
- {{dayjs(model[prop]).format('YYYY-MM-DD')}}
+ {{dayjs(model[prop]).format('YYYY-MM-DD HH:mm:ss')}}
+ {{dayjs(model[prop]).format('YYYY-MM-DD')}}
+ ******
{{model[prop]}}
@@ -70,7 +71,7 @@ export default {
});
/*start*/
const getDisabled = () => {
- if (props.mode==='details') {
+ if (props.mode === "details") {
return true;
}
if (props.mode === "update" && props.schema.readOnly) {
@@ -92,7 +93,7 @@ export default {
} else if (props.schema.url) {
try {
const url = `${props.schema.url}`;
- const result = await request(url, null, { method: "get" });
+ const result = await request(url, null, { method: "GET" });
options.value = result.data?.items.map((o) => ({
value: o[props.schema.value],
label: o[props.schema.label],
diff --git a/code/WebApp/vanilla/components/icon/index.js b/code/WebApp/vanilla/components/icon/index.js
index df178a82..2f446c3d 100644
--- a/code/WebApp/vanilla/components/icon/index.js
+++ b/code/WebApp/vanilla/components/icon/index.js
@@ -16,27 +16,21 @@ export default {
},
setup(props) {
const svg = ref(null);
+ const appStore = useAppStore();
onMounted(async () => {
if (!props.name.startsWith("ep-")) {
try {
const url = `./assets/icons/${props.name}.svg`;
- navigator.locks.request(url, async () => {
- const appStore = useAppStore();
- if (appStore.cache.has(url)) {
- svg.value = appStore.cache.get(url);
- } else {
- const response = await fetch(url);
- if (response.ok && response.status === 200) {
- svg.value = await response.text();
- appStore.cache.set(url, svg.value);
- }
- }
- });
+ if (!appStore.cache.has(url)) {
+ const response = await fetch(url);
+ const result = await response.text();
+ appStore.cache.set(url, result);
+ }
+ svg.value = appStore.cache.get(url);
} catch (error) {
console.log(error);
- if (!svg.value) {
- svg.value = ``;
- }
+ } finally {
+ svg.value ??= ``;
}
}
});
diff --git a/code/WebApp/vanilla/components/list/index.js b/code/WebApp/vanilla/components/list/index.js
index 82a456cc..d9d4125b 100644
--- a/code/WebApp/vanilla/components/list/index.js
+++ b/code/WebApp/vanilla/components/list/index.js
@@ -352,9 +352,11 @@ export default {
const router = useRouter();
const { t } = useI18n();
const appStore = useAppStore();
- const buttons = ref(props.buttons ?? route.meta.children.filter((o) => o.meta.hasPermission));
+ // 注释一下代码暂停权限验证
+ // const buttons = ref(props.buttons ?? route.meta.children.filter((o) => o.meta.hasPermission));
+ // 添加下行代码暂停权限验证
+ const buttons = ref(props.buttons ?? route.meta.children);
const baseUrl = props.controller ?? `${route.meta.path}`;
- const indexUrl = props.indexUrl ?? `${baseUrl}/index`;
const queryModel = ref({});
const sortColumns = ref(new Map());
const querySchema = ref(props.querySchema);
@@ -476,7 +478,8 @@ export default {
editFormModel.value = schemaToModel(config.edit.schema);
} else {
const url = `${config.edit.updateUrl ?? config.query.url}/${rows[0].id}`;
- editFormModel.value = (await request(url, null, { method: "get" })).data;
+ editFormModel.value = (await request(url, null, { method: "GET" })).data;
+ editFormModel.value.id = rows[0].id;
}
editFormTitle.value = `${t(item.path)}${config.edit.schema.title}`;
dialogVisible.value = true;
@@ -516,8 +519,11 @@ export default {
const valid = await editFormRef.value.validate();
if (valid) {
editFormloading.value = true;
- const url =
+ let url =
(editFormMode.value === "create" ? config.edit.createUrl : config.edit.updateUrl) ?? config.query.url;
+ if (editFormMode.value === "update") {
+ url = `${url}/${editFormModel.value.id}`;
+ }
const method = editFormMode.value === "create" ? config.edit.createMethod : config.edit.updateMethod;
const result = await request(url, editFormModel.value, { method });
if (result.errors) {
@@ -617,9 +623,11 @@ export default {
return false;
};
onMounted(async () => {
- for (const item of route.meta.children) {
- if (item.meta.disabled?.constructor === String) {
- item.meta.disabled = await importFunction(item.meta.disabled);
+ if (route.meta.children?.length) {
+ for (const item of route.meta.children) {
+ if (item.meta.disabled?.constructor === String) {
+ item.meta.disabled = await importFunction(item.meta.disabled);
+ }
}
}
pushQueryList();
diff --git a/code/WebApp/vanilla/models/code-setting.js b/code/WebApp/vanilla/models/code-setting.js
new file mode 100644
index 00000000..561da745
--- /dev/null
+++ b/code/WebApp/vanilla/models/code-setting.js
@@ -0,0 +1,86 @@
+const schema = {
+ title: "通用代码",
+ type: "object",
+ properties: {
+ userName: {
+ title: "项目",
+ type: "string",
+ readOnly: true,
+ showForList: true,
+ rules: [
+ {
+ required: true,
+ },
+ ],
+ },
+ userName: {
+ title: "值",
+ type: "string",
+ readOnly: true,
+ showForList: true,
+ rules: [
+ {
+ required: true,
+ },
+ ],
+ },
+ name: {
+ title: "描述",
+ type: "string",
+ showForList: true,
+ rules: [
+ {
+ required: true,
+ },
+ ],
+ },
+ },
+};
+
+const url = "base/code-settings";
+const createUrl = url;
+const updateUrl = url;
+const deleteUrl = url;
+const method = "GET";
+const createMethod = "POST";
+const updateMethod = "PUT";
+const deleteMethod = "DELETE";
+
+export default function () {
+ return {
+ query: {
+ url,
+ method,
+ schema: {
+ title: "通用代码",
+ type: "object",
+ properties: {
+ filter: {
+ title: "项目",
+ type: "string",
+ },
+ skipCount: {
+ hidden: true,
+ default: 0,
+ },
+ maxResultCount: {
+ hidden: true,
+ default: 10,
+ },
+ },
+ },
+ },
+ table: {
+ schema: schema,
+ },
+ edit: {
+ createUrl,
+ updateUrl,
+ deleteUrl,
+ createMethod,
+ updateMethod,
+ deleteMethod,
+ schema: schema,
+ },
+ };
+}
diff --git a/code/WebApp/vanilla/models/role.js b/code/WebApp/vanilla/models/role.js
index c574f7c3..e65832bb 100644
--- a/code/WebApp/vanilla/models/role.js
+++ b/code/WebApp/vanilla/models/role.js
@@ -23,7 +23,7 @@ export default function () {
return {
query: {
url: "identity/roles",
- method: "get",
+ method: "GET",
schema: {
title: "用户",
type: "object",
diff --git a/code/WebApp/vanilla/models/user.js b/code/WebApp/vanilla/models/user.js
index 08960eba..8c2fcfa9 100644
--- a/code/WebApp/vanilla/models/user.js
+++ b/code/WebApp/vanilla/models/user.js
@@ -5,7 +5,7 @@ const schema = {
userName: {
title: "用户名",
type: "string",
- readOnly: true, //
+ readOnly: true,
showForList: true,
rules: [
{
@@ -20,6 +20,7 @@ const schema = {
password: {
title: "密码",
type: "string",
+ readOnly: true,
input: "password",
},
name: {
@@ -52,18 +53,18 @@ const schema = {
},
],
},
- roleNames: {
- title: "角色",
- type: "array",
- input: "select",
- multiple: true,
- url: "identity/roles/all",
- value: "name",
- label: "name",
- items: {
- type: "string",
- },
- },
+ // roleNames: {
+ // title: "角色",
+ // type: "array",
+ // input: "select",
+ // multiple: true,
+ // url: "identity/roles/all",
+ // value: "name",
+ // label: "name",
+ // items: {
+ // type: "string",
+ // },
+ // },
},
};
@@ -71,10 +72,10 @@ const url = "base/user";
const createUrl = url;
const updateUrl = url;
const deleteUrl = "api/identity/users";
-const method = "get";
-const createMethod = "post";
-const updateMethod = "put";
-const deleteMethod = "delete";
+const method = "GET";
+const createMethod = "POST";
+const updateMethod = "PUT";
+const deleteMethod = "DELETE";
export default function () {
return {
diff --git a/code/WebApp/vanilla/request/index.js b/code/WebApp/vanilla/request/index.js
index 4c9a8ab7..dc9e51e3 100644
--- a/code/WebApp/vanilla/request/index.js
+++ b/code/WebApp/vanilla/request/index.js
@@ -113,7 +113,6 @@ async function request(url, data, options, withoutToken = false) {
method: "POST",
headers: {
"Accept-Language": "zh-Hans",
- "Content-Type": "application/json",
},
};
if (options) {
@@ -121,17 +120,17 @@ async function request(url, data, options, withoutToken = false) {
}
if (defaultOptions.method === "GET" && data) {
url = `${url}?${qs.stringify(data)}`;
- }
- if (defaultOptions.method === "POST") {
- if (data instanceof FormData) {
- delete defaultOptions.headers["Content-Type"];
- }
+ } else {
if (defaultOptions.headers["Content-Type"]?.startsWith("application/x-www-form-urlencoded")) {
defaultOptions.body = qs.stringify(data);
} else if (defaultOptions.headers["Content-Type"]?.startsWith("application/json")) {
defaultOptions.body = JSON.stringify(data);
- } else {
+ } else if (data instanceof FormData) {
+ delete defaultOptions.headers["Content-Type"];
defaultOptions.body = data;
+ } else if (data) {
+ defaultOptions.headers["Content-Type"] = "application/json";
+ defaultOptions.body = JSON.stringify(data);
}
}
if (!withoutToken) {
diff --git a/code/WebApp/vanilla/router/index.js b/code/WebApp/vanilla/router/index.js
index 8d1fcca7..61294c3d 100644
--- a/code/WebApp/vanilla/router/index.js
+++ b/code/WebApp/vanilla/router/index.js
@@ -49,11 +49,14 @@ router.beforeEach(async (to, from, next) => {
if (!(await isLogin())) {
next({ path: "/login", query: { redirect: to.fullPath } });
} else {
- if (!to.meta.public && to.meta.hasPermission === false) {
- next({ path: "/403", query: { redirect: to.fullPath } });
- } else {
- next();
- }
+ // 注释以下代码暂停权限验证
+ // if (!to.meta.public && to.meta.hasPermission === false) {
+ // next({ path: "/403", query: { redirect: to.fullPath } });
+ // } else {
+ // next();
+ // }
+ // 添加一下代码暂停权限验证
+ next();
}
} else {
next();
diff --git a/code/WebApp/vanilla/router/routes.js b/code/WebApp/vanilla/router/routes.js
index ed43f2aa..1dafad91 100644
--- a/code/WebApp/vanilla/router/routes.js
+++ b/code/WebApp/vanilla/router/routes.js
@@ -55,50 +55,68 @@ export default [
isTop: true,
},
},
- ],
- },
- {
- path: "role",
- meta: {
- type: "page",
- title: "角色管理",
- icon: "file",
- permission: "AbpIdentity.Users",
- },
- children: [
- {
- path: "create",
- meta: {
- type: "button",
- title: "新建",
- icon: "file",
- permission: "AbpIdentity.Users.Create",
- isTop: true,
- },
- },
{
- path: "update",
+ path: "%s/reset-password",
meta: {
type: "button",
- title: "编辑",
+ title: "重置密码",
icon: "file",
- htmlClass: "el-button--primary",
- permission: "AbpIdentity.Users.Update",
- disabled: `(o) => o.isStatic`,
- },
- },
- {
- path: "delete",
- meta: {
- type: "button",
- title: "删除",
- icon: "file",
- permission: "AbpIdentity.Users.Delete",
- disabled: `(o) => o.isStatic`,
+ permission: "reset-password?",
+ method: "PUT",
},
},
],
},
+ // {
+ // path: "role",
+ // meta: {
+ // type: "page",
+ // title: "角色管理",
+ // icon: "file",
+ // permission: "AbpIdentity.Users",
+ // },
+ // children: [
+ // {
+ // path: "create",
+ // meta: {
+ // type: "button",
+ // title: "新建",
+ // icon: "file",
+ // permission: "AbpIdentity.Users.Create",
+ // isTop: true,
+ // },
+ // },
+ // {
+ // path: "update",
+ // meta: {
+ // type: "button",
+ // title: "编辑",
+ // icon: "file",
+ // htmlClass: "el-button--primary",
+ // permission: "AbpIdentity.Users.Update",
+ // disabled: `(o) => o.isStatic`,
+ // },
+ // },
+ // {
+ // path: "delete",
+ // meta: {
+ // type: "button",
+ // title: "删除",
+ // icon: "file",
+ // permission: "AbpIdentity.Users.Delete",
+ // disabled: `(o) => o.isStatic`,
+ // },
+ // },
+ // ],
+ // },
+ {
+ path: "code-setting",
+ meta: {
+ type: "page",
+ title: "通用代码",
+ icon: "file",
+ },
+ },
],
},
];
diff --git a/code/WebApp/vanilla/utils/validation.js b/code/WebApp/vanilla/utils/validation.js
index 29bd903a..5155c275 100644
--- a/code/WebApp/vanilla/utils/validation.js
+++ b/code/WebApp/vanilla/utils/validation.js
@@ -80,10 +80,10 @@ const validators = {
} else {
const config = {
url: rule.url,
- method: rule.method ?? "get",
+ method: rule.method ?? "GET",
};
const data = { [rule.field]: value };
- if (config.method === "get") {
+ if (config.method === "GET") {
config.params = data;
} else {
config.data = data;
diff --git a/code/WebApp/vanilla/views/base-data/code-setting.js b/code/WebApp/vanilla/views/base-data/code-setting.js
new file mode 100644
index 00000000..bab632ca
--- /dev/null
+++ b/code/WebApp/vanilla/views/base-data/code-setting.js
@@ -0,0 +1,28 @@
+import AppList from "../../components/list/index.js";
+import html from "html";
+import useConfig from "../../models/code-setting.js";
+import request from "../../request/index.js";
+import { format } from "../../utils/index.js";
+import { ElMessage } from "element-plus";
+
+export default {
+ components: { AppList },
+ template: html``,
+ setup() {
+ // 变量定义
+ const config = useConfig();
+ // 函数定义
+ const onCommand = async (item, rows) => {
+ console.log(item.path, item, rows);
+ if (item.path === "%s/reset-password") {
+ const url = format(item.path, rows[0].id);
+ await request(`base/user/${url}`, null, { method: item.meta.method });
+ ElMessage({
+ type: "info",
+ message: format("用户%s的密码已经成功重置为123456", rows[0].userName),
+ });
+ }
+ };
+ return { config, onCommand };
+ },
+};
diff --git a/code/WebApp/vanilla/views/base-data/user.js b/code/WebApp/vanilla/views/base-data/user.js
index 414d4630..e6df244e 100644
--- a/code/WebApp/vanilla/views/base-data/user.js
+++ b/code/WebApp/vanilla/views/base-data/user.js
@@ -1,6 +1,9 @@
import AppList from "../../components/list/index.js";
import html from "html";
import useConfig from "../../models/user.js";
+import request from "../../request/index.js";
+import { format } from "../../utils/index.js";
+import { ElMessage } from "element-plus";
export default {
components: { AppList },
@@ -9,8 +12,16 @@ export default {
// 变量定义
const config = useConfig();
// 函数定义
- const onCommand = (item, rows) => {
+ const onCommand = async (item, rows) => {
console.log(item.path, item, rows);
+ if (item.path === "%s/reset-password") {
+ const url = format(item.path, rows[0].id);
+ await request(`base/user/${url}`, null, { method: item.meta.method });
+ ElMessage({
+ type: "info",
+ message: format("用户%s的密码已经成功重置为123456", rows[0].userName),
+ });
+ }
};
return { config, onCommand };
},
diff --git a/code/WebApp/vanilla/views/login.js b/code/WebApp/vanilla/views/login.js
index 832c0adb..0f1c2a05 100644
--- a/code/WebApp/vanilla/views/login.js
+++ b/code/WebApp/vanilla/views/login.js
@@ -36,12 +36,14 @@ export default {
const result = await request(url, model, { method: "POST" }, true);
if (!result.errors) {
appStore.token = result.data.accessToken;
- setAccessToken(appStore.token);
- //setRefreshToken(result.data.refresh_token);
- appStore.user = await getUser();
- await refreshRouter();
- const redirect = router.currentRoute.value.query?.redirect ?? "/";
- router.push(redirect);
+ if (appStore.token) {
+ setAccessToken(appStore.token);
+ //setRefreshToken(result.data.refresh_token);
+ appStore.user = await getUser();
+ await refreshRouter();
+ const redirect = router.currentRoute.value.query?.redirect ?? "/";
+ router.push(redirect);
+ }
}
callback(result.errors);
} catch (error) {
diff --git a/code/src/AuthServer/AuthServer.Host/appsettings.json b/code/src/AuthServer/AuthServer.Host/appsettings.json
index 1a4089cd..ca902997 100644
--- a/code/src/AuthServer/AuthServer.Host/appsettings.json
+++ b/code/src/AuthServer/AuthServer.Host/appsettings.json
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
- "Default": "Server=dev.ccwin-in.com,13319;Database=BJABP;User ID=ccwin-in;Password=Microsoft@2022;Trusted_Connection=False;TrustServerCertificate=True"
+ "Default": "Server=localhost;Database=BJABP;User ID=sa;Password=aA123456!;Trusted_Connection=False;TrustServerCertificate=True"
},
"CorsOrigins": "http://localhost:9527,http://dev.ccwin-in.com:10588,http://localhost:44307",
"ElasticSearch": {
diff --git a/code/src/Modules/BaseService/BaseService.Host/appsettings.json b/code/src/Modules/BaseService/BaseService.Host/appsettings.json
index 73b75822..5901cf11 100644
--- a/code/src/Modules/BaseService/BaseService.Host/appsettings.json
+++ b/code/src/Modules/BaseService/BaseService.Host/appsettings.json
@@ -1,8 +1,9 @@
{
"AuthServer": {
"Authority": "http://dev.ccwin-in.com:10580",
+ //"Authority": "http://localhost:10130",
"ClientId": "basic-web",
- "ClientSecret": ""
+ "ClientSecret": "1q2w3e*"
},
"App": {
"CorsOrigins": "http://localhost:9527,http://dev.ccwin-in.com:10588,http://localhost:44307"
diff --git a/docs/12.sql b/docs/12.sql
new file mode 100644
index 0000000000000000000000000000000000000000..da14e750cc2dedc6a159e170a891b625ab26142b
GIT binary patch
literal 141416
zcmeHQ+j1N?lC9UBi2Vn?`4V2)lE>p2Z#ZIUl9IWiNDiB{?A1(k=t9XH%cO>+ENeb~
zch3Qs0t$^P6bh*7YBoY4iR`YzC6RgZf<)r~{`aJsRXf#2^`!c>dRkpo*VSotS^d5G
z_v#PTgX%#2|9SPP^=AX0KCAwL=bq!~Z}9F$wT*YL@%Nc(<5ab`S$$U>q9uOMKQlak
zS)EmH@T9zPs@}g>eNo-3zN|j4zQ*6X_;~~WeueMu;gfIh^PljEJ%-QKxVEYzjD52@
zRx{XEKe5-%4|9?+a5fv&7Dm30r#Guz{Qn4V@wbiYTm0Qu-|eV&Im3N?wt?{<;n_!c
z)zh2meR=mIJi*z1RDFhT@8g|4)w=uCHfHlTjP9@a{%>gEOwr^5bib%x
zD!S8le1FsW
zUA4l0#J^wMwEW2prT6gU13aZE9-{BOdJRgwnlzndjCU~BW_pt%Usitvr9-r)bnv+c
zA67*8t2>=Vk~gtxl$IkH$FXWCLJgH^o5jdN?w2Kjtv$^I!Rdf8bqd0Hx!zy!D
zHgfDj7B(O;cW<7!U!CABJ%%6Aig52PWOGMJ+X4RN_}Ih8Sm#~H#{KFoX!#nSomRg?
zN_MMrg;Y<~r>CIuN7X0z!=9hvnOBgjbM@N}IClqa6W;_2?%?MacVVVk8^|KY3B3L_Fm;A!C%$IsVsF
zn`6y(K#fiHJ6GobzmdW=&2#iL8=!6S&^G=Md$q*p9s6Une}uMm`#EPo9Y8E22OTKh
z%t!eXw0wXy-hxydD0#@=_6%d^9QJ{|`CC7M#A+0L4BIWrCZ?o
zBecd9u<13&C;RG?1L(y^YOQk3vfigFeH-9ot{M@P7??Ug&SOha&zAY0Fryu`zm2(@
z&vVU?*g{K){IP}hsky1$xuUtb{jX^G09>(y*5~Mt^rQtwEx|cbE9F5n+J&-qyGlpR
z(GTbN0Dst1K761i-9>w(7d7G>|C5RjZ)TLn6~uat5Meo+V+=FsO>$8#N*c+g^?Zas
zqHq(-bX`6eF_k>)p}CKht!Ti`)r*h9>L
z2u*J^t*33Q0@t5*3~hnDc9{4ilvB-Zk8V6=jS~D+TeO=PgK!>yrsYrXR{NnM)t@BK
zmv+dJqAexaqwzDdRX7`1~n+p;P?+QvJqn8GG4>m%?#K
zyn?@Tm9+2D-&dr5r%cc{Bp*=1g}!=SZ4Ne(Cq0&W%&FarnW=T6r$}n)H6sT;xS=uE
zR%4j>u|&}anDv$#9j&Y*rMHRr#-k-CYQ8WU&gRSijF7?jG3rRmHb#DkSura0MKx@X
zi&{u)L81`psXaB0gwz~%EH?MlZ3^<#{6;5pRP^cVcu^l&J7%0DLJ;F*v)i!PlT|QQ$
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
o@Idvwa;y-q-{dWGhf1r+t&