├── .gitignore
├── LICENSE
├── README.md
├── api
├── Poncon.php
├── add_collect.php
├── config.default.php
├── delete_collect.php
├── fenci.php
├── get_collect_list.php
├── get_collect_list_by_tag.php
├── get_tag_list.php
├── get_title.php
├── login.php
├── public_share_list.php
├── register.php
└── search.php
├── css
└── index.css
├── favicon.ico
├── img
├── at_phone.jpg
├── cat-2722309_640.png
├── chevron-left-solid.svg
├── insect-6626635_1920.jpg
├── plus-solid.svg
├── trash-can-solid.svg
├── uTools_1656678414889.png
├── uTools_1656678450484.png
├── uTools_1656678465902.png
├── uTools_1656678546233.png
├── uTools_1656678565171.png
└── uTools_1656679524839.png
├── index.php
├── js
├── index.js
├── poncon.js
└── poncon.min.js
├── public
├── api
│ ├── Poncon.php
│ ├── add_collect.php
│ ├── config.default.php
│ ├── delete_collect.php
│ ├── fenci.php
│ ├── get_collect_list.php
│ ├── get_collect_list_by_tag.php
│ ├── get_tag_list.php
│ ├── get_title.php
│ ├── login.php
│ ├── public_share_list.php
│ ├── register.php
│ └── search.php
├── css
│ └── index.css
├── img
│ ├── cat-2722309_640.png
│ ├── chevron-left-solid.svg
│ ├── insect-6626635_1920.jpg
│ ├── plus-solid.svg
│ └── trash-can-solid.svg
├── index.php
├── js
│ ├── index.js
│ └── poncon.js
└── share
│ └── index.php
└── share
└── index.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # 配置
2 | config.php
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mypages
2 |
3 | 一款标签化管理网页收藏的工具
4 |
5 | ## 开发宗旨
6 |
7 | - 简约、轻量、便捷
8 |
9 | ## 安装说明
10 |
11 | - 将 `public` 目录上传到主机
12 | - 复制 `config.default.php` 为 `config.php`
13 | - 将 `config.php` 中的数据库信息填写完整
14 | - 运行 `index.html` 即可
15 |
16 | ## 项目介绍
17 |
18 | 当你想要收藏一个网站,而苦恼应该怎么分类的话,你可以尝试使用标签管理法。
19 |
20 | 对于一个综合型的网站,我们为其打上“影视”、“免费”、“学术”等标签,方便我们随性标记和下次方便找到。
21 |
22 | 我们平台推出了“标签精确匹配方法”,你可以按照不同的标签组合匹配出更加符合要求的记录,也提高了标签的复用性。
23 |
24 | 我们可以采用“联想法”去定义我们的标签序列,因为一般情况下,我们会输入我们联想到的关键词去匹配结果,我们将最容易联想的关键词作为标签,附与我们的收藏记录中,并且我们要求标签的定义需要遵从精简的原则,比如“编程教程视频”,我们需要拆解为“编程”、“教程”、“视频”,方便我们下次匹配如“搞笑+视频”、“编程+视频”这样的组合。
25 |
26 | 如果一次联想不能让我们定义出满意的标签序列,在我们下一次匹配某条记录时,可以根据匹配情况对该记录的标签系列进行编辑,以增加下次匹配的正确性。
27 |
28 | 我们在搜索模块上,分为了全局搜索和标签匹配,前者会按照记录的标题、URL 、标签、备注进行综合搜索,而后者是按照指定的标签组合进行精准匹配,我们可以结合两种方法,不断完善我们各自的标签系统。
29 |
30 | 我们平台支持增加收藏记录、定义标签序列、记录随时可编辑、主页共享、多功能搜索等功能。
31 |
32 | 我们的这套方法,会随着我们收藏记录和标签数量的增加而更加贴合我们的使用习惯,让我们从此解放大脑,随性收藏,不再错过精彩内容。
33 |
34 | ## 功能
35 |
36 | - 用户登录注册
37 | - 添加URL收藏,一键获取title,并支持设置标签
38 | - 整体列表按时间排序,可按标签筛选列表
39 | - 可随时编辑和删除收藏记录
40 | - 根据收藏列表自动生成标签列表,用户可多选标签进行一次性加载
41 | - 可生成个人收藏页,不显示私密部分(bata)
42 | - 主页上显示完整收藏列表,列表项上包含标签
43 | - 单击按钮弹出模态框,可以新增收藏
44 | - 点击列表中的标签,弹出模态框加载该标签(bata)
45 | - 不支持重复URL
46 |
47 | ### 待改进
48 |
49 | - 接入微信公众号用户系统
50 | - 标签筛选列表改为数量排序
51 | - 标签筛选时自动滚动滚动条
52 |
53 | ### 标签定义规则推荐
54 |
55 | - 标签能拆解的,尽量拆解,比如 `编程教程`,拆成 `编程` + `教程`
56 | - 对于实在不能拆解的,需保留,比如 `搜索引擎` 不能拆成 `搜索` + `引擎`
57 | - 这样一来,可以最大限度减少标签数量,提高标签复用性和筛选效率
58 |
59 | ## 关于
60 |
61 | - 作者:欧阳鹏
62 | - 个人主页:https://ouyangpeng.top
63 | - 一直在努力学习和探索中,欢迎关注我~
64 |
65 | ## 示意图
66 |
67 | 
68 |
69 | 
70 |
71 | 
72 |
73 | 
74 |
75 | 
76 |
77 | 
78 |
--------------------------------------------------------------------------------
/api/Poncon.php:
--------------------------------------------------------------------------------
1 | $code,
108 | 'msg' => $msg
109 | ]));
110 | }
111 |
112 | /**
113 | * 返回成功信息,语法:success($msg);
114 | * @param string $msg 成功信息
115 | */
116 | function success($msg, ...$args)
117 | {
118 | echo json_encode([
119 | 'code' => 200,
120 | 'msg' => $msg,
121 | 'data' => isset($args[0]) ? $args[0] : null
122 | ]);
123 | }
124 |
125 | /**
126 | * 获取配置信息,语法:getConfig();
127 | */
128 | function getConfig()
129 | {
130 | require 'config.php';
131 | return $config;
132 | }
133 |
134 | /**
135 | * 初始化数据库,语法:initDB();
136 | */
137 | function initDb()
138 | {
139 | $config = $this->getConfig();
140 | $conn = mysqli_connect($config['mysql']['host'], $config['mysql']['user'], $config['mysql']['pass'], $config['mysql']['db']);
141 | if (!$conn) {
142 | die(json_encode([
143 | 'code' => 903,
144 | 'msg' => '数据库错误'
145 | ]));
146 | }
147 |
148 | // 新建用户表
149 | $table = $config['table']['user'];
150 | $sql = "CREATE TABLE IF NOT EXISTS `$table` (
151 | `id` int(11) NOT NULL AUTO_INCREMENT,
152 | `username` varchar(255) NOT NULL, -- 用户名
153 | `password` varchar(255) NOT NULL, -- 密码 md5密文
154 | `register_time` int(11) NOT NULL, -- 注册时间
155 | PRIMARY KEY (`id`) -- 主键
156 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
157 | $result = mysqli_query($conn, $sql);
158 | if (!$result) {
159 | $this->error(903, '数据库错误');
160 | }
161 | // 新建收藏表
162 | $table = $config['table']['collect'];
163 | $sql = "CREATE TABLE IF NOT EXISTS `$table` (
164 | `id` int(11) NOT NULL AUTO_INCREMENT,
165 | `username` varchar(255) NOT NULL, -- 收藏者用户名
166 | `title` TEXT NOT NULL, -- 网页标题
167 | `url` TEXT NOT NULL, -- 网址
168 | `update_time` int(11) NOT NULL, -- 更新时间
169 | `tag_list` TEXT NOT NULL, -- 标签列表,以逗号分隔
170 | `note` TEXT NOT NULL, -- 备注
171 | `private` int(11) NOT NULL, -- 0:公开 1:私密
172 | PRIMARY KEY (`id`) -- 主键
173 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
174 | $result = mysqli_query($conn, $sql);
175 | if (!$result) {
176 | $this->error(903, '数据库错误');
177 | }
178 | return $conn;
179 | }
180 |
181 | /**
182 | * 登录验证,语法:login($conn, $username, $password);
183 | * @param object $conn 数据库连接
184 | * @param string $username 用户名
185 | * @param string $password 密码
186 | * @return array|null
187 | */
188 | function login($conn, $username, $password)
189 | {
190 | $config = $this->getConfig();
191 | $table = $config['table']['user'];
192 | $sql = "SELECT * FROM `$table` WHERE `username` = '$username' AND `password` = '$password'";
193 | $result = mysqli_query($conn, $sql);
194 | if (!$result) {
195 | $this->error(903, '数据库错误');
196 | }
197 | $row = mysqli_fetch_assoc($result);
198 | if (!$row) {
199 | $this->error(907, '用户名或密码错误');
200 | }
201 | return $row;
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/api/add_collect.php:
--------------------------------------------------------------------------------
1 | initDb();
14 |
15 | $username = $poncon->POST('username', null, true);
16 | $password = $poncon->POST('password', null, true);
17 | $tags = $poncon->POST('tags', null, true); // JSON数组[...]
18 | $title = $poncon->POST('title', null, true);
19 | $url = $poncon->POST('url', null, true);
20 | $private = $poncon->POST('private', 0, true); // 0:公开 1:私密
21 | $note = $poncon->POST('note', null, true); // 备注
22 | $update_time = time();
23 | $mode = $poncon->POST('mode', 'add', true); // add:新增 update:更新
24 |
25 | if (!$username || !$password || !$title || !$url) {
26 | $poncon->error(900, '参数缺失');
27 | }
28 |
29 | // 登录验证
30 | $poncon->login($conn, $username, $password);
31 |
32 | $config = $poncon->getConfig();
33 | $table = $config['table']['collect'];
34 |
35 | // 判断URL是否存在
36 |
37 | $sql = "SELECT `url` FROM `$table` WHERE `url` = '$url' LIMIT 1;";
38 | $result = mysqli_query($conn, $sql);
39 | if (mysqli_num_rows($result) > 0 && $mode == 'add') {
40 | $poncon->error(904, '记录已经存在');
41 | } else if (mysqli_num_rows($result) == 0 && $mode == 'update') {
42 | $poncon->error(904, '记录不存在');
43 | }
44 | if ($mode == 'add') {
45 | // 增加收藏
46 | $sql = "INSERT INTO `$table` (`username`, `tag_list`, `update_time`, `title`, `url`, `private`, `note`) VALUES ('$username', '$tags', $update_time, '$title', '$url', $private, '$note');";
47 | } else if ($mode == 'update') {
48 | // 更新
49 | $sql = "UPDATE `$table` SET `tag_list` = '$tags', `title` = '$title', `url` = '$url', `private` = '$private', `update_time` = '$update_time', `note` = '$note' WHERE `url` = '$url' LIMIT 1;";
50 | }
51 |
52 | $result = mysqli_query($conn, $sql);
53 | if (!$result) {
54 | $poncon->error(903, '数据库错误');
55 | }
56 |
57 | $poncon->success('成功');
58 |
--------------------------------------------------------------------------------
/api/config.default.php:
--------------------------------------------------------------------------------
1 | [
10 | 'host' => 'localhost',
11 | 'user' => 'root',
12 | 'pass' => '', // 数据库密码
13 | 'db' => '' // 数据库名称
14 | ],
15 | 'table' => [
16 | 'user' => 'mypages_user', // 用户表
17 | 'collect' => 'mypages_collect' // 收藏表
18 | ]
19 | ];
20 |
21 |
--------------------------------------------------------------------------------
/api/delete_collect.php:
--------------------------------------------------------------------------------
1 | initDb();
13 |
14 | $config = $poncon->getConfig();
15 |
16 | $data = [];
17 |
18 | $table = $config['table']['collect'];
19 |
20 | $username = $poncon->POST('username', null, true);
21 | $password = $poncon->POST('password', null, true);
22 | // 通过URL和时间戳去删除收藏
23 | $url = $poncon->POST('url', null, true);
24 | $time = $poncon->POST('time', null, true);
25 |
26 | if (!$username || !$password || !$url || !$time) {
27 | $poncon->error(900, '参数缺失');
28 | }
29 |
30 | $poncon->login($conn, $username, $password);
31 |
32 | $sql = "DELETE FROM `$table` WHERE `username` = '$username' AND `url` = '$url' AND `update_time` = '$time';";
33 | $result = mysqli_query($conn, $sql);
34 |
35 | if ($result) {
36 | $poncon->success('删除成功');
37 | } else {
38 | $poncon->error(910, '删除失败');
39 | }
40 |
--------------------------------------------------------------------------------
/api/fenci.php:
--------------------------------------------------------------------------------
1 | GET('text', '', true);
14 |
15 | $result = $poncon->request('http://39.96.43.154:8080/api', 'POST', json_encode(['text' => $text]), 'Content-Type: application/json');
16 |
17 | $result = json_decode($result, true);
18 |
19 | $words = $result['words'];
20 |
21 | $data = [];
22 |
23 | foreach ($words as $word) {
24 | $data[] = $word['text'];
25 | }
26 |
27 | $poncon->success('分词成功', $data);
28 |
--------------------------------------------------------------------------------
/api/get_collect_list.php:
--------------------------------------------------------------------------------
1 | initDb();
15 |
16 | $data = [];
17 |
18 | $config = $poncon->getConfig();
19 | $table = $config['table']['collect'];
20 |
21 | $username = $poncon->POST('username', null, true);
22 | $password = $poncon->POST('password', null, true);
23 | $page = $poncon->POST('page', 0, true);
24 | $pageSize = $poncon->POST('pageSize', 36, true);
25 | $offset = $page * $pageSize;
26 | if (!$username || !$password) {
27 | $poncon->error(900, '参数缺失');
28 | }
29 |
30 | // 登录验证
31 | $poncon->login($conn, $username, $password);
32 |
33 |
34 |
35 |
36 | $sql = "SELECT * FROM `$table` WHERE `username` = '$username' ORDER BY `update_time` DESC LIMIT $pageSize OFFSET $offset;";
37 | $result = mysqli_query($conn, $sql);
38 |
39 | if (!$result) {
40 | $poncon->error(903, '数据库错误');
41 | }
42 |
43 |
44 | while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
45 | $row['tag_list'] = json_decode($row['tag_list'], true);
46 | unset($row['id']);
47 | unset($row['username']);
48 | array_push($data, $row);
49 | }
50 | $poncon->success('获取成功', $data);
51 |
--------------------------------------------------------------------------------
/api/get_collect_list_by_tag.php:
--------------------------------------------------------------------------------
1 | initDb();
13 |
14 | $config = $poncon->getConfig();
15 |
16 | $username = $poncon->POST('username', null, true);
17 | $password = $poncon->POST('password', null, true);
18 | $page = $poncon->POST('page', 0, true);
19 | $pageSize = $poncon->POST('pageSize', 36, true);
20 | $offset = $page * $pageSize;
21 | $tags = json_decode($poncon->POST('tags', '[]'), true);
22 |
23 | $data = [];
24 |
25 | $config = $poncon->getConfig();
26 | $table = $config['table']['collect'];
27 |
28 | if (!$username || !$password) {
29 | $poncon->error(900, '参数缺失');
30 | }
31 |
32 | $poncon->login($conn, $username, $password);
33 |
34 | // 查询包含标签列表的数据
35 | $sql = "SELECT * FROM `$table` WHERE `username` = '$username' AND (`tag_list` LIKE '%\"" . implode("\"%' AND `tag_list` LIKE '%\"", $tags) . "\"%') LIMIT $pageSize OFFSET $offset;";
36 |
37 | $result = mysqli_query($conn, $sql);
38 |
39 | if (!$result) {
40 | $poncon->error(903, '数据库错误');
41 | }
42 |
43 | while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
44 | $row['tag_list'] = json_decode($row['tag_list'], true);
45 | unset($row['id']);
46 | unset($row['username']);
47 | array_push($data, $row);
48 | }
49 | $poncon->success('获取成功', $data);
50 |
--------------------------------------------------------------------------------
/api/get_tag_list.php:
--------------------------------------------------------------------------------
1 | initDb();
13 |
14 | $config = $poncon->getConfig();
15 |
16 | $username = $poncon->POST('username', null, true);
17 | $password = $poncon->POST('password', null, true);
18 |
19 | if (!$username || !$password) {
20 | $poncon->error(900, '参数缺失');
21 | }
22 |
23 | $poncon->login($conn, $username, $password);
24 |
25 | $sql = "SELECT `tag_list` FROM `{$config['table']['collect']}` WHERE `username` = '$username' ORDER BY `update_time` DESC;";
26 |
27 | $result = mysqli_query($conn, $sql);
28 |
29 | if (!$result) {
30 | $poncon->error(903, '数据库错误');
31 | }
32 | $data = [];
33 |
34 | while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
35 | $list = json_decode($row['tag_list'], true);
36 | foreach ($list as $tag) {
37 | if (!isset($data[$tag])) {
38 | $data[$tag] = 1;
39 | } else {
40 | $data[$tag]++;
41 | }
42 | }
43 | }
44 |
45 | $poncon->success('获取成功', $data);
46 |
--------------------------------------------------------------------------------
/api/get_title.php:
--------------------------------------------------------------------------------
1 | POST('url', null, true);
12 |
13 | $input = json_decode('{
14 | "options": {
15 | "http": {
16 | "method": "GET",
17 | "header": "Content-type: application/x-www-form-urlencoded\n",
18 | "content": "",
19 | "timeout": 900
20 | },
21 | "ssl": {
22 | "verify_peer": false,
23 | "verify_peer_name": false
24 | }
25 | },
26 | "url": "' . $url . '",
27 | "charset": "utf-8"
28 | }', true);
29 |
30 | // $http是个数组,前端需要传入一个JSON
31 | $options = $input['options'];
32 | $charset = $input['charset'];
33 | if ($charset != 'utf-8') {
34 | $header = $options['http']['header'];
35 | $options['http']['header'] = iconv('utf-8', $charset, $header);
36 | }
37 | $context = stream_context_create($options);
38 | $ym = file_get_contents($input['url'], false, $context);
39 | foreach ($http_response_header as $key => $value) {
40 | $item = explode(':', $value);
41 | if (strtolower($item[0]) == 'content-encoding' && strtolower($item[1]) == ' gzip') {
42 | $result = gzdecode($result);
43 | }
44 | }
45 |
46 | if ($charset != 'utf-8') {
47 | $result = iconv($charset, 'utf-8//IGNORE', $result);
48 | }
49 |
50 |
51 |
52 | if (!$url) {
53 | $poncon->error(900, '参数缺失');
54 | }
55 |
56 |
57 | $title = $poncon->sj($ym, '
`}),t.find(".tags").html(e).attr("data-tags",encodeURIComponent(JSON.stringify(this.tagList))),t.find(".update_time").html(this.parseDate((new Date).getTime()))},cleanInput(){var t=$(".modal-addCollect");t.find(".input-url").val(""),t.find(".input-title").val(""),t.find(".input-tagName").val(""),this.tagList=[],t.find(".tagList").html(""),t.find(".input-note").val("")},removeArray(e,i){return e.map((t,a)=>{t==i&&e.splice(a,1)}),e},makeTags(t,a){var e="";if("all"==a){for(var i in t)e+=`
`}),t.find(".tags").html(e).attr("data-tags",encodeURIComponent(JSON.stringify(this.tagList))),t.find(".update_time").html(this.parseDate((new Date).getTime()))},cleanInput(){var t=$(".modal-addCollect");t.find(".input-url").val(""),t.find(".input-title").val(""),t.find(".input-tagName").val(""),this.tagList=[],t.find(".tagList").html(""),t.find(".input-note").val("")},removeArray(e,i){return e.map((t,a)=>{t==i&&e.splice(a,1)}),e},makeTags(t,a){var e="";if("all"==a){for(var i in t)e+=`