📝 应用描述
浏览web拾物应用商店中的所有上架应用
📋 详细信息
| 应用ID |
siwoapps |
| 名称 |
拾物应用商店 |
| 版本 |
v1 |
| 文件大小 |
4.9 KB |
| 上传时间 |
2026-07-29 20:50:33 |
| 状态 |
✅ 已启用 |
| 权限 |
network_external |
📁 资源文件 (1)
💡 界面预览 (main.lua)
📄 Lua 源码
-- ============================================================
-- 应用浏览器 CIP | 严格匹配官方lua-cip.md规范
-- 功能:分页、分类筛选、应用列表、点击跳转网页详情
-- ============================================================
-- 常量
local API_BASE = "https://oldchat.shop/api/index.php?c=App&a=list&token=abc123456789"
local PAGE_SIZE = 10
local IMAGE_DOMAIN = "https://oldchat.shop"
local MAX_LIST_ITEMS = 10
-- 全局状态(全部非空初始化,杜绝nil)
local currentPage = 1
local totalItems = 0
local currentCategory = ""
local isLoading = false
local categories = {}
local pageAppData = {} -- 缓存当前页应用数据,按钮按下标取id
-- ============================================================
-- 工具函数(所有入参强制兜底,无nil输出)
-- ============================================================
local function formatSize(sizeStr)
local raw = tostring(sizeStr or "0")
local num = tonumber(raw) or 0
if num >= 1024 * 1024 then
return string.format("%.1f MB", num / (1024 * 1024))
elseif num >= 1024 then
return string.format("%.1f KB", num / 1024)
end
return string.format("%.0f B", num)
end
local function formatDownloads(count)
local raw = tostring(count or "0")
local num = tonumber(raw) or 0
if num >= 10000 then
return string.format("%.1f万", num / 10000)
end
return tostring(num)
end
local function extractCategories(list)
local src = list or {}
local catSet = {}
for _, item in ipairs(src) do
local cat = tostring(item.category or "")
if cat ~= "" then
catSet[cat] = true
end
end
local cats = {}
for k in pairs(catSet) do
table.insert(cats, k)
end
table.sort(cats)
return cats
end
-- 详情跳转统一处理(按下标读取缓存应用ID)
local function jumpDetail(itemIndex)
local target = pageAppData[itemIndex] or {}
local aid = tostring(target.id or "")
if aid == "" then
app.toast("未读取到应用ID,无法跳转")
return
end
local targetUrl = "https://oldchat.shop/app.php?id=" .. aid
app.open_url(targetUrl)
end
-- ============================================================
-- UI 批量隐藏工具
-- ============================================================
local function hideAllAppEntries()
for i = 1, MAX_LIST_ITEMS do
app.set_visible("app_icon_" .. i, false)
app.set_visible("app_name_" .. i, false)
app.set_visible("app_pkg_" .. i, false)
app.set_visible("app_info_" .. i, false)
app.set_visible("btn_detail_" .. i, false)
if i < MAX_LIST_ITEMS then
app.set_visible("separator_" .. i, false)
end
end
app.set_visible("empty_text", false)
end
local function updateCategoryButtons()
for i = 1, 5 do
app.set_visible("cat_btn_" .. i, false)
end
app.set_visible("more_cat_text", false)
if #categories <= 0 then
app.set_visible("category_label", false)
app.set_visible("btn_all", false)
return
end
app.set_visible("category_label", true)
app.set_visible("btn_all", true)
if currentCategory == "" then
app.set_text("btn_all", "✅ 全部")
else
app.set_text("btn_all", "全部")
end
local maxShow = math.min(#categories, 5)
for i = 1, maxShow do
local catName = tostring(categories[i] or "")
app.set_text("cat_btn_" .. i, catName)
app.set_visible("cat_btn_" .. i, true)
if catName == currentCategory then
app.set_text("cat_btn_" .. i, "✅ " .. catName)
end
end
if #categories > 5 then
app.set_text("more_cat_text", "... 共 " .. tostring(#categories) .. " 个分类")
app.set_visible("more_cat_text", true)
end
end
-- ============================================================
-- 网络加载函数(文档标准 http_get(body, err))
-- ============================================================
local function loadApps(page)
if isLoading then return end
isLoading = true
pageAppData = {} -- 清空当前页缓存
local url = API_BASE .. "&page=" .. tostring(page) .. "&page_size=" .. tostring(PAGE_SIZE)
if currentCategory ~= "" then
url = url .. "&category=" .. currentCategory
end
app.set_text("status_text", "正在加载第 " .. tostring(page) .. " 页...")
app.set_visible("status_text", true)
app.http_get(url, function(body, err)
isLoading = false
local respBody = tostring(body or "")
local respErr = tostring(err or "")
if respErr ~= "" then
app.set_text("status_text", "加载失败: " .. respErr)
app.toast("网络请求失败:" .. respErr)
return
end
if respBody == "" then
app.set_text("status_text", "服务器返回空数据")
app.toast("接口无返回内容")
return
end
local result = app.json_decode(respBody)
if type(result) ~= "table" then
app.set_text("status_text", "JSON数据解析失败")
app.toast("数据格式错误")
return
end
local code = tonumber(result.code or 0)
if code ~= 200 then
local msg = tostring(result.msg or "未知业务错误")
app.set_text("status_text", "接口错误: " .. msg)
app.toast("业务异常:" .. msg)
return
end
local data = result.data or {}
local list = data.list or {}
pageAppData = list
totalItems = tonumber(data.total or 0)
currentPage = tonumber(data.page or page)
if #categories <= 0 then
categories = extractCategories(list)
end
updateCategoryButtons()
local statusText = "共 " .. tostring(totalItems) .. " 个应用"
if currentCategory ~= "" then
statusText = "分类: " .. currentCategory .. " | " .. statusText
end
app.set_text("status_text", statusText)
app.set_visible("divider_text", true)
hideAllAppEntries()
local appCount = #list
if appCount > 0 then
local renderCount = math.min(appCount, MAX_LIST_ITEMS)
for i = 1, renderCount do
local item = list[i] or {}
-- 图标
local iconPath = tostring(item.icon or "")
if iconPath ~= "" then
app.set_image("app_icon_" .. i, IMAGE_DOMAIN .. "/" .. iconPath)
app.set_visible("app_icon_" .. i, true)
end
-- 应用名
local nameText = tostring(item.app_name or "未知应用")
if tonumber(item.is_top or 0) == 1 then
nameText = "⭐ " .. nameText
end
local ver = tostring(item.version or "")
if ver ~= "" then
nameText = nameText .. " v" .. ver
end
app.set_text("app_name_" .. i, nameText)
app.set_visible("app_name_" .. i, true)
-- 包名
local pkg = tostring(item.package_name or "")
if pkg ~= "" then
app.set_text("app_pkg_" .. i, "📦 " .. pkg)
app.set_visible("app_pkg_" .. i, true)
end
-- 信息行
local infoParts = {
"💾 " .. formatSize(item.size),
"⬇ " .. formatDownloads(item.downloads)
}
local catStr = tostring(item.category or "")
if catStr ~= "" then
table.insert(infoParts, "🏷 " .. catStr)
end
app.set_text("app_info_" .. i, table.concat(infoParts, " | "))
app.set_visible("app_info_" .. i, true)
-- 详情按钮渲染
app.set_text("btn_detail_" .. i, "🔗 查看详情")
app.set_visible("btn_detail_" .. i, true)
-- 分隔线
if i < appCount and i < MAX_LIST_ITEMS then
app.set_visible("separator_" .. i, true)
end
end
else
app.set_visible("empty_text", true)
end
local totalPages = math.max(math.ceil(totalItems / PAGE_SIZE), 1)
app.set_text("page_info", "第 " .. tostring(currentPage) .. " / " .. tostring(totalPages) .. " 页")
app.set_visible("page_info", true)
app.set_visible("btn_prev", currentPage > 1)
app.set_visible("btn_next", (currentPage * PAGE_SIZE) < totalItems)
app.set_visible("btn_refresh", true)
app.set_visible("btn_home", currentPage > 1)
app.toast("加载完成,本页 " .. tostring(appCount) .. " 个应用")
end)
end
-- ============================================================
-- UI 节点构建(仅文档支持控件与属性)
-- ============================================================
local listChildren = {}
-- 状态文字
table.insert(listChildren, ui.text({
id = "status_text",
text = "点击上方按钮加载数据",
size = 14,
color = "#888888",
center = true,
margin = 8
}))
-- 分类标题
table.insert(listChildren, ui.text({
id = "category_label",
text = "分类筛选:",
size = 14,
margin = 4,
visible = false,
}))
-- 全部分类按钮
table.insert(listChildren, ui.button({
id = "btn_all",
text = "全部",
color = "#007AFF",
margin = 2,
visible = false,
on_click = function()
if currentCategory ~= "" then
currentCategory = ""
loadApps(1)
end
end
}))
-- 5个分类按钮(固化下标,闭包无nil风险)
for i = 1, 5 do
local bindIdx = i
table.insert(listChildren, ui.button({
id = "cat_btn_" .. bindIdx,
text = "",
color = "#666666",
margin = 2,
visible = false,
on_click = function()
local targetCat = categories[bindIdx]
if target and currentCategory ~= targetCat then
currentCategory = targetCat
loadApps(1)
end
end
}))
end
table.insert(listChildren, ui.text({
id = "more_cat_text",
text = "",
size = 12,
color = "#999999",
center = true,
margin = 2,
visible = false,
}))
table.insert(listChildren, ui.spacer({ height = 6 }))
-- 分割线
table.insert(listChildren, ui.text({
id = "divider_text",
text = "━━━ 应用列表 ━━━",
size = 12,
color = "#CCCCCC",
center = true,
margin = 4,
visible = false,
}))
-- 循环创建10条应用条目(含详情按钮)
for i = 1, MAX_LIST_ITEMS do
local bindIndex = i
table.insert(listChildren, ui.image({
id = "app_icon_" .. i,
url = "",
height = 52,
margin = 4,
visible = false
}))
table.insert(listChildren, ui.text({
id = "app_name_" .. i,
text = "",
size = 17,
margin = 2,
visible = false
}))
table.insert(listChildren, ui.text({
id = "app_pkg_" .. i,
text = "",
size = 12,
color = "#666666",
margin = 2,
visible = false
}))
table.insert(listChildren, ui.text({
id = "app_info_" .. i,
text = "",
size = 12,
color = "#999999",
margin = 2,
visible = false
}))
-- 查看详情按钮:闭包固化下标,直接调用跳转函数
table.insert(listChildren, ui.button({
id = "btn_detail_" .. i,
text = "",
color = "#007AFF",
margin = 2,
visible = false,
on_click = function()
jumpDetail(bindIndex)
end
}))
-- 条目分隔
if i < MAX_LIST_ITEMS then
table.insert(listChildren, ui.spacer({ height = 4 }))
table.insert(listChildren, ui.text({
id = "separator_" .. i,
text = "─────────────────────",
size = 10,
color = "#EEEEEE",
center = true,
margin = 2,
visible = false
}))
table.insert(listChildren, ui.spacer({ height = 4 }))
end
end
-- 空数据提示
table.insert(listChildren, ui.text({
id = "empty_text",
text = "暂无匹配的应用数据",
size = 15,
color = "#999999",
center = true,
margin = 20,
visible = false
}))
-- 分页区域
table.insert(listChildren, ui.spacer({ height = 6 }))
table.insert(listChildren, ui.text({
id = "page_info",
text = "",
size = 13,
color = "#AAAAAA",
center = true,
margin = 4,
visible = false,
}))
table.insert(listChildren, ui.button({
id = "btn_prev",
text = "◀ 上一页",
margin = 4,
visible = false,
on_click = function()
if currentPage > 1 then
loadApps(currentPage - 1)
end
end
}))
table.insert(listChildren, ui.button({
id = "btn_next",
text = "下一页 ▶",
margin = 4,
visible = false,
on_click = function()
loadApps(currentPage + 1)
end
}))
table.insert(listChildren, ui.spacer({ height = 6 }))
table.insert(listChildren, ui.button({
id = "btn_refresh",
text = "🔄 刷新当前页",
margin = 4,
visible = false,
on_click = function()
loadApps(currentPage)
end
}))
table.insert(listChildren, ui.button({
id = "btn_home",
text = "🏠 回到首页",
margin = 4,
visible = false,
on_click = function()
loadApps(1)
end
}))
-- ============================================================
-- 页面根节点(仅title+children,无自定义参数)
-- ============================================================
return ui.page({
title = "拾物应用商店oc小程序版 ver1.4.1",
children = {
ui.button({
text = "加载应用列表",
color = "#007AFF",
margin = 8,
on_click = function()
loadApps(1)
end
}),
ui.list({
children = listChildren,
margin = 4
}),
ui.spacer({ height = 12 }),
ui.text({
text = "使用说明",
size = 16,
center = true,
margin = 4
}),
ui.text({
text = "点击上方按钮加载数据\n查看详情暂不可用\n翻页浏览列表\n",
size = 13,
color = "#666666",
margin = 8
}),
ui.text({
text = "© 2026 拾物应用商店 版权所有",
size = 14,
color = "#555555",
center = true,
margin = 10
})
}
})