pages修改

This commit is contained in:
qsc 2023-11-11 11:47:11 +08:00
parent 6062a4a3c4
commit 8d14063f2c
86 changed files with 1550 additions and 1356 deletions

View File

@ -9,7 +9,7 @@ import Styles from './web.pc.module.less';
import WechatMenu from '../../wechatMenu';
import UserWechatPublicTag from '../../userWechatPublicTag';
import WechatPublicTag from '../..//wechatPublicTag/list';
import WechatPublicAutoReply from '../..//wechatPublicAutoReply';
import WechatPublicAutoReply from '../../wechatPublicAutoReply';
export default function Render(props) {
const { id, config, oakFullpath, name, style, type } = props.data;
const { t, update } = props.methods;

View File

@ -0,0 +1,4 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../../oak-app-domain").EntityDict, "subscription", false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,11 @@
import { WechatPublicConfig } from '../../../../oak-app-domain/Application/Schema';
import { EntityDict } from '../../../../oak-app-domain';
import { WebComponentProps } from 'oak-frontend-base';
type Config = WechatPublicConfig;
export default function render(props: WebComponentProps<EntityDict, 'application', false, {
name: string;
description: string;
oakId: string;
config: Config;
}, {}>): import("react/jsx-runtime").JSX.Element;
export {};

View File

@ -0,0 +1,7 @@
import { jsx as _jsx } from "react/jsx-runtime";
import ConfigUpsert from '../../../../components/config/application';
import Style from './web.module.less';
export default function render(props) {
const { oakId, config, name } = props.data;
return (_jsx("div", { className: Style.container, children: _jsx(ConfigUpsert, { isService: false, type: "wechatPublic", config: config, entity: "subscription", entityId: oakId, name: name }) }));
}

View File

@ -0,0 +1,4 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "subscription", false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,16 @@
import { WechatPublicConfig } from '../../../oak-app-domain/Application/Schema';
import { EntityDict } from '../../../oak-app-domain';
import { WebComponentProps } from 'oak-frontend-base';
type Config = WechatPublicConfig;
export default function Render(props: WebComponentProps<EntityDict, 'subscription', false, {
name: string;
description: string;
oakId: string;
config: Config;
entity: string;
entityId: string;
tabValue: 'detail';
}, {
onTabClick: (key: string) => void;
}>): import("react/jsx-runtime").JSX.Element;
export {};

View File

@ -0,0 +1,14 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Tabs, Card, Descriptions, Typography } from 'antd';
import Style from './web.module.less';
export default function Render(props) {
const { oakId, tabValue, config, name, description, entity, entityId } = props.data;
const { t, navigateBack, onTabClick } = props.methods;
return (_jsx("div", { className: Style.container, children: _jsx(Card, { title: name, bordered: false, children: _jsx(Tabs, { items: [
{
label: '订阅号概览',
key: 'detail',
children: (_jsxs(Descriptions, { column: 1, bordered: true, children: [_jsx(Descriptions.Item, { label: "id", children: _jsx(Typography.Paragraph, { copyable: true, children: oakId }) }), _jsx(Descriptions.Item, { label: t('subscription:attr.name'), children: name }), _jsx(Descriptions.Item, { label: t('subscription:attr.description'), children: description })] })),
},
] }) }) }));
}

View File

@ -0,0 +1,9 @@
import { EntityDict } from '../../../oak-app-domain';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
import { ReactComponentProps } from 'oak-frontend-base';
declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(props: ReactComponentProps<ED2, T2, true, {
entityId: string;
entity: keyof ED2;
variant?: "dialog" | "inline" | "alone" | undefined;
}>) => React.ReactElement;
export default _default;

View File

@ -0,0 +1,67 @@
export default OakComponent({
isList: true,
entity: 'subscription',
projection: {
id: 1,
name: 1,
description: 1,
config: 1,
entity: 1,
entityId: 1,
},
properties: {
entityId: '',
entity: '',
variant: 'inline',
},
filters: [
{
filter() {
return {
entityId: this.props.entityId,
entity: this.props.entity,
};
},
},
],
formData({ data }) {
return {
list: data,
};
},
data: {
open: false,
},
methods: {
goDetail(id) {
this.navigateTo({
url: '/subscription/detail',
oakId: id,
});
},
goUpdate(id) {
this.navigateTo({
url: '/subscription/upsert',
oakId: id,
});
},
goSetConfig(id) {
this.navigateTo({
url: '/subscription/config/upsert',
oakId: id,
});
},
goCreate() {
const { entityId, entity } = this.props;
this.navigateTo({
url: '/subscription/upsert',
entityId,
entity,
});
},
remove(id) {
this.removeItem(id);
this.execute();
},
},
});

View File

@ -0,0 +1,14 @@
import { EntityDict } from '../../../oak-app-domain';
import { WebComponentProps } from 'oak-frontend-base';
export default function Render(props: WebComponentProps<EntityDict, 'subscription', true, {
searchValue: string;
list: EntityDict['subscription']['Schema'][];
showBack: boolean;
variant?: 'inline' | 'alone' | 'dialog';
}, {
goDetail: (id: string) => void;
goCreate: () => void;
goSetConfig: (id: string) => void;
goUpdate: (id: string) => void;
remove: (id: string) => void;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,79 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Table, Button, Space, Typography } from 'antd';
import PageHeader from '../../../components/common/pageHeader';
import Style from './web.module.less';
export default function Render(props) {
const { oakPagination, list = [], oakLoading, showBack, variant, oakFullpath, } = props.data;
const { pageSize, total, currentPage } = oakPagination || {};
const { t, setPageSize, setCurrentPage, goCreate, goDetail, goSetConfig, goUpdate, remove, } = props.methods;
return (_jsxs(Container, { variant: variant, children: [_jsx(Space, { style: { marginBottom: 16 }, children: _jsx(Button, { type: "primary", onClick: () => {
goCreate();
}, children: "\u6DFB\u52A0\u8BA2\u9605\u53F7" }) }), _jsx(Table, { loading: oakLoading, dataSource: list, rowKey: "id", columns: [
// {
// dataIndex: 'id',
// title: '序号',
// render: (value, record, index) => {
// return index + 1;
// },
// },
{
dataIndex: 'name',
title: '订阅号名称',
width: 300,
render: (value, record, index) => {
return (_jsx(Typography.Link, { onClick: () => {
goDetail(record.id);
}, children: value }));
},
},
{
dataIndex: 'description',
title: '描述',
width: 200,
ellipsis: true,
},
{
dataIndex: 'config',
title: '配置',
align: 'center',
render: (value, record, index) => {
return (_jsx(_Fragment, { children: _jsx(Button, { type: "link", onClick: () => {
goSetConfig(record.id);
}, children: "\u914D\u7F6E" }) }));
},
},
{
dataIndex: 'op',
width: 200,
title: '操作',
align: 'center',
render: (value, record, index) => {
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "link", onClick: () => {
goDetail(record.id);
}, children: "\u8BE6\u60C5" }), _jsx(Button, { type: "link", onClick: () => {
goUpdate(record.id);
}, children: "\u66F4\u65B0" }), _jsx(Button, { type: "link", onClick: () => {
remove(record.id);
}, children: "\u5220\u9664" })] }));
},
fixed: 'right',
},
], pagination: {
total,
pageSize,
current: currentPage,
onShowSizeChange: (pageSize) => {
setPageSize(pageSize);
},
onChange: (current) => {
setCurrentPage(current);
},
} })] }));
}
function Container(props) {
const { children, variant = 'alone', showBack } = props;
if (['inline', 'dialog'].includes(variant)) {
return _jsx(_Fragment, { children: children });
}
return (_jsx(PageHeader, { showBack: showBack, title: "\u5E94\u7528\u7BA1\u7406", children: _jsx("div", { className: Style.container, children: children }) }));
}

View File

@ -0,0 +1,7 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain/EntityDict';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "subscription", false, {
entityId: string;
entity: keyof EntityDict;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,38 @@
export default OakComponent({
isList: false,
entity: 'subscription',
projection: {
id: 1,
name: 1,
config: 1,
description: 1,
entity: 1,
entityId: 1,
},
formData({ data }) {
return data || {};
},
properties: {
entityId: '',
entity: '',
},
lifetimes: {
ready() {
const { entityId, entity, oakId } = this.props;
if (!oakId) {
if (entityId) {
this.update({
entityId,
entity,
});
}
}
},
},
methods: {
async confirm() {
await this.execute();
this.navigateBack();
},
},
});

View File

@ -0,0 +1,13 @@
import { EntityDict } from '../../../oak-app-domain';
import { WebComponentProps } from 'oak-frontend-base';
export default function Render(props: WebComponentProps<EntityDict, 'subscription', false, {
name: string;
description: string;
variant: 'inline' | 'alone' | 'dialog';
showBack: boolean;
entity: string;
entityId: string;
oakId: string;
}, {
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,38 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Button, Form, Row, Col, Space, Input } from 'antd';
import Style from './web.module.less';
export default function Render(props) {
const { name, description, variant, showBack = true, entityId, entity, oakId, } = props.data;
const { t, update, navigateBack, confirm } = props.methods;
return (_jsx(Container, { variant: variant, showBack: showBack, children: _jsx(Row, { children: _jsx(Col, { xs: 24, sm: 12, children: _jsxs(Form, { colon: true, labelCol: { span: 6 }, wrapperCol: { span: 16 }, children: [_jsx(Form.Item, { label: "\u540D\u79F0", required: true, name: "name", rules: [
{
required: true,
},
], children: _jsx(_Fragment, { children: _jsx(Input, { onChange: (e) => {
update({
name: e.target.value,
});
}, value: name }) }) }), _jsx(Form.Item, { label: "\u63CF\u8FF0", required: true, name: "description", children: _jsx(_Fragment, { children: _jsx(Input.TextArea, { onChange: (e) => {
update({
description: e.target.value,
});
}, value: description }) }) }), _jsx(Action, { variant: variant, children: _jsx(Form.Item, { wrapperCol: { offset: 6 }, children: _jsxs(Space, { children: [_jsx(Button, { type: "primary", onClick: () => {
confirm();
}, children: "\u786E\u5B9A" }), _jsx(Button, { onClick: () => {
navigateBack();
}, children: "\u8FD4\u56DE" })] }) }) })] }) }) }) }));
}
function Action(props) {
const { children, variant } = props;
if (variant === 'dialog') {
return null;
}
return (_jsx(_Fragment, { children: children }));
}
function Container(props) {
const { children, variant, showBack } = props;
if (variant === 'inline' || variant === 'dialog') {
return _jsx(_Fragment, { children: children });
}
return (_jsx("div", { className: Style.container, children: children }));
}

View File

@ -1,8 +1,4 @@
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, true, {
areaId: string | null | undefined;
onCancel: (() => void) | undefined;
onConfirm: ((stationIds: string[]) => void) | undefined;
selectIds: string[] | undefined;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "subway", true, {}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -1,9 +1,74 @@
import { pull } from "oak-domain/lib/utils/lodash";
export default OakComponent({
entity: 'subway',
projection: {
id: 1,
name: 1,
areaId: 1,
subwayStation$subway: {
$entity: 'subwayStation',
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
}
}
}
},
pagination: {
currentPage: 1,
pageSize: 100,
more: true,
},
isList: true,
data: {
areaId: '330100',
areaOptions: [],
},
properties: {},
filters: [
{
filter() {
return {
areaId: '330100'
};
},
'#name': 'area',
},
// {
// filter() {
// return {
// };
// },
// '#name': 'type',
// },
],
listeners: {},
formData: ({ data: subway }) => {
const treeData = subway
// ?.filter((ele) => !ele!.subwayStation$subway)
.map((ele) => {
return {
title: ele.name,
key: ele.id,
isLeaf: false,
children: ele.subwayStation$subway
.map((ele2) => ({
title: ele2.station.name,
key: `${ele.id}/${ele2.station.id}`,
isLeaf: true,
})) || [],
};
});
return {
treeData,
};
},
lifetimes: {
async ready() {
const { data: areas } = await this.features.cache.refresh('area', {
const { data: area } = await this.features.cache.refresh('area', {
data: {
id: 1,
name: 1,
@ -14,115 +79,28 @@ export default OakComponent({
level: 'city',
},
});
const areaId = this.props.areaId || areas[0].id;
const { data: subways } = await this.features.cache.refresh('subway', {
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
});
this.setState({
areas,
subways,
subwayId: subways[0]?.id,
});
this.getStations(subways[0]?.id);
},
},
data: {
open: false,
stationIds: [],
},
properties: {
areaId: '',
onCancel: undefined,
onConfirm: undefined,
selectIds: [],
},
methods: {
setAeraId(areaId) {
this.setState({
areaId,
});
},
setCheckedList(value, flag) {
const { stationIds } = this.state;
if (flag) {
this.setState({
stationIds: stationIds.concat(value),
});
// stationIds.push(value);
}
else {
var index = stationIds.indexOf(value);
// stationIds.splice(index, 1);
this.setState({
stationIds: pull(stationIds, value),
});
}
},
async getSubways(areaId) {
this.setState({
areaId,
});
const { data: subways } = await this.features.cache.refresh('subway', {
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
});
this.getStations(subways[0].id);
this.setState({
subways,
});
},
async getStations(subwayId) {
this.setState({
subwayId,
});
const { data: subwayStations } = await this.features.cache.refresh('subwayStation', {
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
},
},
filter: {
subwayId,
},
});
const stations = subwayStations?.map((ele) => ({
label: ele.station.name,
value: ele.station.id,
const areaOptions = area?.map((ele) => ({
label: ele.name,
value: ele.id,
}));
this.setState({
stations,
});
},
cancel() {
this.setState({
stationIds: [],
});
if (this.props.onCancel) {
this.props.onCancel();
}
},
confirm() {
if (this.props.onConfirm) {
this.props.onConfirm(this.state.stationIds);
}
this.setState({
stationIds: [],
areaOptions,
});
},
},
methods: {
setFilterByAreaId(areaId) {
this.addNamedFilter({
filter: {
areaId,
},
'#name': 'area',
}, true);
},
setAreaId(areaId) {
this.setState({
areaId,
});
}
},
});

View File

@ -1,19 +1,14 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(props: WebComponentProps<EntityDict, 'area', true, {
subways: EntityDict['subway']['Schema'][];
areas: EntityDict['area']['Schema'][];
stations: {
import { DataNode } from 'antd/es/tree';
export default function Render(props: WebComponentProps<EntityDict, 'subway', true, {
treeData: DataNode[];
areaId: string;
areaOptions: {
label: string;
value: string;
}[];
areaId: string;
stationIds: string[];
selectIds: string[];
}, {
getStations: (subwayId: string) => void;
getSubways: (areaId: string) => void;
setCheckedList: (station: string, flag: boolean) => void;
cancel: () => void;
confirm: () => void;
setAreaId: (areaId: string) => void;
setFilterByAreaId: (areaId: string) => void;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -1,31 +1,30 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Checkbox, Button, Tabs, Space } from 'antd';
import { useState } from 'react';
import { Button, Space, Tree, Row, Col, Select } from 'antd';
import Style from './web.module.less';
export default function render(props) {
import UpsertSubway from '../upsertSubway';
import UpsertStation from '../upsertStation';
export default function Render(props) {
const { data, methods } = props;
const { t, getStations, getSubways, setCheckedList, cancel, confirm } = methods;
const { subways, stations, areaId, areas, stationIds, selectIds } = data;
return (_jsxs("div", { className: Style.container, children: [_jsx(Tabs, { style: { minHeight: '40vh' }, tabPosition: 'left', type: "card", defaultActiveKey: areaId, onChange: (value) => {
getSubways(value);
}, items: areas?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (_jsx(Tabs, { tabPosition: 'top', onChange: (value) => {
getStations(value);
}, items: subways?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (_jsx(Space, { size: [0, 16], wrap: true, children: stations?.map((ele) => {
return (_jsx(Checkbox, { disabled: selectIds?.includes(ele.value), onChange: (e) => {
setCheckedList(e.target.value, e.target.checked);
}, checked: stationIds
.concat(selectIds || [])
.includes(ele.value), value: ele.value, children: ele.label }));
}) })),
})) })),
})) }), _jsx("div", { style: { textAlign: 'center', marginTop: 16 }, children: _jsxs(Space, { children: [_jsx(Button, { onClick: () => {
cancel();
}, children: "\u53D6\u6D88" }), _jsx(Button, { type: "primary", onClick: async () => {
confirm();
}, children: "\u786E\u5B9A" })] }) })] }));
const { oakFullpath, treeData, areaOptions, areaId } = data;
const { t, setAreaId, setFilterByAreaId } = methods;
const [openSubway, setSubway] = useState(false);
const [openStation, setStation] = useState(false);
const [subwayId, setSubwayId] = useState('');
const [stationId, setStationId] = useState('');
return (_jsxs("div", { className: Style.container, children: [_jsxs("div", { children: ["\u70B9\u51FB\u5207\u6362\u57CE\u5E02\uFF1A", _jsx(Select, { placeholder: '切换城市', value: areaId, onChange: (value) => {
setAreaId(value);
setFilterByAreaId(value);
}, style: { width: '20%' }, options: areaOptions, allowClear: true })] }), _jsx(Tree, { className: Style.tree, blockNode: true, treeData: treeData, titleRender: (nodeData) => {
return (_jsxs(Row, { align: "middle", style: { flex: 1 }, children: [_jsx(Col, { flex: "auto", children: nodeData.title }), _jsx(Col, { flex: "none", children: _jsx(Space, { children: !nodeData.isLeaf ? _jsx(Button, { onClick: () => {
setSubwayId(nodeData.key);
setSubway(true);
}, children: "\u7F16\u8F91" }) :
_jsx(Button, { onClick: () => {
const index = nodeData.key.indexOf('/') + 1;
const temp = nodeData.key.substr(index);
setStationId(temp);
setStation(true);
}, children: "\u7F16\u8F91" }) }) })] }));
} }), openSubway && (_jsx(UpsertSubway, { onClose: () => setSubway(false), openSubway: openSubway, oakId: subwayId, oakPath: `${oakFullpath}.${subwayId}`, oakAutoUnmount: true })), openStation && (_jsx(UpsertStation, { onClose: () => setStation(false), openStation: openStation, oakId: stationId, subwayId: subwayId, oakPath: `$subwayLine/upsertStation,${stationId}`, oakAutoUnmount: true }))] }));
}

View File

@ -2,4 +2,21 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}
.space {
margin-bottom: 15px;
}
.tree {
:global {
.ant-tree-title {
display: flex;
flex: 1;
}
}
}

View File

@ -0,0 +1,8 @@
/// <reference types="react" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, keyof import("../../../oak-app-domain").EntityDict, true, {
areaId: string | null | undefined;
onCancel: (() => void) | undefined;
onConfirm: ((stationIds: string[]) => void) | undefined;
selectIds: string[] | undefined;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,128 @@
import { pull } from "oak-domain/lib/utils/lodash";
export default OakComponent({
isList: true,
lifetimes: {
async ready() {
const { data: areas } = await this.features.cache.refresh('area', {
data: {
id: 1,
name: 1,
level: 1,
},
filter: {
subway$area: {},
level: 'city',
},
});
const areaId = this.props.areaId || areas[0].id;
const { data: subways } = await this.features.cache.refresh('subway', {
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
});
this.setState({
areas,
subways,
subwayId: subways[0]?.id,
});
this.getStations(subways[0]?.id);
},
},
data: {
open: false,
stationIds: [],
},
properties: {
areaId: '',
onCancel: undefined,
onConfirm: undefined,
selectIds: [],
},
methods: {
setAeraId(areaId) {
this.setState({
areaId,
});
},
setCheckedList(value, flag) {
const { stationIds } = this.state;
if (flag) {
this.setState({
stationIds: stationIds.concat(value),
});
// stationIds.push(value);
}
else {
var index = stationIds.indexOf(value);
// stationIds.splice(index, 1);
this.setState({
stationIds: pull(stationIds, value),
});
}
},
async getSubways(areaId) {
this.setState({
areaId,
});
const { data: subways } = await this.features.cache.refresh('subway', {
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
});
this.getStations(subways[0].id);
this.setState({
subways,
});
},
async getStations(subwayId) {
this.setState({
subwayId,
});
const { data: subwayStations } = await this.features.cache.refresh('subwayStation', {
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
},
},
filter: {
subwayId,
},
});
const stations = subwayStations?.map((ele) => ({
label: ele.station.name,
value: ele.station.id,
}));
this.setState({
stations,
});
},
cancel() {
this.setState({
stationIds: [],
});
if (this.props.onCancel) {
this.props.onCancel();
}
},
confirm() {
if (this.props.onConfirm) {
this.props.onConfirm(this.state.stationIds);
}
this.setState({
stationIds: [],
});
},
},
});

View File

@ -0,0 +1,19 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(props: WebComponentProps<EntityDict, 'area', true, {
subways: EntityDict['subway']['Schema'][];
areas: EntityDict['area']['Schema'][];
stations: {
label: string;
value: string;
}[];
areaId: string;
stationIds: string[];
selectIds: string[];
}, {
getStations: (subwayId: string) => void;
getSubways: (areaId: string) => void;
setCheckedList: (station: string, flag: boolean) => void;
cancel: () => void;
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,31 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Checkbox, Button, Tabs, Space } from 'antd';
import Style from './web.module.less';
export default function render(props) {
const { data, methods } = props;
const { t, getStations, getSubways, setCheckedList, cancel, confirm } = methods;
const { subways, stations, areaId, areas, stationIds, selectIds } = data;
return (_jsxs("div", { className: Style.container, children: [_jsx(Tabs, { style: { minHeight: '40vh' }, tabPosition: 'left', type: "card", defaultActiveKey: areaId, onChange: (value) => {
getSubways(value);
}, items: areas?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (_jsx(Tabs, { tabPosition: 'top', onChange: (value) => {
getStations(value);
}, items: subways?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (_jsx(Space, { size: [0, 16], wrap: true, children: stations?.map((ele) => {
return (_jsx(Checkbox, { disabled: selectIds?.includes(ele.value), onChange: (e) => {
setCheckedList(e.target.value, e.target.checked);
}, checked: stationIds
.concat(selectIds || [])
.includes(ele.value), value: ele.value, children: ele.label }));
}) })),
})) })),
})) }), _jsx("div", { style: { textAlign: 'center', marginTop: 16 }, children: _jsxs(Space, { children: [_jsx(Button, { onClick: () => {
cancel();
}, children: "\u53D6\u6D88" }), _jsx(Button, { type: "primary", onClick: async () => {
confirm();
}, children: "\u786E\u5B9A" })] }) })] }));
}

View File

@ -0,0 +1,5 @@
/** index.wxss **/
.container {
background: var(--oak-bg-color-container);
}

View File

@ -0,0 +1,8 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "station", false, {
openStation: boolean;
onClose: () => void;
subwayId: string;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,25 @@
export default OakComponent({
entity: 'station',
projection: {
id: 1,
name: 1,
},
isList: false,
formData({ data: station, features }) {
return {
id: station?.id,
name: station?.name,
};
},
filters: [],
properties: {
openStation: false,
onClose: () => undefined,
subwayId: '',
},
data: {},
lifetimes: {
async ready() { },
},
methods: {},
});

View File

@ -0,0 +1,9 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'station', false, {
oakId: string;
name: string;
onClose: () => void;
openStation: boolean;
subwayId: string;
}, {}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,18 @@
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { Input, Modal } from 'antd';
export default function Render(props) {
const { methods, data, } = props;
const { t, } = methods;
const { oakFullpath, oakId, name, openStation, onClose, subwayId, } = data;
return (_jsx("div", { children: _jsx(Modal, { title: oakId ? '编辑站点' : '新增站点', open: openStation, destroyOnClose: true, okText: "\u786E\u5B9A", cancelText: "\u53D6\u6D88", onOk: async () => {
// if (!subwayId) {
// methods.update({ subwayId, });
// }
methods.execute();
onClose();
}, onCancel: () => {
onClose();
}, children: _jsx(_Fragment, { children: _jsx(Input, { placeholder: "\u8BF7\u8F93\u5165\u7AD9\u70B9\u540D\u79F0", value: name, onChange: ({ target: { value } }) => {
methods.update({ name: value });
} }) }) }) }));
}

View File

@ -0,0 +1,7 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "subway", false, {
openSubway: boolean;
onClose: () => void;
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
export default _default;

View File

@ -0,0 +1,24 @@
export default OakComponent({
entity: 'subway',
projection: {
id: 1,
name: 1,
},
isList: false,
formData({ data: subway, features }) {
return {
id: subway?.id,
name: subway?.name,
};
},
filters: [],
properties: {
openSubway: false,
onClose: () => undefined,
},
data: {},
lifetimes: {
async ready() { },
},
methods: {},
});

View File

@ -0,0 +1,8 @@
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function Render(props: WebComponentProps<EntityDict, 'subway', false, {
oakId: string;
name: string;
onClose: () => void;
openSubway: boolean;
}, {}>): import("react/jsx-runtime").JSX.Element;

View File

@ -0,0 +1,15 @@
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { Input, Modal } from 'antd';
export default function Render(props) {
const { methods, data, } = props;
const { t, } = methods;
const { oakFullpath, oakId, name, openSubway, onClose, } = data;
return (_jsx("div", { children: _jsx(Modal, { title: oakId ? '编辑地铁' : '新增地铁', open: openSubway, destroyOnClose: true, okText: "\u786E\u5B9A", cancelText: "\u53D6\u6D88", onOk: async () => {
methods.execute();
onClose();
}, onCancel: () => {
onClose();
}, children: _jsx(_Fragment, { children: _jsx(Input, { placeholder: "\u8BF7\u8F93\u5165\u7EBF\u8DEF\u540D\u79F0", value: name, onChange: ({ target: { value } }) => {
methods.update({ name: value });
} }) }) }) }));
}

View File

@ -165,6 +165,16 @@ async function createNotification(message, context) {
}
case 'wechatPublic': {
const apps = applications.filter(ele => ele.type === 'wechatPublic');
const [user] = await context.select('user', {
data: {
id: 1,
refId: 1,
},
filter: {
id: userId
}
}, { dontCollect: true });
const userId2 = user.refId ? user.refId : userId;
const wechatUsers = await context.select('wechatUser', {
data: {
id: 1,
@ -173,10 +183,10 @@ async function createNotification(message, context) {
},
filter: {
applicationId: {
$in: apps.map(ele => ele.id),
$in: apps.map((ele) => ele.id),
},
userId,
}
userId: userId2,
},
}, { dontCollect: true });
for (const app of apps) {
// 如果是wechatMp或者wechat还要保证用户已经有openId

View File

@ -170,6 +170,16 @@ async function createNotification(message, context) {
}
case 'wechatPublic': {
const apps = applications.filter(ele => ele.type === 'wechatPublic');
const [user] = await context.select('user', {
data: {
id: 1,
refId: 1,
},
filter: {
id: userId
}
}, { dontCollect: true });
const userId2 = user.refId ? user.refId : userId;
const wechatUsers = await context.select('wechatUser', {
data: {
id: 1,
@ -178,10 +188,10 @@ async function createNotification(message, context) {
},
filter: {
applicationId: {
$in: apps.map(ele => ele.id),
$in: apps.map((ele) => ele.id),
},
userId,
}
userId: userId2,
},
}, { dontCollect: true });
for (const app of apps) {
// 如果是wechatMp或者wechat还要保证用户已经有openId

View File

@ -11,7 +11,7 @@ import Styles from './web.pc.module.less';
import WechatMenu from '../../wechatMenu';
import UserWechatPublicTag from '../../userWechatPublicTag';
import WechatPublicTag from '../..//wechatPublicTag/list';
import WechatPublicAutoReply from '../..//wechatPublicAutoReply';
import WechatPublicAutoReply from '../../wechatPublicAutoReply';
export default function Render(props: WebComponentProps<EntityDict, 'application', false, {
id: string;

View File

@ -0,0 +1,13 @@
export default OakComponent({
isList: false,
entity: 'subscription',
projection: {
id: 1,
name: 1,
config: 1,
},
formData({ data }) {
return data || {};
},
methods: {},
});

View File

@ -27,7 +27,6 @@ export default function render(
) {
const { oakId, config, name } = props.data;
return (
<PageHeader showBack={true} title="订阅号配置">
<div className={Style.container}>
<ConfigUpsert
isService={false}
@ -38,6 +37,5 @@ export default function render(
name={name}
/>
</div>
</PageHeader>
);
}

View File

@ -0,0 +1,16 @@
export default OakComponent({
isList: false,
entity: 'subscription',
projection: {
id: 1,
name: 1,
config: 1,
description: 1,
entity: 1,
entityId: 1,
},
formData({ data }) {
return data || {};
},
methods: {},
});

View File

@ -1,7 +1,6 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}
}

View File

@ -1,6 +1,5 @@
import React from 'react';
import { Tabs, Card, Descriptions, Typography } from 'antd';
import PageHeader from '../../../components/common/pageHeader';
import Style from './web.module.less';
import {
@ -36,7 +35,6 @@ export default function Render(
const { t, navigateBack, onTabClick } = props.methods;
return (
<PageHeader showBack={true} title="订阅号概览">
<div className={Style.container}>
<Card title={name} bordered={false}>
<Tabs
@ -71,6 +69,5 @@ export default function Render(
/>
</Card>
</div>
</PageHeader>
);
}

View File

@ -0,0 +1,6 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}

View File

@ -0,0 +1,6 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}

View File

@ -129,8 +129,6 @@ function Container(props: {
return <>{children}</>;
}
return (
<PageHeader showBack={showBack} title="订阅号编辑">
<div className={Style.container}>{children}</div>
</PageHeader>
);
}

View File

@ -1,140 +1,130 @@
import { pull } from "oak-domain/lib/utils/lodash";
// import { TreeNode } from '@project/types/interface';
import { EntityDict } from '../../../oak-app-domain';
type TreeNode = {
key: string;
title: string;
children?: TreeNode[];
isLeaf?: boolean;
};
export default OakComponent({
isList: true,
lifetimes: {
async ready() {
const { data: areas } = await this.features.cache.refresh('area', {
data: {
entity: 'subway',
projection: {
id: 1,
name: 1,
areaId: 1,
subwayStation$subway: {
$entity: 'subwayStation',
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
level: 1,
},
filter: {
subway$area: {
},
level: 'city',
},
}
}
}
},
pagination: {
currentPage: 1,
pageSize: 100,
more: true,
},
isList: true,
data: {
areaId: '330100' as string,
areaOptions: [] as Array<{ label: string, value: string }>,
},
properties: {},
filters: [
{
filter() {
return {
areaId: '330100'
}
},
'#name': 'area',
},
// {
// filter() {
// return {
// };
// },
// '#name': 'type',
// },
],
listeners: {},
formData: ({ data: subway }) => {
const treeData: TreeNode[] = subway
// ?.filter((ele) => !ele!.subwayStation$subway)
.map((ele) => {
return {
title: ele!.name!,
key: ele!.id!,
isLeaf: false,
children:
ele.subwayStation$subway!
.map((ele2) => ({
title: ele2!.station!.name,
key: `${ele.id}/${ele2!.station!.id}`,
isLeaf: true,
})) || [],
};
});
const areaId = this.props.areaId || areas[0].id;
const { data: subways } = await this.features.cache.refresh(
'subway',
return {
treeData,
};
},
lifetimes: {
async ready() {
const { data: area } = await this.features.cache.refresh(
'area',
{
data: {
id: 1,
name: 1,
level: 1,
},
filter: {
areaId,
subway$area: {
},
level: 'city',
},
}
);
const areaOptions = area?.map(
(ele: any) => ({
label: ele.name,
value: ele.id,
})
)
this.setState({
areas,
subways,
subwayId: subways[0]?.id,
areaOptions,
});
this.getStations(subways[0]?.id!);
},
},
data: {
open: false,
stationIds: [] as string[],
},
properties: {
areaId: '' as string | undefined | null,
onCancel: undefined as (() => void) | undefined,
onConfirm: undefined as ((stationIds: string[]) => void) | undefined,
selectIds: [] as string[] | undefined,
},
methods: {
setAeraId(areaId: string) {
this.setState({
areaId,
});
},
setCheckedList(value: string, flag: boolean) {
const { stationIds } = this.state;
if (flag) {
this.setState({
stationIds: stationIds.concat(value),
});
// stationIds.push(value);
} else {
var index = stationIds.indexOf(value);
// stationIds.splice(index, 1);
this.setState({
stationIds: pull(stationIds, value),
});
}
},
async getSubways(areaId: string) {
this.setState({
areaId,
});
const { data: subways } = await this.features.cache.refresh(
'subway',
setFilterByAreaId(areaId: string) {
this.addNamedFilter(
{
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
}
'#name': 'area',
},
true
);
this.getStations(subways[0]!.id!);
this.setState({
subways,
});
},
async getStations(subwayId: string) {
setAreaId(areaId: string) {
this.setState({
subwayId,
});
const { data: subwayStations } = await this.features.cache.refresh(
'subwayStation',
{
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
},
},
filter: {
subwayId,
},
}
);
const stations = subwayStations?.map((ele: any) => ({
label: ele.station.name,
value: ele.station.id,
}));
this.setState({
stations,
});
},
cancel() {
this.setState({
stationIds: [],
});
if (this.props.onCancel) {
this.props.onCancel();
}
},
confirm() {
if (this.props.onConfirm) {
this.props.onConfirm(this.state.stationIds);
}
this.setState({
stationIds: [],
});
},
areaId,
})
}
},
});

View File

@ -2,4 +2,21 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}
.space {
margin-bottom: 15px;
}
.tree {
:global {
.ant-tree-title {
display: flex;
flex: 1;
}
}
}

View File

@ -1,111 +1,151 @@
import { Checkbox, Button, Col, Tabs, Row, Space } from 'antd';
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
import React, { useState } from 'react';
import { Button, Space, Tree, Row, Col, Tabs, Select } from 'antd';
import Style from './web.module.less';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { DataNode } from 'antd/es/tree'
import UpsertSubway from '../upsertSubway';
import UpsertStation from '../upsertStation';
export default function render(
export default function Render(
props: WebComponentProps<
EntityDict,
'area',
'subway',
true,
{
subways: EntityDict['subway']['Schema'][];
areas: EntityDict['area']['Schema'][];
stations: { label: string; value: string }[];
treeData: DataNode[];
areaId: string;
stationIds: string[];
selectIds: string[];
areaOptions: { label: string; value: string }[];
},
{
getStations: (subwayId: string) => void;
getSubways: (areaId: string) => void;
setCheckedList: (station: string, flag: boolean) => void;
cancel: () => void;
confirm: () => void;
setAreaId: (areaId: string) => void;
setFilterByAreaId: (areaId: string) => void;
}
>
) {
const { data, methods } = props;
const { t, getStations, getSubways, setCheckedList, cancel, confirm } =
methods;
const { subways, stations, areaId, areas, stationIds, selectIds } = data;
const { oakFullpath, treeData, areaOptions, areaId } = data;
const { t, setAreaId, setFilterByAreaId } = methods;
const [openSubway, setSubway] = useState(false);
const [openStation, setStation] = useState(false);
const [subwayId, setSubwayId] = useState('');
const [stationId, setStationId] = useState('');
return (
<div className={Style.container}>
<Tabs
style={{ minHeight: '40vh' }}
tabPosition={'left'}
type="card"
defaultActiveKey={areaId}
onChange={(value) => {
getSubways(value);
}}
items={areas?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (
<Tabs
tabPosition={'top'}
onChange={(value) => {
getStations(value);
}}
items={subways?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (
<Space size={[0, 16]} wrap>
{stations?.map((ele: any) => {
return (
<Checkbox
disabled={selectIds?.includes(
ele.value
)}
onChange={(
e: CheckboxChangeEvent
) => {
setCheckedList(
e.target.value,
e.target.checked
);
}}
checked={stationIds
.concat(selectIds || [])
.includes(ele.value)}
value={ele.value}
>
{ele.label}
</Checkbox>
);
})}
</Space>
),
}))}
></Tabs>
),
}))}
></Tabs>
<div style={{ textAlign: 'center', marginTop: 16 }}>
<Space>
<Button
onClick={() => {
cancel();
}}
>
</Button>
{/* <Space className={Style.space}>
<Button
type="primary"
onClick={async () => {
confirm();
onClick={() => {
goServiceUpsert();
}}
>
</Button>
</Space>
</Space> */}
<div>
<Select
placeholder={'切换城市'}
value={areaId}
onChange={(value) => {
setAreaId(value);
setFilterByAreaId(value);
}}
style={{ width: '20%' }}
options={areaOptions}
allowClear
></Select>
</div>
<Tree
className={Style.tree}
blockNode={true}
treeData={treeData}
titleRender={(nodeData) => {
return (
<Row align="middle" style={{ flex: 1 }}>
<Col flex="auto">
{(nodeData as any).title}
</Col>
<Col flex="none">
<Space>
{!nodeData.isLeaf ? <Button
onClick={() => {
setSubwayId((nodeData as any).key)
setSubway(true)
}
}
>
</Button> :
<Button
onClick={() => {
const index = (nodeData as any).key.indexOf('/') + 1;
const temp = (nodeData as any).key.substr(index);
setStationId(temp)
setStation(true)
}
}
>
</Button>
}
{/* {!nodeData.isLeaf && (
<Button
onClick={() =>
{
setSubwayId((nodeData as any).key)
setStation(true)
}
}
>
</Button>
// <Button
// type="primary"
// onClick={() =>
// goServiceUpsert(
// nodeData!
// .key as string
// )
// }
// >
// 添加站点
// </Button>
)} */}
</Space>
</Col>
</Row>
);
}}
/>
{openSubway && (
<UpsertSubway
onClose={() => setSubway(false)}
openSubway={openSubway}
oakId={subwayId}
oakPath={`${oakFullpath}.${subwayId}`}
oakAutoUnmount={true}
/>
)}
{openStation && (
<UpsertStation
onClose={() => setStation(false)}
openStation={openStation}
oakId={stationId}
subwayId={subwayId}
oakPath={`$subwayLine/upsertStation,${stationId}`}
oakAutoUnmount={true}
/>
)}
</div>
);
}

View File

@ -0,0 +1,140 @@
import { pull } from "oak-domain/lib/utils/lodash";
export default OakComponent({
isList: true,
lifetimes: {
async ready() {
const { data: areas } = await this.features.cache.refresh('area', {
data: {
id: 1,
name: 1,
level: 1,
},
filter: {
subway$area: {
},
level: 'city',
},
});
const areaId = this.props.areaId || areas[0].id;
const { data: subways } = await this.features.cache.refresh(
'subway',
{
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
}
);
this.setState({
areas,
subways,
subwayId: subways[0]?.id,
});
this.getStations(subways[0]?.id!);
},
},
data: {
open: false,
stationIds: [] as string[],
},
properties: {
areaId: '' as string | undefined | null,
onCancel: undefined as (() => void) | undefined,
onConfirm: undefined as ((stationIds: string[]) => void) | undefined,
selectIds: [] as string[] | undefined,
},
methods: {
setAeraId(areaId: string) {
this.setState({
areaId,
});
},
setCheckedList(value: string, flag: boolean) {
const { stationIds } = this.state;
if (flag) {
this.setState({
stationIds: stationIds.concat(value),
});
// stationIds.push(value);
} else {
var index = stationIds.indexOf(value);
// stationIds.splice(index, 1);
this.setState({
stationIds: pull(stationIds, value),
});
}
},
async getSubways(areaId: string) {
this.setState({
areaId,
});
const { data: subways } = await this.features.cache.refresh(
'subway',
{
data: {
id: 1,
name: 1,
},
filter: {
areaId,
},
}
);
this.getStations(subways[0]!.id!);
this.setState({
subways,
});
},
async getStations(subwayId: string) {
this.setState({
subwayId,
});
const { data: subwayStations } = await this.features.cache.refresh(
'subwayStation',
{
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
},
},
filter: {
subwayId,
},
}
);
const stations = subwayStations?.map((ele: any) => ({
label: ele.station.name,
value: ele.station.id,
}));
this.setState({
stations,
});
},
cancel() {
this.setState({
stationIds: [],
});
if (this.props.onCancel) {
this.props.onCancel();
}
},
confirm() {
if (this.props.onConfirm) {
this.props.onConfirm(this.state.stationIds);
}
this.setState({
stationIds: [],
});
},
},
});

View File

@ -0,0 +1,5 @@
/** index.wxss **/
.container {
background: var(--oak-bg-color-container);
}

View File

@ -0,0 +1,111 @@
import { Checkbox, Button, Col, Tabs, Row, Space } from 'antd';
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
import Style from './web.module.less';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
export default function render(
props: WebComponentProps<
EntityDict,
'area',
true,
{
subways: EntityDict['subway']['Schema'][];
areas: EntityDict['area']['Schema'][];
stations: { label: string; value: string }[];
areaId: string;
stationIds: string[];
selectIds: string[];
},
{
getStations: (subwayId: string) => void;
getSubways: (areaId: string) => void;
setCheckedList: (station: string, flag: boolean) => void;
cancel: () => void;
confirm: () => void;
}
>
) {
const { data, methods } = props;
const { t, getStations, getSubways, setCheckedList, cancel, confirm } =
methods;
const { subways, stations, areaId, areas, stationIds, selectIds } = data;
return (
<div className={Style.container}>
<Tabs
style={{ minHeight: '40vh' }}
tabPosition={'left'}
type="card"
defaultActiveKey={areaId}
onChange={(value) => {
getSubways(value);
}}
items={areas?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (
<Tabs
tabPosition={'top'}
onChange={(value) => {
getStations(value);
}}
items={subways?.map((ele) => ({
key: ele.id,
label: ele.name,
children: (
<Space size={[0, 16]} wrap>
{stations?.map((ele: any) => {
return (
<Checkbox
disabled={selectIds?.includes(
ele.value
)}
onChange={(
e: CheckboxChangeEvent
) => {
setCheckedList(
e.target.value,
e.target.checked
);
}}
checked={stationIds
.concat(selectIds || [])
.includes(ele.value)}
value={ele.value}
>
{ele.label}
</Checkbox>
);
})}
</Space>
),
}))}
></Tabs>
),
}))}
></Tabs>
<div style={{ textAlign: 'center', marginTop: 16 }}>
<Space>
<Button
onClick={() => {
cancel();
}}
>
</Button>
<Button
type="primary"
onClick={async () => {
confirm();
}}
>
</Button>
</Space>
</div>
</div>
);
}

View File

@ -0,0 +1,103 @@
@import "../../../config/styles/mp/mixins.less";
.container {
padding-top: 100rpx;
display: flex;
flex-direction: column;
flex: 1;
background-color: #f7f8fb;
min-height: 100vh;
.safe-area-inset-bottom()
}
.stickyView {
box-sizing: border-box;
padding: 20rpx;
border-bottom: 1px solid rgba(200, 200, 200, 0.3);
position: fixed;
top: 0;
width: 750rpx;
display: flex;
align-items: center;
background-color: #fff;
z-index: 999;
}
.addText {
padding-left: 20rpx;
color: var(--oak-color-primary);
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
}
.card {
margin: 20rpx;
margin-bottom: 0rpx;
border-radius: 20rpx;
display: flex;
flex-direction: column;
background-color: #fff;
.title-view {
padding: 32rpx;
display: flex;
align-items: center;
justify-content: space-between;
.title {
display: flex;
align-items: center;
font-weight: 600;
}
}
.card-content {
padding: 32rpx;
padding-top: 0rpx;
display: flex;
flex-direction: column;
}
.card-op {
border-top: 0.8px solid rgba(200, 200, 200, 0.2);
height: 80rpx;
display: flex;
align-items: center;
}
.card-btn {
color: var(--oak-color-primary);
display: flex;
flex: 1;
align-items: center;
justify-content: center;
}
.text-view {
display: flex;
align-items: center;
justify-content: space-between;
.label {
color: #888;
}
}
.state-view {
display: flex;
align-items: center;
}
.badge {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: var(--oak-color-success);
margin-right: 5px;
}
.success {
background-color: var(--oak-color-success);
}
.failed {
background-color: var(--oak-color-error);
}
.inCharge {
background-color: var(--oak-color-primary);
}
.init {
background-color: var(--oak-color-warning);
}
}
[class='text-view']:not(:last-child) {
margin-bottom: 16rpx;
}

View File

@ -0,0 +1,6 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}

View File

@ -0,0 +1,103 @@
@import "../../../config/styles/mp/mixins.less";
.container {
padding-top: 100rpx;
display: flex;
flex-direction: column;
flex: 1;
background-color: #f7f8fb;
min-height: 100vh;
.safe-area-inset-bottom()
}
.stickyView {
box-sizing: border-box;
padding: 20rpx;
border-bottom: 1px solid rgba(200, 200, 200, 0.3);
position: fixed;
top: 0;
width: 750rpx;
display: flex;
align-items: center;
background-color: #fff;
z-index: 999;
}
.addText {
padding-left: 20rpx;
color: var(--oak-color-primary);
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
}
.card {
margin: 20rpx;
margin-bottom: 0rpx;
border-radius: 20rpx;
display: flex;
flex-direction: column;
background-color: #fff;
.title-view {
padding: 32rpx;
display: flex;
align-items: center;
justify-content: space-between;
.title {
display: flex;
align-items: center;
font-weight: 600;
}
}
.card-content {
padding: 32rpx;
padding-top: 0rpx;
display: flex;
flex-direction: column;
}
.card-op {
border-top: 0.8px solid rgba(200, 200, 200, 0.2);
height: 80rpx;
display: flex;
align-items: center;
}
.card-btn {
color: var(--oak-color-primary);
display: flex;
flex: 1;
align-items: center;
justify-content: center;
}
.text-view {
display: flex;
align-items: center;
justify-content: space-between;
.label {
color: #888;
}
}
.state-view {
display: flex;
align-items: center;
}
.badge {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: var(--oak-color-success);
margin-right: 5px;
}
.success {
background-color: var(--oak-color-success);
}
.failed {
background-color: var(--oak-color-error);
}
.inCharge {
background-color: var(--oak-color-primary);
}
.init {
background-color: var(--oak-color-warning);
}
}
[class='text-view']:not(:last-child) {
margin-bottom: 16rpx;
}

View File

@ -0,0 +1,6 @@
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}

View File

@ -1,4 +0,0 @@
{
"navigationBarTitleText": "地铁线路管理",
"usingComponents": {}
}

View File

@ -1,130 +0,0 @@
// import { TreeNode } from '@project/types/interface';
import { EntityDict } from '../../../oak-app-domain';
type TreeNode = {
key: string;
title: string;
children?: TreeNode[];
isLeaf?: boolean;
};
export default OakComponent({
entity: 'subway',
projection: {
id: 1,
name: 1,
areaId: 1,
subwayStation$subway: {
$entity: 'subwayStation',
data: {
id: 1,
subwayId: 1,
stationId: 1,
station: {
id: 1,
name: 1,
}
}
}
},
pagination: {
currentPage: 1,
pageSize: 100,
more: true,
},
isList: true,
data: {
areaId: '330100' as string,
areaOptions: [] as Array<{ label: string, value: string }>,
},
properties: {},
filters: [
{
filter() {
return {
areaId: '330100'
}
},
'#name': 'area',
},
// {
// filter() {
// return {
// };
// },
// '#name': 'type',
// },
],
listeners: {},
formData: ({ data: subway }) => {
const treeData: TreeNode[] = subway
// ?.filter((ele) => !ele!.subwayStation$subway)
.map((ele) => {
return {
title: ele!.name!,
key: ele!.id!,
isLeaf: false,
children:
ele.subwayStation$subway!
.map((ele2) => ({
title: ele2!.station!.name,
key: `${ele.id}/${ele2!.station!.id}`,
isLeaf: true,
})) || [],
};
});
return {
treeData,
};
},
lifetimes: {
async ready() {
const { data: area } = await this.features.cache.refresh(
'area',
{
data: {
id: 1,
name: 1,
level: 1,
},
filter: {
subway$area: {
},
level: 'city',
},
}
);
const areaOptions = area?.map(
(ele: any) => ({
label: ele.name,
value: ele.id,
})
)
this.setState({
areaOptions,
});
},
},
methods: {
setFilterByAreaId(areaId: string) {
this.addNamedFilter(
{
filter: {
areaId,
},
'#name': 'area',
},
true
);
},
setAreaId(areaId: string) {
this.setState({
areaId,
})
}
},
});

View File

@ -1,22 +0,0 @@
/** index.wxss **/
.container {
background: var(--oak-bg-color-container);
box-shadow: 0 2px 3px #0000001a;
border-radius: 3px;
padding: 30px 32px;
}
.space {
margin-bottom: 15px;
}
.tree {
:global {
.ant-tree-title {
display: flex;
flex: 1;
}
}
}

View File

@ -1,157 +0,0 @@
import React, { useState } from 'react';
import { Button, Space, Tree, Row, Col, Tabs, Select } from 'antd';
import PageHeader from '../../../components/common/pageHeader';
import Style from './web.module.less';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { DataNode } from 'antd/es/tree'
import UpsertSubway from '../upsertSubway';
import UpsertStation from '../upsertStation';
export default function Render(
props: WebComponentProps<
EntityDict,
'subway',
true,
{
treeData: DataNode[];
areaId: string;
areaOptions: { label: string; value: string }[];
},
{
setAreaId: (areaId: string) => void;
setFilterByAreaId: (areaId: string) => void;
}
>
) {
const { data, methods } = props;
const { oakFullpath, treeData, areaOptions, areaId } = data;
const { t, setAreaId, setFilterByAreaId } = methods;
const [openSubway, setSubway] = useState(false);
const [openStation, setStation] = useState(false);
const [subwayId, setSubwayId] = useState('');
const [stationId, setStationId] = useState('');
return (
<PageHeader title="地铁线路管理">
<div className={Style.container}>
{/* <Space className={Style.space}>
<Button
type="primary"
onClick={() => {
goServiceUpsert();
}}
>
</Button>
</Space> */}
<div>
<Select
placeholder={'切换城市'}
value={areaId}
onChange={(value) => {
setAreaId(value);
setFilterByAreaId(value);
}}
style={{ width: '20%' }}
options={areaOptions}
allowClear
></Select>
</div>
<Tree
className={Style.tree}
blockNode={true}
treeData={treeData}
titleRender={(nodeData) => {
return (
<Row align="middle" style={{ flex: 1 }}>
<Col flex="auto">
{(nodeData as any).title}
</Col>
<Col flex="none">
<Space>
{!nodeData.isLeaf ? <Button
onClick={() =>
{
setSubwayId((nodeData as any).key)
setSubway(true)
}
}
>
</Button> :
<Button
onClick={() =>
{
const index = (nodeData as any).key.indexOf('/') + 1;
const temp = (nodeData as any).key.substr(index);
setStationId(temp)
setStation(true)
}
}
>
</Button>
}
{/* {!nodeData.isLeaf && (
<Button
onClick={() =>
{
setSubwayId((nodeData as any).key)
setStation(true)
}
}
>
</Button>
// <Button
// type="primary"
// onClick={() =>
// goServiceUpsert(
// nodeData!
// .key as string
// )
// }
// >
// 添加站点
// </Button>
)} */}
</Space>
</Col>
</Row>
);
}}
/>
{openSubway && (
<UpsertSubway
onClose={() => setSubway(false)}
openSubway={openSubway}
oakId={subwayId}
oakPath={`${oakFullpath}.${subwayId}`}
oakAutoUnmount={true}
/>
)}
{openStation && (
<UpsertStation
onClose={() => setStation(false)}
openStation={openStation}
oakId={stationId}
subwayId={subwayId}
oakPath={`$subwayLine/upsertStation,${stationId}`}
oakAutoUnmount={true}
/>
)}
</div>
</PageHeader>
);
}

View File

@ -1,3 +0,0 @@
{
"navigationBarTitleText": "微信公众号标签详情"
}

View File

@ -1,77 +0,0 @@
export default OakComponent({
entity: 'wechatPublicTag',
isList: false,
projection: {
id: 1,
text: 1,
wechatId: 1,
sync: 1,
syncAt: 1,
applicationId: 1,
iState: 1,
$$createAt$$: 1,
$$updateAt$$: 1,
$$seq$$: 1,
userWechatPublicTag$wechatPublicTag$$aggr: {
$entity: 'userWechatPublicTag',
data: {
'#count-1': {
id: 1,
},
},
},
},
formData({ data }) {
return {
list: data,
};
},
actions: ['sync'],
filters: [
{
filter() {
const { applicationId } = this.props;
return {
applicationId
}
}
}
],
properties: {
applicationId: '',
},
methods: {
async sync(name: string, wechatId?: number) {
// this.updateItem({}, id, 'sync');
// await this.execute();
const { applicationId } = this.props;
if(wechatId) {
await this.features.wechatPublicTag.createTag({applicationId: applicationId!, name});
} else {
await this.features.wechatPublicTag.editTag({applicationId: applicationId!, id: wechatId!, name});
};
this.setMessage({
type: 'success',
content: '操作成功'
})
},
async oneKeySync() {
const { applicationId } = this.props;
await this.features.wechatPublicTag.oneKeySync({ applicationId: applicationId! });
await this.refresh();
this.setMessage({
content: '同步成功',
type: 'success'
});
},
async deleteTag(id: string, wechatId: number) {
const { applicationId } = this.props;
await this.features.wechatPublicTag.deleteTag({ applicationId: applicationId!, id, wechatId });
await this.refresh();
this.setMessage({
content: '操作成功',
type: 'success',
});
}
}
});

View File

@ -1,3 +0,0 @@
.container {
width: 100%
}

View File

@ -1,83 +0,0 @@
import React from 'react';
import { Button, Form, Row, Col, Select, Input, Space, Tooltip } from 'antd';
import PageHeader from '../../../../components/common/pageHeader';
import Style from './web.module.less';
import { EntityDict } from '../../../../oak-app-domain';
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
import { getWechatPublicTags } from '../../../../config/constants';
export default function Render(
props: WebComponentProps<
EntityDict,
'wechatPublicTag',
false,
{
variant: 'inline' | 'alone' | 'dialog';
showBack: boolean;
text: string;
wechatId: number;
sync: boolean;
oakId: string,
},
{
confirm: () => void;
createTag: (name: string) => void;
editTag: (id: number, name: string) => void;
}
>
) {
const {
variant,
showBack = true,
text,
wechatId,
sync,
oakDirty,
oakExecuting,
oakId,
} = props.data;
const { t, update, navigateBack, confirm, createTag, editTag } = props.methods;
const WechatPublicTags = getWechatPublicTags();
const TagOptions = Object.keys(WechatPublicTags).map(
ele => ({
label: WechatPublicTags[ele],
value: WechatPublicTags[ele],
})
);
return (
<PageHeader showBack={true} title="微信公众号TAG信息">
<Row>
<Col xs={24} sm={12}>
<Form
colon={true}
labelCol={{ span: 6 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="TAG名称"
required
rules={[
{
required: true,
},
]}
>
<>
<Input
value={text}
onChange={(v) => update({ text: v.target.value })}
placeholder='标签名称'
maxLength={30}
/>
</>
</Form.Item>
</Form>
</Col>
</Row>
</PageHeader>
);
}

View File

@ -1,3 +0,0 @@
{
"navigationBarTitleText": "微信公众号标签"
}

View File

@ -1,55 +0,0 @@
export default OakComponent({
entity: 'wechatPublicTag',
isList: true,
projection: {
id: 1,
text: 1,
wechatId: 1,
sync: 1,
syncAt: 1,
applicationId: 1,
iState: 1,
$$createAt$$: 1,
$$updateAt$$: 1,
$$seq$$: 1,
},
formData({ data }) {
return {
list: data,
};
},
actions: ['sync'],
filters: [
{
filter() {
const { applicationId } = this.props;
return {
applicationId
}
}
}
],
properties: {
applicationId: '',
},
methods: {
async sync(id: string) {
const { applicationId } = this.props;
await this.features.wechatPublicTag.syncTag({applicationId: applicationId!, id});
await this.refresh();
},
async oneKeySync() {
const { applicationId } = this.props;
await this.features.wechatPublicTag.oneKeySync({ applicationId: applicationId! });
await this.refresh();
this.setMessage({
content: '同步成功',
type: 'success'
});
},
async deleteTag(id: string) {
this.removeItem(id);
await this.execute();
}
}
});

View File

@ -1,249 +0,0 @@
import React, { useState } from 'react';
import {
Avatar,
Space,
Button,
Input,
Typography,
DatePicker,
Table,
Modal,
} from 'antd';
const { confirm } = Modal;
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../../oak-app-domain';
import PageHeader from '../../../../components/common/pageHeader';
import Style from './web.module.less';
import dayjs from 'dayjs';
import WechatPublicTagUpsert from '../../../../components/wechatPublicTag/upsert';
export default function Render(
props: WebComponentProps<
EntityDict,
'wechatPublicTag',
true,
{
showBack: boolean;
list: Partial<EntityDict['wechatPublicTag']['Schema']>[];
applicationId: string;
},
{
goDetail: (id: string) => void;
goCreate: () => void;
goUpdate: (id: string) => void;
goDelete: (id: string) => void;
sync: (id: string) => void;
oneKeySync: () => void;
deleteTag: (id: string) => void;
}
>
) {
const { data, methods } = props;
const {
t,
setPageSize,
setCurrentPage,
goCreate,
goDetail,
goUpdate,
goDelete,
sync,
oneKeySync,
deleteTag,
addItem,
updateItem,
execute,
} = methods;
const { list, showBack = true, oakLoading, oakPagination, applicationId } = data;
const { pageSize, total, currentPage } = oakPagination || {};
const [open, setOpen] = useState(false);
const [oakId, setOakId] = useState('');
const [tagName, setTagName] = useState('');
const [text, setText] = useState('');
const changeOpen = (open: boolean) => {
setOpen(open);
}
const changeText = (text: string) => {
setText(text);
}
const addTag = async () => {
const id = addItem({
applicationId,
text,
iState: 'wait',
});
await execute();
sync(id);
}
const editTag = async () => {
updateItem({
text,
iState: 'wait',
}, oakId);
await execute();
sync(oakId);
}
return (
<PageHeader title="微信公众号标签" showBack={showBack}>
<div className={Style.container}>
<Space style={{ marginBottom: 20 }}>
<Button
type="primary"
onClick={() => {
setOpen(true);
setOakId('');
setText('');
}}
>
TAG
</Button>
<Button onClick={async () => {
oneKeySync();
}}>
</Button>
</Space>
<WechatPublicTagUpsert
isUpdate={oakId ? true : false}
oakAutoUnmount={true}
open={open}
changeOpen={changeOpen}
changeText={changeText}
text={text}
tagName={tagName}
addTag={addTag}
editTag={editTag}
/>
<Table
loading={oakLoading}
dataSource={list}
rowKey="id"
columns={[
{
dataIndex: '$$seq$$',
title: '序号',
width: 100,
},
{
dataIndex: 'text',
title: t('wechatPublicTag:attr.text'),
width: 150,
ellipsis: true,
},
{
dataIndex: 'wechatId',
title: t('wechatPublicTag:attr.wechatId'),
width: 100,
},
{
dataIndex: 'iState',
title: '状态',
width: 100,
render: (value, record, index) => {
return value === 'wait' ? '待同步' : value === 'success' ? '同步成功' : '同步失败';
},
},
{
dataIndex: 'syncAt',
title: t('wechatPublicTag:attr.syncAt'),
width: 100,
render: (value, record, index) => {
return value ? dayjs(value).format('YYYY-MM-DD HH:mm') : '--';
},
},
{
dataIndex: '$$createAt$$',
title: '创建时间',
width: 100,
render: (value, record, index) => {
return dayjs(value).format('YYYY-MM-DD HH:mm');
},
},
{
dataIndex: '$$updateAt$$',
title: '更新时间',
width: 100,
render: (value, record, index) => {
return dayjs(value).format('YYYY-MM-DD HH:mm');
},
},
{
dataIndex: 'op',
width: 200,
title: '操作',
align: 'center',
render: (value, record, index) => {
return (
<>
<Button
type="link"
onClick={() => {
goDetail(record.id!);
}}
>
</Button>
<Button
type="link"
onClick={() => {
setOpen(true);
setOakId(record.id!);
setText(record.text!);
setTagName(record.text!);
}}
>
</Button>
{
(record.iState === 'fail' || record.iState === 'wait') && <Button
type="link"
onClick={() => {
sync(record.id!);
}}
>
</Button>
}
<Button
type="link"
onClick={() => {
const modal = confirm({
title: '确定删除该标签吗?',
content: '删除后不可恢复',
okText: '确定',
cancelText: '取消',
onOk: (e) => {
deleteTag(record.id!);
modal!.destroy();
},
});
}}
danger
>
</Button>
</>
);
},
fixed: 'right',
},
]}
pagination={{
total,
pageSize,
current: currentPage,
onShowSizeChange: (pageSize: number) => {
setPageSize(pageSize);
},
onChange: (current: number) => {
setCurrentPage(current);
},
}}
/>
</div>
</PageHeader>
);
}

View File

@ -1,3 +0,0 @@
{
"navigationBarTitleText": "微信公众号标签修改"
}

View File

@ -1,78 +0,0 @@
import assert from "assert";
export default OakComponent({
entity: 'wechatPublicTag',
isList: false,
properties: {
applicationId: '',
oakId: '',
},
projection: {
id: 1,
text: 1,
wechatId: 1,
sync: 1,
syncAt: 1,
$$createAt$$: 1,
$$updateAt$$: 1,
$$seq$$: 1,
},
formData({ data: tag }) {
return {
text: tag?.text,
wechatId: tag?.wechatId,
sync: tag?.sync,
}
},
lifetimes: {
ready() {
const { oakId, applicationId } = this.props;
if (!oakId) {
assert(applicationId);
this.update({
applicationId,
iState: 'wait',
});
}
}
},
methods: {
async confirm() {
this.navigateBack();
},
async createTag(name: string) {
if (!name) {
this.setMessage({
type: 'warning',
content: '请输入标签名称'
});
return;
}
const { applicationId } = this.props;
const { text } = this.state;
await this.features.wechatPublicTag.createTag({applicationId: applicationId!, name: text!});
this.setMessage({
type: 'success',
content: '操作成功',
});
await this.confirm();
},
async editTag(id: number, name: string) {
if (!name) {
this.setMessage({
type: 'warning',
content: '请输入标签名称'
});
return;
}
const { applicationId } = this.props;
const { wechatId, text } = this.state;
await this.features.wechatPublicTag.editTag({applicationId: applicationId!, id: wechatId!, name: text! });
this.setMessage({
type: 'success',
content: '操作成功',
});
await this.confirm();
}
}
})

View File

@ -1,124 +0,0 @@
import React from 'react';
import { Button, Form, Row, Col, Select, Input, Space, Tooltip } from 'antd';
import PageHeader from '../../../../components/common/pageHeader';
import Style from './web.module.less';
import { EntityDict } from '../../../../oak-app-domain';
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
import { getWechatPublicTags } from '../../../../config/constants';
export default function Render(
props: WebComponentProps<
EntityDict,
'wechatPublicTag',
false,
{
variant: 'inline' | 'alone' | 'dialog';
showBack: boolean;
text: string;
wechatId: number;
sync: boolean;
oakId: string,
},
{
confirm: () => void;
createTag: (name: string) => void;
editTag: (id: number, name: string) => void;
}
>
) {
const {
variant,
showBack = true,
text,
wechatId,
sync,
oakDirty,
oakExecuting,
oakId,
} = props.data;
const { t, update, navigateBack, confirm, createTag, editTag } = props.methods;
const WechatPublicTags = getWechatPublicTags();
const TagOptions = Object.keys(WechatPublicTags).map(
ele => ({
label: WechatPublicTags[ele],
value: WechatPublicTags[ele],
})
);
return (
<PageHeader showBack={true} title="微信公众号TAG信息">
<Row>
<Col xs={24} sm={12}>
<Form
colon={true}
labelCol={{ span: 6 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="TAG名称"
required
rules={[
{
required: true,
},
]}
>
<>
<Input
value={text}
onChange={(v) => update({ text: v.target.value })}
placeholder='标签名称'
maxLength={30}
/>
</>
</Form.Item>
<Action variant={variant}>
<Form.Item wrapperCol={{ offset: 6 }}>
<Space>
<Button
type="primary"
onClick={() => {
if (oakId) {
editTag(wechatId, text);
console
} else {
createTag(text);
}
}}
disabled={!oakDirty || oakExecuting}
>
</Button>
<Button
onClick={() => {
navigateBack();
}}
>
</Button>
</Space>
</Form.Item>
</Action>
</Form>
</Col>
</Row>
</PageHeader>
);
}
function Action(props: {
children: React.ReactNode;
variant?: 'inline' | 'alone' | 'dialog';
}) {
const { children, variant } = props;
if (variant === 'dialog') {
return null;
}
return (
<>{children}</>
)
}