dbcs07 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,147 @@
1
+ // Tizen 4.0专属:修复同步请求阻塞问题
2
+ var express = require('express');
3
+ var https = require('https');
4
+ var path = require('path');
5
+ var net = require('net');
6
+
7
+ var app = express();
8
+ var PORT = 8085;
9
+ var HOST = '127.0.0.1';
10
+
11
+ // 全局状态(启动时直接初始化,避免检测中)
12
+ var systemStatus = {
13
+ server: { status: 'unknown', msg: '' },
14
+ port: { status: 'unknown', msg: '' },
15
+ douban: { status: 'unknown', msg: '' },
16
+ timestamp: new Date().getTime()
17
+ };
18
+
19
+ // 1. 启动时立即检测端口(同步执行,避免后续检测中)
20
+ function checkPortSync() {
21
+ try {
22
+ var tester = net.createServer().listen(PORT, HOST);
23
+ tester.close();
24
+ systemStatus.port = { status: 'success', msg: `端口${PORT}可用` };
25
+ } catch (err) {
26
+ if (err.code === 'EADDRINUSE') {
27
+ systemStatus.port = { status: 'error', msg: `端口${PORT}被占用,请换端口` };
28
+ } else {
29
+ systemStatus.port = { status: 'error', msg: `端口检测失败:${err.message}` };
30
+ }
31
+ }
32
+ }
33
+
34
+ // 2. 启动时立即检测豆瓣(异步,但提前执行)
35
+ function checkDoubanAsync() {
36
+ var doubanUrl = 'https://movie.douban.com/j/search_subjects?type=movie&tag=热映&page_limit=5&page_start=0';
37
+ var options = {
38
+ method: 'GET',
39
+ headers: {
40
+ 'User-Agent': 'Mozilla/5.0 (SMART-TV; Linux; Tizen 4.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
41
+ 'Referer': 'https://movie.douban.com/'
42
+ },
43
+ timeout: 10000
44
+ };
45
+
46
+ var reqObj = https.request(doubanUrl, options, (res) => {
47
+ var data = '';
48
+ res.on('data', (chunk) => data += chunk);
49
+ res.on('end', () => {
50
+ try {
51
+ JSON.parse(data);
52
+ systemStatus.douban = { status: 'success', msg: '豆瓣接口访问成功' };
53
+ } catch (e) {
54
+ systemStatus.douban = { status: 'error', msg: `豆瓣数据解析失败:${e.message}` };
55
+ }
56
+ });
57
+ });
58
+
59
+ reqObj.on('error', (e) => {
60
+ systemStatus.douban = { status: 'error', msg: `豆瓣接口访问失败:${e.message}(IP可能被拦截)` };
61
+ });
62
+
63
+ reqObj.setTimeout(10000, () => {
64
+ reqObj.abort();
65
+ systemStatus.douban = { status: 'error', msg: '豆瓣请求超时(10秒)' };
66
+ });
67
+
68
+ reqObj.end();
69
+ }
70
+
71
+ // 3. 跨域配置
72
+ app.use(function(req, res, next) {
73
+ res.setHeader('Access-Control-Allow-Origin', '*');
74
+ res.setHeader('Content-Type', 'application/json;charset=utf-8');
75
+ if (req.method === 'OPTIONS') {
76
+ res.status(200).end();
77
+ return;
78
+ }
79
+ next();
80
+ });
81
+
82
+ // 4. 状态接口(返回已初始化的状态,无检测中)
83
+ app.get('/status', function(req, res) {
84
+ systemStatus.timestamp = new Date().getTime();
85
+ res.send(systemStatus);
86
+ });
87
+
88
+ // 5. 豆瓣数据接口
89
+ app.get('/get-douban', function(req, res) {
90
+ var doubanUrl = 'https://movie.douban.com/j/search_subjects?type=movie&tag=热映&page_limit=10&page_start=0';
91
+ var options = {
92
+ method: 'GET',
93
+ headers: {
94
+ 'User-Agent': 'Mozilla/5.0 (SMART-TV; Linux; Tizen 4.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
95
+ 'Referer': 'https://movie.douban.com/',
96
+ 'Host': 'movie.douban.com'
97
+ },
98
+ timeout: 30000
99
+ };
100
+
101
+ var reqObj = https.request(doubanUrl, options, function(response) {
102
+ var data = '';
103
+ response.on('data', function(chunk) { data += chunk; });
104
+ response.on('end', function() {
105
+ try {
106
+ var jsonData = JSON.parse(data);
107
+ res.send(jsonData);
108
+ } catch (e) {
109
+ res.status(500).send({ msg: `解析失败:${e.message}` });
110
+ }
111
+ });
112
+ });
113
+
114
+ reqObj.on('error', function(e) {
115
+ res.status(500).send({ msg: `请求豆瓣失败:${e.message}` });
116
+ });
117
+
118
+ reqObj.setTimeout(30000, function() {
119
+ reqObj.abort();
120
+ res.status(504).send({ msg: '请求超时(30秒)' });
121
+ });
122
+
123
+ reqObj.end();
124
+ });
125
+
126
+ // 6. 静态资源+根路由
127
+ var staticDir = path.join(__dirname, 'static');
128
+ app.use(express.static(staticDir));
129
+
130
+ app.get('/', function(req, res) {
131
+ var htmlPath = path.join(staticDir, 'douban-tv.html');
132
+ res.sendFile(htmlPath, function(err) {
133
+ if (err) {
134
+ systemStatus.server = { status: 'error', msg: `页面缺失:${htmlPath}` };
135
+ res.status(404).send(`<h1 style="color:red;">页面缺失:${err.message}</h1>`);
136
+ }
137
+ });
138
+ });
139
+
140
+ // 7. 启动服务(先检测端口,再启动)
141
+ checkPortSync(); // 同步检测端口,立即出结果
142
+ systemStatus.server = { status: 'success', msg: `服务已启动:http://${HOST}:${PORT}` };
143
+ checkDoubanAsync(); // 异步检测豆瓣,不阻塞启动
144
+
145
+ app.listen(PORT, HOST, function() {
146
+ console.log('✅ ' + systemStatus.server.msg);
147
+ });
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "dbcs07",
3
+ "version": "1.0.0",
4
+ "main": "douban-tv-server.js",
5
+ "packageType": "app",
6
+ "appName": "douban",
7
+ "appPath": "static/douban-tv.html",
8
+ "keys": [
9
+ "MediaPlayPause",
10
+ "MediaPlay",
11
+ "MediaPause",
12
+ "MediaStop",
13
+ "MediaTrackPrevious",
14
+ "MediaTrackNext",
15
+ "MediaRewind",
16
+ "MediaFastForward"
17
+ ],
18
+ "serviceFile": "douban-tv-server.js",
19
+ "dependencies": {
20
+ "express": "^4.17.1",
21
+ "http-proxy-middleware": "^3.0.5"
22
+ }
23
+ }
@@ -0,0 +1,190 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>TizenBrew 排查工具</title>
7
+ <style>
8
+ body {
9
+ margin: 20px;
10
+ padding: 0;
11
+ font-family: Arial, sans-serif;
12
+ background: #000;
13
+ color: #fff;
14
+ font-size: 18px;
15
+ -webkit-user-select: none; /* Tizen电视适配 */
16
+ }
17
+ .check-item {
18
+ margin: 20px 0;
19
+ padding: 15px;
20
+ border-radius: 8px;
21
+ border: 1px solid #333;
22
+ tabindex: 0; /* 遥控器可聚焦 */
23
+ outline: none;
24
+ }
25
+ .success { background: #003300; border-color: #00ff00; }
26
+ .error { background: #333300; border-color: #ff0000; }
27
+ .unknown { background: #333300; border-color: #ffff00; }
28
+ .title { font-size: 24px; font-weight: bold; margin-bottom: 10px; }
29
+ .msg { font-size: 16px; color: #ccc; margin-top: 10px; }
30
+ .btn {
31
+ padding: 10px 20px;
32
+ background: #0066cc;
33
+ color: #fff;
34
+ border: none;
35
+ border-radius: 4px;
36
+ font-size: 18px;
37
+ margin: 10px 5px;
38
+ tabindex: 1; /* 遥控器优先聚焦 */
39
+ outline: 2px solid transparent;
40
+ }
41
+ .btn:focus { outline: 2px solid #00ff00; } /* 焦点高亮 */
42
+ .btn-secondary { background: #cc6600; }
43
+ .step { font-size: 20px; margin: 10px 0; color: #00ff00; }
44
+ #movieList { margin-top: 30px; padding: 15px; border-top: 1px solid #666; }
45
+ .loading { color: #ffff00; }
46
+ </style>
47
+ </head>
48
+ <body>
49
+ <h1 style="text-align:center; tabindex:0;">TizenBrew 代理排查(Tizen 4.0)</h1>
50
+
51
+ <!-- 检测项(加tabindex,遥控器可聚焦) -->
52
+ <div class="check-item unknown" id="serverStatus" tabindex="0">
53
+ <div class="title">⚠️ 步骤1:服务启动状态</div>
54
+ <div class="msg">加载中...</div>
55
+ </div>
56
+
57
+ <div class="check-item unknown" id="portStatus" tabindex="0">
58
+ <div class="title">⚠️ 步骤2:端口占用检测</div>
59
+ <div class="msg">加载中...</div>
60
+ </div>
61
+
62
+ <div class="check-item unknown" id="doubanStatus" tabindex="0">
63
+ <div class="title">⚠️ 步骤3:豆瓣接口连通性</div>
64
+ <div class="msg">加载中...</div>
65
+ </div>
66
+
67
+ <div class="check-item unknown" id="dataStatus" tabindex="0">
68
+ <div class="title">⚠️ 步骤4:豆瓣数据加载</div>
69
+ <div class="msg">未检测</div>
70
+ </div>
71
+
72
+ <!-- 按钮(加tabindex,适配遥控器) -->
73
+ <button class="btn" onclick="refreshAll()" tabindex="1">🔄 刷新状态</button>
74
+ <button class="btn btn-secondary" onclick="testData()" tabindex="2">📝 测试数据</button>
75
+
76
+ <div id="movieList" tabindex="0">
77
+ <div class="step">📌 豆瓣热映电影(测试成功后显示)</div>
78
+ </div>
79
+
80
+ <script>
81
+ // Tizen 4.0适配:异步请求,避免阻塞
82
+ var statusStyle = {
83
+ success: { cls: 'success', icon: '✅' },
84
+ error: { cls: 'error', icon: '❌' },
85
+ unknown: { cls: 'unknown', icon: '⚠️' }
86
+ };
87
+
88
+ // 页面加载后异步检测(不阻塞)
89
+ window.onload = function() {
90
+ setTimeout(checkStatus, 500); // 延迟500ms,让页面先渲染
91
+ };
92
+
93
+ // 1. 异步获取状态(核心修复)
94
+ function checkStatus() {
95
+ var xhr = new XMLHttpRequest();
96
+ xhr.open('GET', 'http://127.0.0.1:8085/status?' + new Date().getTime(), true); // 异步!
97
+ xhr.onload = function() {
98
+ if (xhr.status === 200) {
99
+ try {
100
+ var data = JSON.parse(xhr.responseText);
101
+ updateItem('serverStatus', data.server);
102
+ updateItem('portStatus', data.port);
103
+ updateItem('doubanStatus', data.douban);
104
+ } catch (e) {
105
+ updateItem('serverStatus', { status: 'error', msg: `解析失败:${e.message}` });
106
+ }
107
+ } else {
108
+ updateItem('serverStatus', { status: 'error', msg: `状态请求失败:${xhr.status}` });
109
+ }
110
+ };
111
+ xhr.onerror = function() {
112
+ updateItem('serverStatus', { status: 'error', msg: '无法连接服务,请检查是否启动' });
113
+ updateItem('portStatus', { status: 'error', msg: '端口检测失败:服务未连接' });
114
+ updateItem('doubanStatus', { status: 'error', msg: '豆瓣检测失败:服务未连接' });
115
+ };
116
+ xhr.send(null);
117
+ }
118
+
119
+ // 2. 异步测试数据
120
+ function testData() {
121
+ var dataItem = document.getElementById('dataStatus');
122
+ var movieList = document.getElementById('movieList');
123
+ updateItem('dataStatus', { status: 'unknown', msg: '请求中...' });
124
+ movieList.innerHTML = '<div class="step">📌 豆瓣热映电影(请求中...)</div>';
125
+
126
+ var xhr = new XMLHttpRequest();
127
+ xhr.open('GET', 'http://127.0.0.1:8085/get-douban?' + new Date().getTime(), true);
128
+ xhr.onload = function() {
129
+ if (xhr.status === 200) {
130
+ try {
131
+ var data = JSON.parse(xhr.responseText);
132
+ if (data.subjects && data.subjects.length > 0) {
133
+ updateItem('dataStatus', { status: 'success', msg: '数据加载成功' });
134
+ var html = '<div class="step">📌 豆瓣热映电影(共' + data.subjects.length + '部)</div>';
135
+ for (var i = 0; i < data.subjects.length; i++) {
136
+ var item = data.subjects[i];
137
+ html += `<div style="margin:10px 0;padding:10px;border:1px solid #666;">
138
+ <h3>${i+1}. ${item.title}</h3>
139
+ <p>评分:${item.rating.average || '暂无'}</p>
140
+ </div>`;
141
+ }
142
+ movieList.innerHTML = html;
143
+ } else {
144
+ updateItem('dataStatus', { status: 'error', msg: '豆瓣返回空数据(IP可能被拦截)' });
145
+ }
146
+ } catch (e) {
147
+ updateItem('dataStatus', { status: 'error', msg: `解析失败:${e.message}` });
148
+ }
149
+ } else {
150
+ updateItem('dataStatus', { status: 'error', msg: `请求失败:${xhr.status}` });
151
+ }
152
+ };
153
+ xhr.onerror = function() {
154
+ updateItem('dataStatus', { status: 'error', msg: '数据请求失败(status=0):检查权限/网络' });
155
+ };
156
+ xhr.send(null);
157
+ }
158
+
159
+ // 3. 刷新所有状态
160
+ function refreshAll() {
161
+ updateItem('serverStatus', { status: 'unknown', msg: '加载中...' });
162
+ updateItem('portStatus', { status: 'unknown', msg: '加载中...' });
163
+ updateItem('doubanStatus', { status: 'unknown', msg: '加载中...' });
164
+ checkStatus();
165
+ }
166
+
167
+ // 4. 更新显示
168
+ function updateItem(id, statusData) {
169
+ var item = document.getElementById(id);
170
+ var style = statusStyle[statusData.status] || statusStyle.unknown;
171
+ item.className = 'check-item ' + style.cls;
172
+ var title = item.querySelector('.title').textContent.split(':')[1];
173
+ item.innerHTML = `
174
+ <div class="title">${style.icon} 步骤${id.replace(/\D/g, '')}:${title}</div>
175
+ <div class="msg">${statusData.msg || '无信息'}</div>
176
+ `;
177
+ }
178
+
179
+ // Tizen遥控器适配:按OK键触发按钮点击
180
+ document.addEventListener('keydown', function(e) {
181
+ if (e.keyCode === 13) { // OK键=13
182
+ var focused = document.activeElement;
183
+ if (focused.tagName === 'BUTTON') {
184
+ focused.click();
185
+ }
186
+ }
187
+ });
188
+ </script>
189
+ </body>
190
+ </html>