user:manage:detail加上了action-panel

This commit is contained in:
Xu Chang 2022-05-09 20:44:30 +08:00
parent 22294a1073
commit d301eace00
42 changed files with 1087 additions and 57 deletions

View File

@ -6,7 +6,7 @@ export declare abstract class GeneralRuntimeContext<ED extends EntityDict> exten
private getTokenFn;
private scene;
constructor(store: RowStore<ED, GeneralRuntimeContext<ED>>, appId: string, getToken: () => Promise<string | undefined>, scene: string);
getApplication(): Promise<import("oak-domain/lib/types").SelectRowShape<EntityDict, {
getApplication(): Promise<import("oak-domain/lib/types").SelectRowShape<import("oak-app-domain/Application/Schema").Schema, {
id: 1;
name: 1;
config: 1;

View File

@ -5,10 +5,12 @@ const UniversalContext_1 = require("oak-domain/lib/store/UniversalContext");
class GeneralRuntimeContext extends UniversalContext_1.UniversalContext {
applicationId;
getTokenFn;
constructor(store, appId, getToken) {
scene;
constructor(store, appId, getToken, scene) {
super(store);
this.applicationId = appId;
this.getTokenFn = getToken;
this.scene = scene;
}
async getApplication() {
const { result: [application] } = await this.rowStore.select('application', {
@ -42,6 +44,9 @@ class GeneralRuntimeContext extends UniversalContext_1.UniversalContext {
return token;
}
}
getScene() {
return this.scene;
}
}
exports.GeneralRuntimeContext = GeneralRuntimeContext;
;

View File

@ -7,6 +7,7 @@ exports.syncUserInfoWechatMp = exports.loginWechatMp = exports.loginByPassword =
const oak_wechat_sdk_1 = __importDefault(require("oak-wechat-sdk"));
const assert_1 = __importDefault(require("assert"));
const lodash_1 = require("lodash");
const extraFile_1 = require("../utils/extraFile");
async function loginMp(params, context) {
const { rowStore } = context;
throw new Error('method not implemented!');
@ -105,8 +106,7 @@ async function loginWechatMp({ code, env }, context) {
action: 'create',
data: {
id: await generateNewId(),
name: '',
nickname: ''
userState: 'normal',
},
},
});
@ -185,6 +185,7 @@ async function loginWechatMp({ code, env }, context) {
// 到这里都是要同时创建wechatUser和user对象了
const userData = {
id: await generateNewId(),
userState: 'normal',
};
const wechatUserCreateData = {
id: await generateNewId(),
@ -240,6 +241,7 @@ async function syncUserInfoWechatMp({ nickname, avatarUrl, encryptedData, iv, si
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
@ -252,59 +254,57 @@ async function syncUserInfoWechatMp({ nickname, avatarUrl, encryptedData, iv, si
applicationId: application.id,
}
}, context);
const { type, config } = application;
(0, assert_1.default)(type === 'wechatMp' || config.type === 'wechatMp');
const config2 = config;
const { appId, appSecret } = config2;
const wechatInstance = oak_wechat_sdk_1.default.getInstance(appId, appSecret, 'wechatMp');
console.log(avatarUrl);
// console.log(avatarUrl);
// const { type, config } = application;
// assert(type === 'wechatMp' || config.type === 'wechatMp');
// const config2 = config as WechatMpConfig;
// const { appId, appSecret } = config2;
// const wechatInstance = WechatSDK.getInstance(appId, appSecret, 'wechatMp');
// const result = wechatInstance.decryptData(sessionKey as string, encryptedData, iv, signature);
// 实测发现解密出来的和userInfo完全一致……
// console.log(result);
const { id, nickname: originNickname, extraFile$entity } = user;
const { nickname: originNickname, extraFile$entity } = user;
const updateData = {};
if (nickname !== originNickname) {
Object.assign(updateData, {
nickname,
});
}
/* if (extraFile$entity?.length === 0 || composeFileUrl(extraFile$entity![0]) !== avatarUrl) {
if (extraFile$entity?.length === 0 || (0, extraFile_1.composeFileUrl)(extraFile$entity[0]) !== avatarUrl) {
// 需要更新新的avatar extra file
const extraFileOperations: ExtraFileOperation['data'][] = [
const extraFileOperations = [
{
action: 'create',
data: assign({
data: (0, lodash_1.assign)({
id: await generateNewId(),
tag1: 'avatar',
userId,
}, decomposeFileUrl(avatarUrl))
entity: 'user',
entityId: userId,
}, (0, extraFile_1.decomposeFileUrl)(avatarUrl))
}
];
if (extraFile$entity!.length > 0) {
extraFileOperations.push(
{
action: 'remove',
data: {},
filter: {
id: extraFile$entity![0].id,
}
if (extraFile$entity.length > 0) {
extraFileOperations.push({
action: 'remove',
data: {},
filter: {
id: extraFile$entity[0].id,
}
);
});
}
assign(updateData, {
(0, lodash_1.assign)(updateData, {
extraFile$entity: extraFileOperations,
});
}
if (keys(updateData).length > 0) {
if ((0, lodash_1.keys)(updateData).length > 0) {
await rowStore.operate('user', {
action: 'update',
data: updateData,
filter: {
id,
id: userId,
}
}, context);
} */
}
}
exports.syncUserInfoWechatMp = syncUserInfoWechatMp;
/* export type AspectDict<ED extends EntityDict> = {

View File

@ -1,2 +1,2 @@
declare const _default: (import("oak-domain/lib/types").Checker<EntityDict, "address", import("..").GeneralRuntimeContext<EntityDict>> | import("oak-domain/lib/types").Checker<EntityDict, "token", import("..").GeneralRuntimeContext<EntityDict>>)[];
declare const _default: (import("oak-domain/lib/types").Checker<import("oak-app-domain").EntityDict, "address", import("..").GeneralRuntimeContext<import("oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Checker<import("oak-app-domain").EntityDict, "token", import("..").GeneralRuntimeContext<import("oak-app-domain").EntityDict>> | import("oak-domain/lib/types").Checker<import("oak-app-domain").EntityDict, "user", import("..").GeneralRuntimeContext<import("oak-app-domain").EntityDict>>)[];
export default _default;

View File

@ -4,4 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const address_1 = __importDefault(require("./address"));
exports.default = [...address_1.default];
const token_1 = __importDefault(require("./token"));
const user_1 = __importDefault(require("./user"));
exports.default = [...address_1.default, ...token_1.default, ...user_1.default];

37
lib/checkers/token.js Normal file
View File

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = require("oak-domain/lib/types");
const Exceptions_1 = require("../types/Exceptions");
const lodash_1 = require("lodash");
const filter_1 = require("oak-domain/lib/store/filter");
const checkers = [
{
type: 'user',
action: 'select',
entity: 'token',
checker: async ({ operation }, context) => {
const scene = context.getScene();
const { filter } = operation;
if (scene === 'token:me') {
if (!filter || !filter.id) {
const token = await context.getToken();
if (!token) {
throw new Exceptions_1.OakUnloggedInException();
}
const { id } = token;
(0, lodash_1.assign)(operation, {
filter: (0, filter_1.combineFilters)([filter, { id }]),
});
return 1;
}
return 0;
}
if (['app:onLaunch', 'token:me', 'token:login'].includes(scene)) {
return 0;
}
// 对获取token的权限进行精细化控制除了root
throw new types_1.OakUserUnpermittedException();
},
}
];
exports.default = checkers;

5
lib/checkers/user.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Checker } from "oak-domain/lib/types";
import { EntityDict } from 'oak-app-domain';
import { GeneralRuntimeContext } from '../RuntimeContext';
declare const checkers: Checker<EntityDict, 'user', GeneralRuntimeContext<EntityDict>>[];
export default checkers;

24
lib/checkers/user.js Normal file
View File

@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const checkers = [
{
type: 'data',
action: 'create',
entity: 'user',
checker: async ({ operation }) => {
/* const { action, data } = operation;
if (data instanceof Array) {
data.forEach(
ele => {
checkAttributesNotNull(ele, ['nickname']);
}
);
}
else {
checkAttributesNotNull(data, ['nickname']);
} */
return 0;
},
}
];
exports.default = checkers;

File diff suppressed because one or more lines are too long

4
lib/data/index.d.ts vendored
View File

@ -1,6 +1,6 @@
declare const _default: {
user: UserCreate[];
role: RoleCreate[];
user: import("oak-app-domain/User/Schema").CreateOperationData[];
role: import("oak-app-domain/Role/Schema").CreateOperationData[];
area: ({
code: string;
level: string;

View File

@ -5,6 +5,7 @@ const constants_1 = require("../constants");
exports.users = [
{
password: 'oak@2022',
nickname: 'root',
name: 'root',
id: constants_1.ROOT_USER_ID,
}

View File

@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Token = void 0;
const lodash_1 = require("lodash");
const oak_frontend_base_1 = require("oak-frontend-base");
const concurrent_1 = require("oak-domain/lib/utils/concurrent");
class Token extends oak_frontend_base_1.Feature {
@ -16,20 +17,50 @@ class Token extends oak_frontend_base_1.Feature {
super();
this.rwLock = new concurrent_1.RWLock();
}
async loginByPassword(mobile, password) {
async loginByPassword(mobile, password, scene) {
await this.rwLock.acquire('X');
this.token = await this.getAspectProxy().loginByPassword({ password, mobile });
this.rwLock.release();
try {
this.token = await this.getAspectProxy().loginByPassword({ password, mobile }, scene);
this.rwLock.release();
}
catch (err) {
this.rwLock.release();
throw err;
}
}
async loginWechatMp(code, env) {
async loginWechatMp(scene) {
await this.rwLock.acquire('X');
this.token = await this.getAspectProxy().loginWechatMp({
code,
env,
});
this.rwLock.release();
try {
const { code } = await wx.login();
const env = await wx.getSystemInfo();
const env2 = (0, lodash_1.pick)(env, [
'brand',
'model',
'pixelRatio',
'screenWidth',
'screenHeight',
'windowWidth',
'windowHeight',
'statusBarHeight',
'language',
'version',
'system',
'platform',
'fontSizeSetting',
'SDKVersion'
]);
this.token = await this.getAspectProxy().loginWechatMp({
code,
env: Object.assign(env2, { type: 'wechatMp' }),
}, scene);
this.rwLock.release();
}
catch (err) {
this.rwLock.release();
throw err;
}
}
async syncUserInfoWechatMp() {
async syncUserInfoWechatMp(scene) {
const info = await wx.getUserProfile({
desc: '同步微信昵称和头像信息',
});
@ -40,16 +71,22 @@ class Token extends oak_frontend_base_1.Feature {
encryptedData,
signature,
iv,
});
}, scene);
}
async logout() {
this.token = undefined;
}
async getToken() {
await this.rwLock.acquire('S');
const token = this.token;
this.rwLock.release();
return token;
try {
const token = this.token;
this.rwLock.release();
return token;
}
catch (err) {
this.rwLock.release();
throw err;
}
}
}
__decorate([

View File

@ -1,3 +1,4 @@
import { EntityDict as BaseEntityDict } from 'oak-app-domain/EntityDict';
import { Trigger } from 'oak-domain/lib/types';
declare const _default: (Trigger<EntityDict, "address", import("..").GeneralRuntimeContext<EntityDict>> | Trigger<EntityDict, "user", import("..").GeneralRuntimeContext<EntityDict>>)[];
declare const _default: (Trigger<BaseEntityDict, "address", import("..").GeneralRuntimeContext<BaseEntityDict>> | Trigger<BaseEntityDict, "user", import("..").GeneralRuntimeContext<BaseEntityDict>>)[];
export default _default;

View File

@ -4,11 +4,23 @@ const constants_1 = require("../constants");
let NO_ANY_USER = true;
const triggers = [
{
name: '系统生成的第一个用户默认注册为root',
name: '系统生成的第一个用户默认注册为root用户的初始状态默认为shadow',
entity: 'user',
action: 'create',
when: 'before',
fn: async ({ operation }, context, params) => {
const { data } = operation;
const setDefaultState = (userData) => {
if (!userData.userState) {
userData.userState = 'shadow';
}
};
if (data instanceof Array) {
data.forEach(ele => setDefaultState(ele));
}
else {
setDefaultState(data);
}
if (NO_ANY_USER) {
const { rowStore } = context;
const { result } = await rowStore.select('user', {
@ -24,7 +36,6 @@ const triggers = [
count: 1,
}, context, params);
if (result.length === 0) {
const { data } = operation;
const userData = data instanceof Array ? data[0] : data;
const userRoleData = {
id: await generateNewId(),
@ -48,6 +59,6 @@ const triggers = [
}
return 0;
}
}
},
];
exports.default = triggers;

View File

@ -1,3 +1,3 @@
import { OpSchema as ExtraFile } from '../base-app-domain/ExtraFile/Schema';
export declare function composeFileUrl(extraFile: ExtraFile): any;
export declare function composeFileUrl(extraFile: ExtraFile): string;
export declare function decomposeFileUrl(url: string): Pick<ExtraFile, 'bucket' | 'filename' | 'origin' | 'type' | 'extra1'>;

View File

@ -2,9 +2,21 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.decomposeFileUrl = exports.composeFileUrl = void 0;
function composeFileUrl(extraFile) {
return ``;
const { type, bucket, filename, origin, extra1 } = extraFile;
if (origin === 'unknown') {
// 未知第三方源
return extra1;
}
throw new Error('not implemented yet');
}
exports.composeFileUrl = composeFileUrl;
function decomposeFileUrl(url) {
return {
origin: 'unknown',
extra1: url,
type: 'file',
filename: '',
bucket: '',
};
}
exports.decomposeFileUrl = decomposeFileUrl;

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"g-btn": "../../UI/g-btn/index",
"g-icon": "../../UI/g-icon/index"
}
}

View File

@ -0,0 +1,26 @@
@import "../../../styles/base.less";
.panel {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 10rpx;
}
.btn-container {
padding: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.btn-icon {
color: @primary-color;
}
.btn-label {
color: @primary-color;
font-size: 24rpx;
}

View File

@ -0,0 +1,40 @@
Component({
properties: {
actions: Array,
actionDescriptions: Object,
},
methods: {
onClick(touch: WechatMiniprogram.Touch) {
const { index } = touch.currentTarget.dataset;
const { actions } = this.data;
const action = actions[index];
this.triggerEvent('click', { action });
}
},
observers: {
actions: function (actions) {
const { actionDescriptions } = this.data;
const actionss = actions.map(
(action: string) => actionDescriptions[action]
);
this.setData({ actionss });
},
},
lifetimes: {
ready() {
const { actions, actionDescriptions } = this.data;
const actionss = actions.map(
action => actionDescriptions[action]
);
this.setData({ actionss });
}
}
});

View File

@ -0,0 +1,6 @@
<view class="panel">
<view class="btn-container" wx:for="{{actionss}}" wx:key="index" bind:tap="onClick" data-index="{{index}}">
<g-icon class="btn-icon" size="64" family="{{item.icon.family}}" name="{{item.icon.name}}" />
<text class="btn-label">{{item.label}}</text>
</view>
</view>

View File

@ -0,0 +1,78 @@
"use strict";
Component({
properties: {
// default, primary, ghost, info, success, warning, error
type: {
type: String,
value: '',
},
inline: {
type: Boolean,
value: false
},
// default, large, small
size: {
type: String,
value: '',
},
// circle, square
shape: {
type: String,
value: 'square'
},
disabled: {
type: Boolean,
value: false,
},
loading: {
type: Boolean,
value: false,
},
long: {
type: Boolean,
value: false
},
openType: String,
appParameter: String,
hoverStopPropagation: Boolean,
hoverStartTime: {
type: Number,
value: 20
},
hoverStayTime: {
type: Number,
value: 70
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
},
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: Boolean
},
methods: {
handleTap() {
if (this.data.disabled)
return false;
this.triggerEvent('click');
},
bindgetuserinfo({ detail = {} } = {}) {
this.triggerEvent('getuserinfo', detail);
},
bindcontact({ detail = {} } = {}) {
this.triggerEvent('contact', detail);
},
bindgetphonenumber({ detail = {} } = {}) {
this.triggerEvent('getphonenumber', detail);
},
binderror({ detail = {} } = {}) {
this.triggerEvent('error', detail);
}
}
});

View File

View File

@ -0,0 +1,20 @@
"use strict";
Component({
properties: {
name: String,
color: {
type: String,
value: '#3963bc'
},
size: {
type: String,
value: '44'
},
},
ready: function () {
if (!this.properties.name) {
console.error('请传入Icon组件的name属性');
}
},
methods: {}
});

View File

@ -0,0 +1,56 @@
"use strict";
Component({
behaviors: ['wx://form-field'],
properties: {
title: {
type: String
},
// text || textarea || password || number
type: {
type: String,
value: 'text'
},
disabled: {
type: Boolean,
value: false
},
placeholder: {
type: String,
value: ''
},
focus: {
type: Boolean,
value: false
},
mode: {
type: String,
value: 'normal'
},
right: {
type: Boolean,
value: false
},
error: {
type: Boolean,
value: false
},
maxlength: {
type: Number,
value: 140,
}
},
methods: {
handleInputChange(event) {
const { detail } = event;
const { value } = detail;
this.setData({ value });
this.triggerEvent('change', event.detail);
},
handleInputFocus(event) {
this.triggerEvent('focus', event.detail);
},
handleInputBlur(event) {
this.triggerEvent('blur', event.detail);
}
}
});

View File

@ -0,0 +1,8 @@
"use strict";
// index.ts
OakComponent({
entity: 'area',
formData: async ([area]) => ({
name: area.name,
}),
}, {});

View File

@ -0,0 +1,43 @@
"use strict";
// index.ts
OakPage({
path: 'address:list',
entity: 'address',
projection: {
id: 1,
name: 1,
phone: 1,
detail: 1,
area: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
},
},
},
},
isList: true,
formData: async (addresses) => ({
addresses: addresses.map((address) => ({
name: address?.name,
phone: address?.phone,
districtName: address?.area?.name,
areaText: address?.area && `${address?.area?.parent?.parent?.name}${address?.area?.parent?.name}${address?.area?.name}`,
detail: address?.detail,
})),
}),
}, {
methods: {
goNewAddress() {
this.data.a;
this.navigateTo({
url: '../upsert/index',
});
}
}
});

View File

@ -0,0 +1,55 @@
"use strict";
OakPage({
path: 'address:upsert',
entity: 'address',
projection: {
id: 1,
name: 1,
phone: 1,
detail: 1,
area: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
parent: {
id: 1,
name: 1,
},
},
},
},
isList: false,
formData: async ([address]) => ({
name: address?.name,
phone: address?.phone,
// areaName: `${address?.area?.parent.parent.name}${address?.area?.parent.name}${address?.area?.name}`,
// provinceName: address?.area?.parent.parent.name,
districtName: address?.area?.name,
area: address?.area,
areaText: address?.area && `${address?.area?.parent?.parent?.name}${address?.area?.parent?.name}${address?.area?.name}`,
detail: address?.detail,
}),
}, {
methods: {
setValue(input) {
const { target, detail } = input;
const { dataset: { attr } } = target;
const { value } = detail;
this.setUpdateData(attr, value);
},
callAreaPicker() {
this.callPicker('area', {
depth: 3,
});
},
async confirm() {
await this.execute(this.data.oakId ? 'update' : 'create', () => {
if (this.data.oakFrom === 'address:list') {
wx.navigateBack();
}
});
}
}
});

View File

@ -0,0 +1,6 @@
"use strict";
Page({
handleClick() {
console.log('btn');
}
});

View File

@ -0,0 +1,15 @@
"use strict";
Page({
data: {
value1: '',
value2: '',
value3: '',
value4: '输入框已禁用',
value5: '',
value6: '',
value7: ''
},
changeValue(e) {
console.log(e);
}
});

View File

@ -0,0 +1,7 @@
"use strict";
Page({
navigateToCpnPage(e) {
const pagename = e.currentTarget.dataset.value;
wx.navigateTo({ url: `../g-${pagename}/index` });
}
});

View File

@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
OakPage({
path: 'mobile:me',
entity: 'mobile',
isList: true,
projection: {
id: 1,
mobile: 1,
userId: 1,
},
formData: async (mobiles) => ({
mobiles,
}),
}, {
methods: {
async onRefreshMobile(e) {
this.setData({
refreshing: true,
});
try {
console.log(e.detail.code);
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
}
}
});

View File

@ -0,0 +1,40 @@
"use strict";
OakPage({
path: 'area:picker',
entity: 'area',
projection: {
id: 1,
name: 1,
depth: 1,
level: 1,
},
filters: [
{
parent: {
level: 'country',
},
}
],
isList: true,
formData: async (arealist) => ({
arealist,
}),
}, {
properties: {
depth: Number,
},
methods: {
onItemClicked(options) {
const item = (this.data.arealist).find((ele) => ele.id === options.currentTarget.dataset.id);
const { depth, id } = item;
if (depth !== this.data.depth) {
this.setFilters([{
parentId: id,
}]);
}
else {
this.setForeignKey(id);
}
}
}
});

View File

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
OakPage({
path: 'token:login',
entity: 'token',
projection: {
id: 1,
wechatUser: {
id: 1,
},
userId: 1,
playerId: 1,
},
isList: true,
formData: async (tokenList, features) => {
const tokenValue = await features.token.getToken();
if (tokenValue) {
return {
loggedIn: true,
};
}
return {
loggedIn: false,
};
},
}, {
methods: {
async onLoginClicked(options) {
const { code } = await wx.login();
const env = await wx.getSystemInfo();
await this.features.token.loginWechatMp('token:login');
},
onReturnClicked() {
wx.navigateBack();
}
}
});

View File

@ -0,0 +1,117 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../../../../src/constants");
const extraFile_1 = require("../../../../src/utils/extraFile");
OakPage({
path: 'token:me',
entity: 'token',
isList: true,
projection: {
id: 1,
userId: 1,
playerId: 1,
user: {
id: 1,
nickname: 1,
name: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
player: {
id: 1,
userRole$user: {
$entity: 'userRole',
data: {
id: 1,
userId: 1,
roleId: 1,
}
},
}
},
formData: async ([token]) => {
const user = token?.user;
const player = token?.player;
const avatarFile = user && user.extraFile$entity && user.extraFile$entity[0];
const avatar = avatarFile && (0, extraFile_1.composeFileUrl)(avatarFile);
const nickname = user && user.nickname;
const mobileData = user && user.mobile$user && user.mobile$user[0];
const { mobile } = mobileData || {};
const mobileCount = user?.mobile$user?.length || 0;
const isLoggedIn = !!token;
const isPlayingAnother = token && token.userId !== token.playerId;
const isRoot = player?.userRole$user && player.userRole$user[0].roleId === constants_1.ROOT_ROLE_ID;
return {
avatar,
nickname,
mobile,
mobileCount,
isLoggedIn,
isPlayingAnother,
isRoot,
};
},
}, {
methods: {
async onRefresh() {
this.setData({
refreshing: true,
});
try {
await this.features.token.syncUserInfoWechatMp('token:me');
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
},
async doLogin() {
this.setData({
refreshing: true,
});
try {
await this.features.token.loginWechatMp('token:me');
}
catch (err) {
console.error(err);
}
this.setData({
refreshing: false,
});
},
goMyMobile() {
this.navigateTo({
url: '../../mobile/me/index',
});
},
goUserManage() {
this.navigateTo({
url: '../../user/manage/index',
});
}
}
});

View File

@ -0,0 +1,57 @@
"use strict";
// index.ts
Object.defineProperty(exports, "__esModule", { value: true });
const extraFile_1 = require("../../../../../src/utils/extraFile");
OakPage({
path: 'user:manage:detail',
entity: 'user',
projection: {
id: 1,
nickname: 1,
name: 1,
userState: 1,
idState: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
isList: false,
formData: async ([user]) => {
const { id, nickname, idState, userState, name, mobile$user, extraFile$entity } = user;
const mobile = mobile$user && mobile$user[0]?.mobile;
const avatar = extraFile$entity && extraFile$entity[0] && (0, extraFile_1.composeFileUrl)(extraFile$entity[0]);
return {
id,
nickname,
name,
mobile,
avatar,
userState,
idState,
};
},
actions: ['accept', 'activate', 'disable', 'enable', 'remove', 'update', 'verify'],
}, {
methods: {}
});

View File

@ -1,6 +1,7 @@
{
"navigationBarTitleText": "用户详情",
"usingComponents": {
"g-btn": "../../../../components/UI/g-btn/index"
"g-btn": "../../../../components/UI/g-btn/index",
"action-panel": "../../../../components/Func/action-panel/index"
}
}

View File

@ -63,7 +63,8 @@
height: 200rpx;
width: 200rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.info-panel {

View File

@ -51,7 +51,69 @@ OakPage({
idState,
};
},
actions: ['accept', 'activate', 'disable', 'enable', 'remove', 'update', 'verify'],
}, {
data: {
actionDescriptions: {
accept: {
icon: {
name: 'pan_tool',
},
label: '通过',
},
activate: {
icon: {
name: 'check',
},
label: '激活',
},
disable: {
icon: {
name: 'flash_off',
},
label: '禁用',
},
enable: {
icon: {
name: 'flash_on',
},
label: '启用',
},
remove: {
icon: {
name: 'clear',
},
label: '删除',
},
update: {
icon: {
name: 'edit',
},
label: '更新',
},
verify: {
icon: {
name: 'how_to_reg',
},
label: '验证',
}
}
},
methods: {
onActionClick({ detail }: WechatMiniprogram.CustomEvent) {
const { action } = detail;
switch (action) {
case 'update': {
this.navigateTo({
url: '../upsert/index',
oakId: this.data.oakId,
});
break;
}
default: {
console.error(`尚未实现的action: ${action}`)
}
}
}
}
});

View File

@ -46,4 +46,11 @@
</view>
</view>
</view>
<view style="flex:1" />
<action-panel
style="align-self:stretch"
actions="{{oakLegalActions}}"
actionDescriptions="{{actionDescriptions}}"
bind:click="onActionClick"
/>
</view>

View File

@ -0,0 +1,72 @@
"use strict";
// index.ts
Object.defineProperty(exports, "__esModule", { value: true });
const extraFile_1 = require("../../../../src/utils/extraFile");
OakPage({
path: 'user:manage',
entity: 'user',
projection: {
id: 1,
nickname: 1,
name: 1,
userState: 1,
extraFile$entity: {
$entity: 'extraFile',
data: {
id: 1,
tag1: 1,
origin: 1,
bucket: 1,
objectId: 1,
filename: 1,
extra1: 1,
},
filter: {
tag1: 'avatar',
},
indexFrom: 0,
count: 1,
},
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
mobile: 1,
},
},
},
isList: true,
formData: async (users) => {
const userData = users.map((user) => {
const { id, nickname, userState, name, mobile$user, extraFile$entity } = user;
const mobile = mobile$user && mobile$user[0]?.mobile;
const avatar = extraFile$entity && extraFile$entity[0] && (0, extraFile_1.composeFileUrl)(extraFile$entity[0]);
return {
id,
nickname,
name,
mobile,
avatar,
userState,
};
});
return {
userData,
};
},
}, {
methods: {
goUserManageDetail(options) {
const { id } = options.currentTarget.dataset;
this.navigateTo({
url: 'detail/index',
oakId: id,
});
},
goNewUser() {
this.navigateTo({
url: 'upsert/index',
});
},
}
});

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const GenderOptions = [
{
value: 'male', label: '男',
},
{
value: 'female', label: '女',
}
];
const IDCardTypeOptions = [
{
value: 'ID-Card', label: '身份证',
},
{
value: 'passport', label: '护照',
},
{
value: 'Mainland-passport', label: '港澳通行证',
}
];
OakPage({
path: 'user:manage:upsert',
entity: 'user',
projection: {
id: 1,
name: 1,
nickname: 1,
birth: 1,
gender: 1,
avatar: 1,
idCardType: 1,
idNumber: 1,
},
isList: false,
formData: async ([user]) => {
const { birth, gender, idCardType } = user || {};
const birthText = birth && (new Date(birth)).toLocaleDateString();
const GenderDict = {
male: '男',
female: '女',
};
const genderText = gender && GenderDict[gender];
const genderIndex = gender && GenderOptions.find(ele => ele.value === gender);
const IdCardTypeDict = {
'ID-Card': '身份证',
'passport': '护照',
'Mainland-passport': '港澳通行证',
};
const idCardTypeText = idCardType && IdCardTypeDict[idCardType];
const idCardTypeIndex = idCardType && IDCardTypeOptions.find(ele => ele.value === gender);
const now = new Date();
return (0, lodash_1.assign)({}, user, {
birthText,
genderText,
idCardTypeText,
oldestBirthday: `${now.getFullYear() - 120}-01-01`,
today: `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`,
genderIndex,
idCardTypeIndex,
});
},
}, {
data: {
GenderOptions,
IDCardTypeOptions,
},
methods: {
setValue(input) {
const { target, detail } = input;
const { dataset: { attr } } = target;
const { value } = detail;
this.setUpdateData(attr, value);
},
onBirthChange(e) {
const { value } = e.detail;
const birth = new Date(value);
birth.setHours(0);
birth.setMinutes(0);
birth.setSeconds(0);
birth.setMilliseconds(0);
this.setUpdateData('birth', birth);
},
onGenderChange(e) {
const { value } = e.detail;
this.setUpdateData('gender', GenderOptions[value].value);
},
onIdCardTypeChange(e) {
const { value } = e.detail;
this.setUpdateData('idCardType', IDCardTypeOptions[value].value);
},
async confirm() {
await this.execute(this.data.oakId ? 'update' : 'create', () => {
if (this.data.oakFrom === 'user:manage:list') {
wx.navigateBack();
}
});
}
}
});