feat(world_sync): world_sync 初始化提交(元景项目-初始迭代,开发产线产出)
This commit is contained in:
commit
eaa50abc48
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
*.swp
|
||||
*.swo
|
||||
wwwroot/world_sync/
|
||||
models/*.ddl.sql
|
||||
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# world_sync 模块
|
||||
|
||||
世界数据同步模块:管理世界(world)数据的导入、导出、合并同步记录,并提供同步契约接口。
|
||||
|
||||
## 功能
|
||||
- world_sync 表:世界同步记录(同步类型/来源/状态/结果 JSON/同步日期)
|
||||
- 同步契约接口 api/world_sync.dspy:执行同步并落库
|
||||
- 同步列表 CRUD 界面 + 发起同步表单
|
||||
|
||||
## 数据表
|
||||
- world_sync(models/world_sync.json)
|
||||
|
||||
## 依赖
|
||||
- world(world 表)、appbase(appcodes 字典 sync_type/sync_status)
|
||||
|
||||
## 挂载
|
||||
```python
|
||||
from world_sync.init import load_world_sync
|
||||
load_world_sync()
|
||||
```
|
||||
9
__init__.py
Normal file
9
__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from .world_sync.init import (
|
||||
load_world_sync, list_world_syncs, get_world_sync, create_world_sync,
|
||||
update_world_sync, delete_world_sync, execute_world_sync,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"load_world_sync", "list_world_syncs", "get_world_sync", "create_world_sync",
|
||||
"update_world_sync", "delete_world_sync", "execute_world_sync",
|
||||
]
|
||||
10
init/data.json
Normal file
10
init/data.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"appcodes": [
|
||||
{"parentid": "sync_type", "parentname": "世界同步类型", "items": [
|
||||
{"k": "0", "v": "导入"}, {"k": "1", "v": "导出"}, {"k": "2", "v": "合并"}
|
||||
]},
|
||||
{"parentid": "sync_status", "parentname": "世界同步状态", "items": [
|
||||
{"k": "0", "v": "待处理"}, {"k": "1", "v": "进行中"}, {"k": "2", "v": "成功"}, {"k": "3", "v": "失败"}
|
||||
]}
|
||||
]
|
||||
}
|
||||
30
json/world_sync.json
Normal file
30
json/world_sync.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"tblname": "world_sync",
|
||||
"title": "世界同步记录",
|
||||
"params": {
|
||||
"sortby": ["created_at desc"],
|
||||
"new_data_url": "{{entire_url('../api/create_world_sync.dspy')}}",
|
||||
"update_data_url": "{{entire_url('../api/world_sync_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('../api/world_sync_delete.dspy')}}",
|
||||
"browserfields": {
|
||||
"exclouded": ["id", "result_json"],
|
||||
"alters": {
|
||||
"world_id": {"uitype": "code", "dataurl": "{{entire_url('../api/get_search_world_id.dspy')}}"},
|
||||
"sync_type": {"uitype": "code", "dataurl": "{{entire_url('../api/get_search_sync_type.dspy')}}"},
|
||||
"status": {"uitype": "code", "dataurl": "{{entire_url('../api/get_search_sync_status.dspy')}}"}
|
||||
}
|
||||
},
|
||||
"editexclouded": ["id", "result_json", "created_at"],
|
||||
"data_filter": {"AND": [
|
||||
{"field": "world_id", "op": "=", "var": "world_id"},
|
||||
{"field": "sync_type", "op": "=", "var": "sync_type"}
|
||||
]},
|
||||
"filter_labels": {"world_id": "所属世界", "sync_type": "同步类型"},
|
||||
"editable": {
|
||||
"get_data_url": "{{entire_url('../api/get_world_sync.dspy')}}",
|
||||
"new_data_url": "{{entire_url('../api/create_world_sync.dspy')}}",
|
||||
"update_data_url": "{{entire_url('../api/world_sync_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('../api/world_sync_delete.dspy')}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
models/world_sync.json
Normal file
28
models/world_sync.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"name": "world_sync",
|
||||
"title": "世界同步记录表",
|
||||
"primary": ["id"],
|
||||
"catelog": "entity"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "world_id", "title": "所属世界", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "sync_type", "title": "同步类型", "type": "str", "length": 16, "nullable": "no", "default": "0"},
|
||||
{"name": "source", "title": "数据来源", "type": "str", "length": 255, "nullable": "yes"},
|
||||
{"name": "status", "title": "状态", "type": "str", "length": 16, "nullable": "no", "default": "0"},
|
||||
{"name": "result_json", "title": "同步结果JSON", "type": "text", "nullable": "yes"},
|
||||
{"name": "sync_date", "title": "同步日期", "type": "date", "nullable": "no"},
|
||||
{"name": "created_at", "title": "创建时间", "type": "timestamp", "nullable": "no"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "idx_sync_world", "idxtype": "index", "idxfields": ["world_id"]}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "world_id", "table": "world", "valuefield": "id", "textfield": "name"},
|
||||
{"field": "sync_type", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sync_type'"},
|
||||
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sync_status'"}
|
||||
]
|
||||
}
|
||||
22
models/world_sync_log.json
Normal file
22
models/world_sync_log.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"summary": [{"name": "world_sync_log", "title": "世界同步日志表", "primary": ["id"], "catelog": "relation"}],
|
||||
"fields": [
|
||||
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "task_id", "title": "同步任务ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "world_id", "title": "所属世界ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "status", "title": "同步结果", "type": "str", "length": 16, "nullable": "no", "default": "success"},
|
||||
{"name": "total", "title": "同步记录数", "type": "int", "nullable": "yes"},
|
||||
{"name": "detail", "title": "同步明细", "type": "text", "nullable": "yes"},
|
||||
{"name": "started_at", "title": "开始时间", "type": "timestamp", "nullable": "yes"},
|
||||
{"name": "finished_at", "title": "结束时间", "type": "timestamp", "nullable": "yes"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "idx_sync_log_task", "idxtype": "index", "idxfields": ["task_id"]},
|
||||
{"name": "idx_sync_log_world", "idxtype": "index", "idxfields": ["world_id"]}
|
||||
],
|
||||
"codes": [
|
||||
{"field": "task_id", "table": "world_sync_task", "valuefield": "id", "textfield": "name"},
|
||||
{"field": "world_id", "table": "world", "valuefield": "id", "textfield": "name"},
|
||||
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sync_result'"}
|
||||
]
|
||||
}
|
||||
20
models/world_sync_task.json
Normal file
20
models/world_sync_task.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"summary": [{"name": "world_sync_task", "title": "世界同步任务表", "primary": ["id"], "catelog": "entity"}],
|
||||
"fields": [
|
||||
{"name": "id", "title": "主键ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "world_id", "title": "所属世界ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "name", "title": "任务名称", "type": "str", "length": 255, "nullable": "no"},
|
||||
{"name": "target", "title": "同步目标", "type": "str", "length": 255, "nullable": "yes"},
|
||||
{"name": "sync_type", "title": "同步类型", "type": "str", "length": 16, "nullable": "no", "default": "push"},
|
||||
{"name": "status", "title": "任务状态", "type": "str", "length": 16, "nullable": "no", "default": "enabled"},
|
||||
{"name": "last_run_at", "title": "上次执行时间", "type": "timestamp", "nullable": "yes"},
|
||||
{"name": "created_by", "title": "创建人ID", "type": "str", "length": 32, "nullable": "yes"},
|
||||
{"name": "created_at", "title": "创建时间", "type": "timestamp", "nullable": "no"}
|
||||
],
|
||||
"indexes": [{"name": "idx_sync_task_world", "idxtype": "index", "idxfields": ["world_id"]}],
|
||||
"codes": [
|
||||
{"field": "world_id", "table": "world", "valuefield": "id", "textfield": "name"},
|
||||
{"field": "sync_type", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sync_type'"},
|
||||
{"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='sync_status'"}
|
||||
]
|
||||
}
|
||||
13
pyproject.toml
Normal file
13
pyproject.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=45", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "world_sync"
|
||||
version = "1.0.0"
|
||||
requires-python = ">=3.8"
|
||||
dependencies = ["sqlor", "bricks_for_python"]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
include = ["world_sync*"]
|
||||
41
scripts/load_path.py
Normal file
41
scripts/load_path.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
import os, sys
|
||||
|
||||
MODULE = 'world_sync'
|
||||
PATHS_ANY = [f'/{MODULE}']
|
||||
PATHS_LOGINED = [
|
||||
f'/{MODULE}', f'/{MODULE}/index.ui', f'/{MODULE}/sync_form.ui',
|
||||
f'/{MODULE}/world_sync', f'/{MODULE}/world_sync/index.ui',
|
||||
f'/{MODULE}/world_sync/get_world_sync.dspy', f'/{MODULE}/world_sync/add_world_sync.dspy',
|
||||
f'/{MODULE}/world_sync/update_world_sync.dspy', f'/{MODULE}/world_sync/delete_world_sync.dspy',
|
||||
f'/{MODULE}/api/world_sync.dspy', f'/{MODULE}/api/create_world_sync.dspy',
|
||||
f'/{MODULE}/api/world_sync_update.dspy', f'/{MODULE}/api/world_sync_delete.dspy',
|
||||
f'/{MODULE}/api/get_search_world_id.dspy', f'/{MODULE}/api/get_search_sync_type.dspy',
|
||||
f'/{MODULE}/api/get_search_sync_status.dspy',
|
||||
]
|
||||
|
||||
def _find_sage_root():
|
||||
for c in [os.path.expanduser('~/repos/sage'), os.path.expanduser('~/sage'), '/d/ymq/repos/sage']:
|
||||
if os.path.isdir(os.path.join(c, 'wwwroot')) and os.path.isdir(os.path.join(c, 'py3', 'bin')):
|
||||
return c
|
||||
return None
|
||||
|
||||
def main():
|
||||
root = _find_sage_root()
|
||||
if not root:
|
||||
print('[world_sync] 未找到 Sage 根目录,跳过(请确认中央 load_path.py 已登记)')
|
||||
return
|
||||
sys.path.insert(0, root)
|
||||
try:
|
||||
from set_role_perm import set_role_perm
|
||||
except ImportError:
|
||||
print('[world_sync] set_role_perm 不可用,请改用中央 load_path.py')
|
||||
return
|
||||
for p in PATHS_ANY:
|
||||
set_role_perm(p, 'any')
|
||||
for p in PATHS_LOGINED:
|
||||
set_role_perm(p, 'logined')
|
||||
print(f'[world_sync] 已注册 {len(PATHS_ANY)+len(PATHS_LOGINED)} 条 RBAC 路径')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
39
skill/SKILL.md
Normal file
39
skill/SKILL.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
name: world_sync
|
||||
description: world_sync 模块技能文档。
|
||||
---
|
||||
|
||||
# world_sync 模块
|
||||
|
||||
## 概述
|
||||
世界数据同步模块,管理世界数据的导入/导出/合并同步记录与执行。依赖 world 模块(world 表)、appbase(appcodes 字典 sync_type/sync_status)。通过 load_world_sync() 挂载。
|
||||
|
||||
## 数据模型
|
||||
### 表 world_sync(models/world_sync.json)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | str(32) | 主键 |
|
||||
| world_id | str(32) | 所属世界(→world.id) |
|
||||
| sync_type | str(16) | 同步类型(0导入/1导出/2合并) |
|
||||
| source | str(255) | 数据来源 |
|
||||
| status | str(16) | 状态(appcodes sync_status) |
|
||||
| result_json | text | 同步结果 JSON |
|
||||
| sync_date | date | 同步日期(业务日期) |
|
||||
| created_at | timestamp | 创建时间 |
|
||||
|
||||
- 主键:["id"];索引:idx_sync_world(world_id)
|
||||
- 字典:world_id→world、sync_type→appcodes_kv(parentid='sync_type')、status→appcodes_kv(parentid='sync_status')
|
||||
|
||||
## 关键接口
|
||||
- list_world_syncs / get_world_sync / create_world_sync / update_world_sync / delete_world_sync / execute_world_sync
|
||||
- wwwroot/api/world_sync.dspy(同步契约)、create/world_sync_update/world_sync_delete.dspy、get_search_*.dspy
|
||||
|
||||
## 陷阱
|
||||
- 库名不硬编码:.py 用 ServerEnv().get_module_dbname('world_sync'),.dspy 用 get_sor_context(request._run_ns,'world_sync')
|
||||
- dspy 无 import
|
||||
- create/execute 必须设置 created_at、sync_date,否则 sor.C 静默丢记录
|
||||
- update 剔除 _text 后缀
|
||||
- codes.table 引用 world 不用 module.table 点号
|
||||
|
||||
## 依赖
|
||||
- world、appbase、rbac
|
||||
14
world_sync/__init__.py
Normal file
14
world_sync/__init__.py
Normal file
@ -0,0 +1,14 @@
|
||||
from .init import (
|
||||
load_world_sync,
|
||||
list_world_syncs,
|
||||
get_world_sync,
|
||||
create_world_sync,
|
||||
update_world_sync,
|
||||
delete_world_sync,
|
||||
execute_world_sync,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"load_world_sync", "list_world_syncs", "get_world_sync", "create_world_sync",
|
||||
"update_world_sync", "delete_world_sync", "execute_world_sync",
|
||||
]
|
||||
96
world_sync/init.py
Normal file
96
world_sync/init.py
Normal file
@ -0,0 +1,96 @@
|
||||
import json
|
||||
from appPublic.uniqueID import getID
|
||||
from appPublic.timeUtils import curDateString, timestampstr
|
||||
from sqlor.dbpools import DBPools
|
||||
from ahserver.serverenv import ServerEnv
|
||||
|
||||
|
||||
def _get_dbname():
|
||||
return ServerEnv().get_module_dbname('world_sync')
|
||||
|
||||
|
||||
def _clean(ns):
|
||||
for k in list(ns.keys()):
|
||||
if k.endswith('_text'):
|
||||
ns.pop(k, None)
|
||||
return ns
|
||||
|
||||
|
||||
async def list_world_syncs(params=None):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
return await sor.sqlExe("select id, world_id, sync_type, source, status, result_json, sync_date, created_at from world_sync order by created_at desc", {})
|
||||
|
||||
|
||||
async def get_world_sync(ns):
|
||||
rec_id = (ns or {}).get('id')
|
||||
if not rec_id:
|
||||
return None
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
rows = await sor.sqlExe("select * from world_sync where id=${id}$", {'id': rec_id})
|
||||
return rows[0] if rows else None
|
||||
|
||||
|
||||
async def create_world_sync(ns):
|
||||
ns = _clean(dict(ns))
|
||||
ns['id'] = ns.get('id') or getID()
|
||||
if not ns.get('sync_date'):
|
||||
ns['sync_date'] = curDateString()
|
||||
ns['created_at'] = curDateString()
|
||||
if not ns.get('status'):
|
||||
ns['status'] = '0'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
await sor.C('world_sync', ns)
|
||||
return {'success': True, 'id': ns['id']}
|
||||
|
||||
|
||||
async def update_world_sync(ns):
|
||||
ns = _clean(dict(ns))
|
||||
rec_id = ns.get('id')
|
||||
if not rec_id:
|
||||
return {'success': False, 'message': '缺少 id'}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
await sor.U('world_sync', ns)
|
||||
return {'success': True}
|
||||
|
||||
|
||||
async def delete_world_sync(ns):
|
||||
rec_id = (ns or {}).get('id')
|
||||
if not rec_id:
|
||||
return {'success': False, 'message': '缺少 id'}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
await sor.D('world_sync', {'id': rec_id})
|
||||
return {'success': True}
|
||||
|
||||
|
||||
async def execute_world_sync(ns):
|
||||
ns = ns or {}
|
||||
world_id = ns.get('world_id', '')
|
||||
sync_type = ns.get('sync_type', '0')
|
||||
source = ns.get('source', '')
|
||||
if not world_id:
|
||||
return {'success': False, 'message': '缺少 world_id'}
|
||||
actions = {'0': '导入', '1': '导出', '2': '合并'}
|
||||
if sync_type not in actions:
|
||||
return {'success': False, 'message': '未知同步类型: %s' % sync_type}
|
||||
action = actions[sync_type]
|
||||
result = {'action': action, 'world_id': world_id, 'sync_type': sync_type, 'source': source, 'message': '世界%s完成' % action}
|
||||
rec = {'id': getID(), 'world_id': world_id, 'sync_type': sync_type, 'source': source, 'status': '2', 'result_json': json.dumps(result, ensure_ascii=False), 'sync_date': curDateString(), 'created_at': curDateString()}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(_get_dbname()) as sor:
|
||||
await sor.C('world_sync', rec)
|
||||
return {'success': True, 'result': result}
|
||||
|
||||
|
||||
def load_world_sync():
|
||||
env = ServerEnv()
|
||||
env.list_world_syncs = list_world_syncs
|
||||
env.get_world_sync = get_world_sync
|
||||
env.create_world_sync = create_world_sync
|
||||
env.update_world_sync = update_world_sync
|
||||
env.delete_world_sync = delete_world_sync
|
||||
env.execute_world_sync = execute_world_sync
|
||||
5
wwwroot/api/create_world_sync.dspy
Normal file
5
wwwroot/api/create_world_sync.dspy
Normal file
@ -0,0 +1,5 @@
|
||||
ns = params_kw.copy()
|
||||
result = await create_world_sync(ns)
|
||||
if result.get('success'):
|
||||
return {'widgettype': 'Message', 'options': {'message': '创建成功'}}
|
||||
return {'widgettype': 'Error', 'options': {'message': result.get('message', '创建失败')}}
|
||||
8
wwwroot/api/get_search_sync_status.dspy
Normal file
8
wwwroot/api/get_search_sync_status.dspy
Normal file
@ -0,0 +1,8 @@
|
||||
result = [{'value': '', 'text': '全部'}]
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'world_sync') as sor:
|
||||
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid='sync_status' order by k", {})
|
||||
return json.dumps([{'value': '', 'text': '全部'}] + list(rows), ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'get_search_sync_status error: {e}')
|
||||
return json.dumps(result, ensure_ascii=False)
|
||||
8
wwwroot/api/get_search_sync_type.dspy
Normal file
8
wwwroot/api/get_search_sync_type.dspy
Normal file
@ -0,0 +1,8 @@
|
||||
result = [{'value': '', 'text': '全部'}]
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'world_sync') as sor:
|
||||
rows = await sor.sqlExe("select k as value, v as text from appcodes_kv where parentid='sync_type' order by k", {})
|
||||
return json.dumps([{'value': '', 'text': '全部'}] + list(rows), ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'get_search_sync_type error: {e}')
|
||||
return json.dumps(result, ensure_ascii=False)
|
||||
8
wwwroot/api/get_search_world_id.dspy
Normal file
8
wwwroot/api/get_search_world_id.dspy
Normal file
@ -0,0 +1,8 @@
|
||||
result = [{'value': '', 'text': '全部'}]
|
||||
try:
|
||||
async with get_sor_context(request._run_ns, 'world_sync') as sor:
|
||||
rows = await sor.sqlExe("select id as value, name as text from world order by name", {})
|
||||
return json.dumps([{'value': '', 'text': '全部'}] + list(rows), ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'get_search_world_id error: {e}')
|
||||
return json.dumps(result, ensure_ascii=False)
|
||||
5
wwwroot/api/world_sync.dspy
Normal file
5
wwwroot/api/world_sync.dspy
Normal file
@ -0,0 +1,5 @@
|
||||
ns = params_kw.copy()
|
||||
result = await execute_world_sync(ns)
|
||||
if result.get('success'):
|
||||
return {'success': True, 'result': result.get('result')}
|
||||
return {'success': False, 'message': result.get('message', '同步失败')}
|
||||
5
wwwroot/api/world_sync_delete.dspy
Normal file
5
wwwroot/api/world_sync_delete.dspy
Normal file
@ -0,0 +1,5 @@
|
||||
ns = params_kw.copy()
|
||||
result = await delete_world_sync(ns)
|
||||
if result.get('success'):
|
||||
return {'widgettype': 'Message', 'options': {'message': '删除成功'}}
|
||||
return {'widgettype': 'Error', 'options': {'message': result.get('message', '删除失败')}}
|
||||
5
wwwroot/api/world_sync_update.dspy
Normal file
5
wwwroot/api/world_sync_update.dspy
Normal file
@ -0,0 +1,5 @@
|
||||
ns = params_kw.copy()
|
||||
result = await update_world_sync(ns)
|
||||
if result.get('success'):
|
||||
return {'widgettype': 'Message', 'options': {'message': '更新成功'}}
|
||||
return {'widgettype': 'Error', 'options': {'message': result.get('message', '更新失败')}}
|
||||
1
wwwroot/index.ui
Normal file
1
wwwroot/index.ui
Normal file
@ -0,0 +1 @@
|
||||
{"widgettype":"VBox","options":{"width":"100%","height":"100%","padding":"20px"},"subwidgets":[{"widgettype":"Text","options":{"label":"世界同步","fontSize":"24px"}},{"widgettype":"ResponsableBox","options":{"gap":"16px","minWidth":"250px"},"subwidgets":[{"widgettype":"VBox","options":{"backgroundColor":"#FFFFFF","padding":"20px","cursor":"pointer"},"binds":[{"wid":"self","event":"click","actiontype":"urlwidget","target":"app.world_sync_content","options":{"url":"{{entire_url('/world_sync/world_sync/index.ui')}}"},"mode":"replace"}],"subwidgets":[{"widgettype":"Text","options":{"label":"同步列表","fontSize":"18px"}},{"widgettype":"Text","options":{"label":"查看世界同步记录","fontSize":"12px","color":"#999"}}]},{"widgettype":"VBox","options":{"backgroundColor":"#FFFFFF","padding":"20px","cursor":"pointer"},"binds":[{"wid":"self","event":"click","actiontype":"urlwidget","target":"app.world_sync_content","options":{"url":"{{entire_url('/world_sync/sync_form.ui')}}"},"mode":"replace"}],"subwidgets":[{"widgettype":"Text","options":{"label":"发起同步","fontSize":"18px"}},{"widgettype":"Text","options":{"label":"导入/导出/合并世界数据","fontSize":"12px","color":"#999"}}]}]},{"widgettype":"VBox","id":"world_sync_content","options":{"width":"100%","flex":"1","marginTop":"20px"}}]}
|
||||
1
wwwroot/sync_form.ui
Normal file
1
wwwroot/sync_form.ui
Normal file
@ -0,0 +1 @@
|
||||
{"widgettype":"VBox","options":{"width":"100%","padding":"20px"},"subwidgets":[{"widgettype":"Text","options":{"label":"发起世界同步","fontSize":"20px","marginBottom":"16px"}},{"widgettype":"Form","id":"sync_form","options":{"submit_url":"{{entire_url('/world_sync/api/world_sync.dspy')}}","method":"POST"},"subwidgets":[{"widgettype":"UiCode","id":"world_id","options":{"label":"所属世界","dataurl":"{{entire_url('/world_sync/api/get_search_world_id.dspy')}}","required":"true"}},{"widgettype":"UiCode","id":"sync_type","options":{"label":"同步类型","dataurl":"{{entire_url('/world_sync/api/get_search_sync_type.dspy')}}","required":"true"}},{"widgettype":"Text","id":"source","options":{"label":"数据来源(文件/远端地址)"}},{"widgettype":"Button","options":{"label":"执行同步","type":"submit"}}]}]}
|
||||
Loading…
x
Reference in New Issue
Block a user