Compare commits
100 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
48a22e5d2e | |
|
|
e8bc9625af | |
|
|
9f462bfed1 | |
|
|
1677d60b51 | |
|
|
60bbfbb391 | |
|
|
ea9097b124 | |
|
|
c8f183fbff | |
|
|
ac1758b8da | |
|
|
27f1ccdb1a | |
|
|
7b0ed143d4 | |
|
|
64c1750c20 | |
|
|
3d06055292 | |
|
|
0a74c4fc0a | |
|
|
93fa0ce016 | |
|
|
d02c27a8f7 | |
|
|
692ab124aa | |
|
|
f2797f4bbf | |
|
|
f6fd7bda23 | |
|
|
dcdfb5d202 | |
|
|
b52c622f93 | |
|
|
c9ae4bd803 | |
|
|
cbe4ad4e91 | |
|
|
2448ce767b | |
|
|
ba087ae32c | |
|
|
0d5adcd304 | |
|
|
f2f041b7f7 | |
|
|
30878006eb | |
|
|
dd67d8ee64 | |
|
|
075ff1fd0b | |
|
|
d4d65275d6 | |
|
|
8dfe0db390 | |
|
|
72993b46a5 | |
|
|
2e019d26ac | |
|
|
47773c2560 | |
|
|
82b45db461 | |
|
|
7b1401c4f5 | |
|
|
f4f5149e27 | |
|
|
38d6ff2084 | |
|
|
5c756434ee | |
|
|
a09dbf23dd | |
|
|
14d976a12d | |
|
|
c77bf01a08 | |
|
|
c0e3af63c1 | |
|
|
597052515c | |
|
|
d637f070a9 | |
|
|
7044dff709 | |
|
|
53d1bc0ea1 | |
|
|
5c2420ab1d | |
|
|
ef42a5ada7 | |
|
|
7f89c32404 | |
|
|
101022258d | |
|
|
bdb9a931fc | |
|
|
f667b0f290 | |
|
|
040bc47219 | |
|
|
7c8b533a6e | |
|
|
664083f0e3 | |
|
|
13dfecc3af | |
|
|
60b7ff714f | |
|
|
c4dba3cb18 | |
|
|
6967bcee7a | |
|
|
c9fa1add85 | |
|
|
74de1c1ffa | |
|
|
c9f6c71120 | |
|
|
d18abde892 | |
|
|
34d2696cc3 | |
|
|
411cd8b970 | |
|
|
a0242aa1a8 | |
|
|
8d9f3b20ba | |
|
|
7de7687dcf | |
|
|
bd67663191 | |
|
|
666ced7d6d | |
|
|
18bab95327 | |
|
|
a3b179a4e7 | |
|
|
b812d99ee6 | |
|
|
73105a7acb | |
|
|
3b17d30a34 | |
|
|
a25bd7ce63 | |
|
|
823e1625b0 | |
|
|
dd13f85163 | |
|
|
819109c900 | |
|
|
746460eded | |
|
|
2f5f7792d9 | |
|
|
10dc1f46a8 | |
|
|
28895b7019 | |
|
|
c58a367e88 | |
|
|
fec9ecf03f | |
|
|
70f166de70 | |
|
|
97a35af919 | |
|
|
7425be2690 | |
|
|
b8a482f94c | |
|
|
c6d8a76102 | |
|
|
18fd732daa | |
|
|
e6af3742ac | |
|
|
6636b698ff | |
|
|
a4c95df12b | |
|
|
df29e3e1d5 | |
|
|
56620d2565 | |
|
|
6492d3ad51 | |
|
|
6cfdc601ab | |
|
|
c4f61f6bbe |
|
|
@ -0,0 +1,27 @@
|
|||
FROM luchenqun/ubuntu-mysql-node
|
||||
LABEL maintainer="luchenqun@qq.com"
|
||||
|
||||
RUN mkdir -p /app
|
||||
COPY src /app/src
|
||||
COPY view /app/view
|
||||
COPY package.json /app/package.json
|
||||
COPY production.js /app/production.js
|
||||
COPY schema.sql /app/schema.sql
|
||||
|
||||
WORKDIR /app
|
||||
RUN USER=`sed -n '4,4p' /etc/mysql/debian.cnf | awk 'BEGIN { FS = "= " } ; { print $2 }'` \
|
||||
&& sed -i "s/test/${USER}/" /app/src/config/adapter.js \
|
||||
&& PASSWORD=`sed -n '5,5p' /etc/mysql/debian.cnf | awk 'BEGIN { FS = "= " } ; { print $2 }'` \
|
||||
&& sed -i "s/123456/${PASSWORD}/g" /app/src/config/adapter.js \
|
||||
&& npm install --production \
|
||||
&& touch /usr/local/bin/start.sh \
|
||||
&& chmod 777 /usr/local/bin/start.sh \
|
||||
&& echo "#!/bin/bash" >> /usr/local/bin/start.sh \
|
||||
&& echo "service mysql restart" >> /usr/local/bin/start.sh \
|
||||
&& echo "mysql -u root < /app/schema.sql" >> /usr/local/bin/start.sh \
|
||||
&& echo "node /app/production.js" >> /usr/local/bin/start.sh
|
||||
|
||||
EXPOSE 3306
|
||||
EXPOSE 2000
|
||||
|
||||
ENTRYPOINT ["start.sh"]
|
||||
143
README.md
|
|
@ -1,22 +1,149 @@
|
|||
# 在线书签管理工具
|
||||

|
||||
|
||||
Application created by [ThinkJS](http://www.thinkjs.org)
|
||||
1 在线体验(demo)
|
||||
-------------
|
||||
[在线书签管理系统](http://b.lucq.fun/ "在线书签管理系统"),体验账号:test。密码:123456。
|
||||
|
||||
## Install dependencies
|
||||
2 为什么要做个网络书签
|
||||
------------------
|
||||
每个浏览器上面都会有个书签可以供你收藏你以后可能还要用到的网址。但是你可能还是会遇到下列问题:
|
||||
1、如果你重装系统,或者换浏览器怎么办?
|
||||
2、如果你有多个浏览器书签该如何整合?
|
||||
3、如何快速搜索保存的书签?比如我只想搜索某个时间段保存的书签?
|
||||
4、如果一个分类下面书签过多,如何方便快速查看?
|
||||
5、我能不能查看别人收藏的书签?
|
||||
6、在其他地方上网的时候能不能查看我自己的书签?
|
||||
7、如果公用一台电脑,如何区分我收藏的跟别人收藏的书签?
|
||||
在线书签管理工具,帮助你快速记录你喜欢的网站,并可以随时随地查看这些站点,而不必拘泥于使用的浏览器。无论在什么地方,只要能接入网络,就能打开属于你自己的网络书签,看到自己收藏的页面网址。
|
||||
|
||||
3 主要功能(开发计划)
|
||||
-------
|
||||
- [x] 需要注册账号用户。
|
||||
- [x] 在书签分类里面,可以更新分类,删除分类,新增分类,对分类显示进行排序。分类的标签默认按照添加日期展示,但是可以点击表格的标题,按照点击次数,添加日期,最后点击从大到小进行排序。
|
||||
- [x] 可以按照指定添加时间段,指定分类目录,指定网址关键字等进行查询。
|
||||
- [x] 添加书签的时候,会自动获取title,供用户编辑。其中:Insert键打开添加页面,再次按Insert键保存书签,Esc取消添加。
|
||||
- [x] 可以导入Chrome的书签导出文件,暂时做在设置里面。
|
||||
- [x] 书签可以作为公有或者私有,公有可供所有人搜索。
|
||||
- [x] 可以将搜索到其他用户的书签转存为自己的书签。
|
||||
- [x] 可以将书签导出来,然后导入到浏览器。
|
||||
- [x] 在热门标签里面,有在网上找的热门书签。
|
||||
- [x] 新增备忘录功能,有时候随手要做点纪录,就方便了。任意界面按快捷键A增加备忘录。双击备忘录可查看详情!亦可分享备忘。
|
||||
- [x] 在设置的全局链接,可设置快捷键,用来在任何页面,快速打开设置的链接。
|
||||
- [x] 增加[Chrome插件](https://chrome.google.com/webstore/detail/%E4%B9%A6%E7%AD%BE%E5%BF%AB%E9%80%9F%E6%B7%BB%E5%8A%A0/lmmobgephofdffmaednjooplcpbgbjle),可在任意界面快速添加书签至系统。如果你无法访问该插件,可以按照[Chrome如何安装插件(开发版本/自制)](https://jingyan.baidu.com/article/f3ad7d0f58d6b609c3345b80.html)方法安装插件,插件请到[bookmark-plugin](https://github.com/luchenqun/bookmark-plugin)下载。
|
||||
- [x] 适配手机平板,手机端请访问[mb.lucq.fun](http://mb.lucq.fun/)。
|
||||
|
||||
|
||||
4 主要用到的软件与模块说明
|
||||
------------------
|
||||
**Node.js**:`v12.13.0` 用来做后台服务。
|
||||
**MySQL**: `v5.7.23`用来做数据存储。
|
||||
**AngularJS**:`v1.5.8`前端JavaScript框架。
|
||||
**jQuery**: `v3.1.1`本来用了AngularJS是不需要再使用jQuery了的。但是有些功能AngularJS要大费周章才能完成,jQuery一句代码就能解决。所以还是忍不住将它导入了进来。
|
||||
**Semantic**:`v2.4.0`由于没有美工人员,自己开发的,不想界面太丑,用了这套UI。
|
||||
|
||||
5 目录结构
|
||||
---------
|
||||
```
|
||||
npm install
|
||||
my-bookmark/
|
||||
├── development.js # 开发环境下的入口文件
|
||||
├── logs/ # 日志目录
|
||||
├── Dockerfile # Dockerfile 构建文件
|
||||
├── nginx.conf # nginx 配置文件
|
||||
├── package.json # 项目依赖包
|
||||
├── pm2.json # pm2 配置文件
|
||||
├── production.js # 生产环境下的入口文件
|
||||
├── runtime/ # 后台运行文件夹
|
||||
├── schema.sql # mysql数据库建表文件
|
||||
├── src/ # 后台实现文件夹
|
||||
│ ├── bootstrap/ # 启动自动执行目录
|
||||
│ │ ├── master.js # Master 进程下自动执行
|
||||
│ │ └── worker.js # Worker 进程下自动执行
|
||||
│ ├── config/ # 后台配置文件夹
|
||||
│ │ ├── adapter.js # 后台适配器文件
|
||||
│ │ ├── config.js # 后台配置文件
|
||||
│ │ ├── config.production.js # 后台生产环境配置文件
|
||||
│ │ ├── extend.js # 后台extend配置文件
|
||||
│ │ ├── middleware.js # 后台middleware配置文件
|
||||
│ │ └── router.js # 自定义路由配置文件
|
||||
│ ├── controller/ # 后台控制器文件夹
|
||||
│ │ ├── api.js # 后台api控制器实现
|
||||
│ │ ├── base.js # 后台base控制器实现
|
||||
│ │ └── index.js # 后台index控制器实现
|
||||
│ ├── logic/ # 后台逻辑文件夹
|
||||
│ │ ├── api.js # 后台逻辑api文件
|
||||
│ │ └── index.js # 后台逻辑index文件
|
||||
│ └── model/ # 后台模型文件夹
|
||||
│ └── index.js # 后台模型文件
|
||||
├── test/ # 后台测试文件夹
|
||||
│ └── index.js # 后台测试文件
|
||||
├── update.sql # MySQL更新文件
|
||||
├── view/ # 网站主页显示文件夹
|
||||
│ ├── 404.html # 默认404页面
|
||||
│ ├── css/ # 样式表文件夹
|
||||
│ │ ├── externe/ # 外部引入引来的css文件
|
||||
│ │ └── style.css # 自己写的css文件
|
||||
│ ├── favicon.ico # 网站favicon
|
||||
│ ├── images/ # 图片文件夹
|
||||
│ ├── scripts/ # 前端逻辑实现的JS文件以及引入的JS文件
|
||||
│ │ ├── app-angular.js # AngularJS路由配置文件
|
||||
│ │ ├── controllers/ # 所有的AngularJS控制器
|
||||
│ │ ├── directives/ # 所有的AngularJS指令
|
||||
│ │ ├── externe/ # 外部引入的JS文件
|
||||
│ │ └── services/ # 所有的AngularJS服务文件
|
||||
│ ├── views/ # 页面实现文件
|
||||
│ └── index.html # 网站主页
|
||||
└── README.md # 项目工程说明文件
|
||||
```
|
||||
|
||||
## Start server
|
||||
6 Docker安装部署
|
||||
-------------
|
||||
此部署方式适合新手。
|
||||
|
||||
如果你的Linux环境中没有安装Docker环境。那么请先执行如下命令安装Docker环境。
|
||||
```
|
||||
npm start
|
||||
curl -fsSL get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh --mirror Aliyun
|
||||
```
|
||||
|
||||
## Deploy with pm2
|
||||
安装好docker环境之后,执行命令 `docker run -d -p 2000:2000 -p 3306:3306 luchenqun/mybookmark` 安装并启动应用即可。然后在浏览器输入: `http://你的IP:2000/` 即可访问书签应用。安装好的环境默认了一个账号`test`,密码为`123456`。
|
||||
|
||||
Use pm2 to deploy app on production enviroment.
|
||||
如果MySQL需要远程访问,那么你需要进入容器之后更新 `/etc/mysql/mysql.conf.d/mysqld.cnf`,将绑定地址 `127.0.0.1` 改为 `0.0.0.0`。然后执行命令`service mysql restart`重启数据库服务。安装后的 MySQL默认有两个账户,一个是root账户,无密码。一个是在文件`/etc/mysql/debian.cnf`有个账号密码。当然这些账号都是只能在本地访问的,你需要手动创建一个可供远程访问的账号。
|
||||
|
||||
另外,有人做了arm架构的docker,如果有需要的请按如下命令执行安装
|
||||
```
|
||||
pm2 startOrReload pm2.json
|
||||
docker run -itd --name mybookmark -p 2000:2000 -p 3306:3306 740162752/bookmark
|
||||
```
|
||||
|
||||
7 安装部署指南
|
||||
-------------
|
||||
这种适合动手能力比较强的人员。
|
||||
|
||||
1、安装MySQL数据库。如果不会,请戳教程[MySQL 数据库安装教程](http://baidu.lucq.fun/?q=TXlTUUwg5pWw5o2u5bqT5a6J6KOF5pWZ56iL "mysql 数据库安装教程")。有点需要注意的是,MySQL的版本至少要是5.6。否则执行schema.sql文件会出错。
|
||||
2、新建一个数据库名,使用MySQL将根目录下面的schema.sql文件执行一遍,创建数据库表格。有个问题尤其要注意:**数据库一定要使用UTF-8的编码**,否则执行一些汉字的sql语句会出错!如果是Ubuntu,大概过程如下。
|
||||
```
|
||||
mysql -u root -p // 使用root账号进入mysql数据库。按回车之后输入安装时候root的密码。
|
||||
CREATE DATABASE mybookmarks DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; // 创建mybookmarks数据库。
|
||||
CREATE USER 'test'@'%' IDENTIFIED BY '123456';// 创建一个以用户名为test,密码为123456的用户
|
||||
GRANT ALL ON *.* TO 'test'@'%'; // 给刚创建的test用户数据库所有的权限
|
||||
use mybookmarks; //选择刚创建的数据库。
|
||||
source /home/lcq/schema.sql; // 执行schema.sql文件创建数据库表格。注意,将路径换为你schema.sql所在路径。
|
||||
```
|
||||
3、如果你是全新部署,你可忽略此步骤。如果之前部署过此应用,那么需要执行update.sql文件需要升级。注意:升级之前,请务必备份数据库!确认是否需要运行此升级sql文件也很简单,看一下你之前的数据库mybookmarks下面有没有`tags_bookmarks`这个数据表。如果有,那么需要执行。执行方法还是如上类似`source /home/lcq/update.sql;`。
|
||||
4、安装Node.js。Node.js版本至少要求12.0以上。不会的话,请按照上面步骤1提供的方法自行解决。
|
||||
5、克隆代码`git clone git@github.com:luchenqun/my-bookmark.git`,切换到项目根目录下面,执行`npm install`安装package。
|
||||
6、在根目录,更新`pm2.json`文件,只需要更新`cwd`项即可。该项为你项目所在的路径。更新`src/config/adapter.js`下面`exports.model`关于你的MySQL的账号密码信息。注意,该账号必须要有写数据库的权限!
|
||||
7、如果上面的都做好了,执行命令`npm install pm2 -g`安装pm2模块。再执行命令`pm2 startOrReload pm2.json`。以后如果项目代码有升级,更新代码之后,执行此命令即可重启该应用。
|
||||
8、在浏览器里面输入:`http://你的IP:2000/`。
|
||||
9、如果需要域名部署的话,推荐使用nginx作为HTTP和反向代理服务器,根目录有一份`nginx.conf`文件,你只需要更新`root`项即可使用。相关知识,请自行百度。
|
||||
|
||||
|
||||
8 其他说明
|
||||
---------
|
||||
1、我没有做浏览器兼容测试,只在Google Chrome下面进行了测试开发。
|
||||
|
||||
9 开源许可证
|
||||
-----------
|
||||
[MIT License](http://www.opensource.org/licenses/MIT)
|
||||
你可以随意使用此项目,无需通知我,因为我可能很忙没时间。注意,手机版当前没开源
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name book.mybookmark.cn;
|
||||
server_name b.lucq.fun;
|
||||
root /var/www/my-bookmark;
|
||||
set $node_port 8360;
|
||||
set $node_port 2000;
|
||||
|
||||
index index.js index.html index.htm;
|
||||
if ( -f $request_filename/index.html ){
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"cheerio": "^1.0.0-rc.3",
|
||||
"fs-extra": "^9.0.0",
|
||||
"node-readability": "^3.0.0",
|
||||
"request": "^2.88.2",
|
||||
"think-cache": "^1.0.0",
|
||||
"think-cache-file": "^1.0.8",
|
||||
"think-logger3": "^1.0.0",
|
||||
|
|
|
|||
25
schema.sql
|
|
@ -1,6 +1,8 @@
|
|||
CREATE DATABASE IF NOT EXISTS mybookmarks DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 创建mybookmarks数据库
|
||||
USE mybookmarks;
|
||||
|
||||
-- 用户信息表
|
||||
drop table if exists users;
|
||||
CREATE TABLE `users` (
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`username` varchar(255) NOT NULL, -- 用户名
|
||||
`password` varchar(255) NOT NULL, -- 密码
|
||||
|
|
@ -9,15 +11,14 @@ CREATE TABLE `users` (
|
|||
`lastLogin` datetime DEFAULT now(), -- 最后一次登录时间
|
||||
`searchHistory` varchar(512) DEFAULT NULL, -- 历史搜索记录
|
||||
`avatar` varchar(512) DEFAULT NULL, -- 头像地址
|
||||
`quickUrl` varchar(2048) DEFAULT '{\"B\":\"https://www.baidu.com/\",\"G\":\"https://www.google.com.hk/\",\"V\":\"https://www.v2ex.com/\",\"L\":\"http://luchenqun.com/\",\"H\":\"https://github.com/\",\"Q\":\"http://www.iqiyi.com/\",\"J\":\"https://www.jd.com/\"}', -- 全局快捷地址
|
||||
`quickUrl` varchar(2048) DEFAULT '{\"B\":\"https://www.baidu.com/\",\"G\":\"https://www.google.com.hk/\",\"H\":\"https://github.com/\"}', -- 全局快捷地址
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `username` (`username`),
|
||||
UNIQUE KEY `email` (`email`)
|
||||
);
|
||||
|
||||
-- 书签表
|
||||
drop table if exists bookmarks;
|
||||
CREATE TABLE `bookmarks` (
|
||||
CREATE TABLE IF NOT EXISTS `bookmarks` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`userId` int(11) NOT NULL, -- 用户id
|
||||
`tagId` int(11) NOT NULL, -- 分类id (只允许一个书签对应一个分类)
|
||||
|
|
@ -33,8 +34,7 @@ CREATE TABLE `bookmarks` (
|
|||
);
|
||||
|
||||
-- 书签分类表
|
||||
drop table if exists tags;
|
||||
CREATE TABLE `tags` (
|
||||
CREATE TABLE IF NOT EXISTS `tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`userId` int(11) NOT NULL, -- 用户id
|
||||
`name` varchar(32) NOT NULL, -- 标签
|
||||
|
|
@ -47,8 +47,7 @@ CREATE TABLE `tags` (
|
|||
);
|
||||
|
||||
-- 建议留言
|
||||
drop table if exists advices;
|
||||
CREATE TABLE `advices` (
|
||||
CREATE TABLE IF NOT EXISTS `advices` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`userId` int(11) NOT NULL, -- 用户id
|
||||
`comment` text NOT NULL, -- 评论
|
||||
|
|
@ -59,8 +58,7 @@ CREATE TABLE `advices` (
|
|||
);
|
||||
|
||||
-- 热门表
|
||||
drop table if exists hot_bookmarks;
|
||||
CREATE TABLE `hot_bookmarks` (
|
||||
CREATE TABLE IF NOT EXISTS `hot_bookmarks` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id(articleId)
|
||||
`title` varchar(255) DEFAULT NULL, -- 标题(title)
|
||||
`url` varchar(1024) DEFAULT NULL, -- 链接(url)
|
||||
|
|
@ -69,13 +67,12 @@ CREATE TABLE `hot_bookmarks` (
|
|||
`createdAt` datetime DEFAULT now(), -- 创建时间(updatetime)
|
||||
`lastClick` datetime DEFAULT now(), -- 最后一次点击时间(createtime)
|
||||
`snap` varchar(1024) DEFAULT NULL, -- 截图链接(imageList[0])
|
||||
`icon` varchar(1024) DEFAULT NULL -- icon链接(sourceLogo)
|
||||
`icon` varchar(1024) DEFAULT NULL, -- icon链接(sourceLogo)
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
-- 备忘录
|
||||
drop table if exists notes;
|
||||
CREATE TABLE `notes` (
|
||||
CREATE TABLE IF NOT EXISTS `notes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT, -- id
|
||||
`userId` int(11) NOT NULL, -- 用户id
|
||||
`content` text NOT NULL, -- 备忘内容
|
||||
|
|
|
|||
|
|
@ -1 +1,18 @@
|
|||
// invoked in worker
|
||||
const { execSync } = require('child_process');
|
||||
const os = require("os");
|
||||
think.beforeStartServer(async () => {
|
||||
if (os.platform().startsWith("linux")) {
|
||||
try {
|
||||
execSync('service mysql start', { stdio: ['inherit', 'inherit', 'inherit'] });
|
||||
} catch (error) {
|
||||
console.log("beforeStartServer", error);
|
||||
}
|
||||
}
|
||||
|
||||
const username = 'test';
|
||||
let user = await think.model("users").where({ username }).find();
|
||||
if (think.isEmpty(user)) {
|
||||
await think.model("users").add({ username, password: 'e10adc3949ba59abbe56e057f20f883e', email: 'ilovejiajia@qq.com' });
|
||||
}
|
||||
})
|
||||
|
|
@ -66,7 +66,7 @@ exports.session = {
|
|||
tokenName: 'authorization', // if tokenType not 'cookie', this will be token name, 'jwt' is default 后端字母要小写
|
||||
sign: {
|
||||
// sign options is not required
|
||||
expiresIn: '604800s' // 7天过期
|
||||
expiresIn: '2592000s' // 30天过期
|
||||
},
|
||||
verify: {
|
||||
// verify options is not required
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
const request = require("request");
|
||||
|
||||
module.exports = [{
|
||||
interval: 1000 * 60 * 10, // 10分钟抓取一次
|
||||
immediate: true,
|
||||
handle: async () => {
|
||||
let form = {
|
||||
userId: null,
|
||||
lastupdataTime: new Date().getTime(),
|
||||
pageNo: 1,
|
||||
pageSize: 1000,
|
||||
sort: "desc",
|
||||
renderType: 0,
|
||||
date: think.datetime(new Date(), "YYYY年MM月DD日"),
|
||||
idfa: "d4995f8a0c9b2ad9182369016e376278",
|
||||
os: "ios",
|
||||
osv: "9.3.5"
|
||||
};
|
||||
const url = "https://api.shouqu.me/api_service/api/v1/daily/dailyMark";
|
||||
request.post({ url, form }, async function (error, response, body) {
|
||||
if (!error && response && response.statusCode == 200) {
|
||||
let data = JSON.parse(body).data;
|
||||
let list = data.list;
|
||||
let dataList = [];
|
||||
for (let item of list) {
|
||||
if (item.images_upd.indexOf(',http') >= 0) {
|
||||
item.images_upd = item.images_upd.split(',http')[0];
|
||||
}
|
||||
|
||||
dataList.push({
|
||||
id: item.articleId,
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
clickCount: item.favCount,
|
||||
tagName: item.sourceName,
|
||||
createdAt: think.datetime(item.updatetime > item.createtime ? item.createtime : item.updatetime),
|
||||
lastClick: think.datetime(item.updatetime <= item.createtime ? item.createtime : item.updatetime),
|
||||
snap: item.images_upd.replace("http://", "https://"),
|
||||
icon: item.sourceLogo.replace("http://", "https://")
|
||||
})
|
||||
}
|
||||
await think.model('hot_bookmarks').addMany(dataList, { replace: true });
|
||||
}
|
||||
})
|
||||
}
|
||||
}]
|
||||
|
|
@ -13,8 +13,8 @@ module.exports = [
|
|||
handle: 'resource',
|
||||
enable: true,
|
||||
options: {
|
||||
root: path.join(think.ROOT_PATH, 'www'),
|
||||
publicPath: /^\/(scripts|css|views|images|favicon\.ico)/
|
||||
root: path.join(think.ROOT_PATH, 'view'),
|
||||
publicPath: /^\/(scripts|css|views|images|admin\.jpg|favicon\.ico)/
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ function md5(str) {
|
|||
|
||||
module.exports = class extends Base {
|
||||
async __before() {
|
||||
if (['userRegister', 'userLogin', 'noteShare'].indexOf(this.ctx.action) >= 0) {
|
||||
if (['userRegister', 'userLogin', 'noteShare', 'bookmarkDownload', 'hotBookmarks', 'hotBookmarksRandom'].indexOf(this.ctx.action) >= 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
@ -59,6 +59,7 @@ module.exports = class extends Base {
|
|||
username: user.username
|
||||
});
|
||||
user.token = token;
|
||||
await this.model('users').where({ id: user.id }).update({ lastLogin: ['exp', 'NOW()'] });
|
||||
this.json({ code: 0, data: user, msg: "登陆成功" });
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -210,6 +211,17 @@ module.exports = class extends Base {
|
|||
let bookmark = this.post();
|
||||
bookmark.userId = this.ctx.state.user.id;
|
||||
try {
|
||||
let bookmarkFind = await this.model('bookmarks').where({ userId: this.ctx.state.user.id, url: bookmark.url }).find();
|
||||
if (!think.isEmpty(bookmarkFind)) {
|
||||
await this.model('bookmarks').where({
|
||||
userId: this.ctx.state.user.id,
|
||||
id: bookmarkFind.id
|
||||
}).update({
|
||||
createdAt: ['exp', 'NOW()']
|
||||
});
|
||||
this.json({ code: 0, data: bookmarkFind, msg: `书签 ${bookmark.title} 已存在,更新创建日期!` });
|
||||
return
|
||||
}
|
||||
// 没有分类的直接放未分类里面
|
||||
if (!bookmark.tagId) {
|
||||
const name = "未分类";
|
||||
|
|
@ -225,6 +237,10 @@ module.exports = class extends Base {
|
|||
}
|
||||
}
|
||||
let data = await this.model("bookmarks").add(bookmark);
|
||||
await this.model('tags').where({
|
||||
userId: this.ctx.state.user.id,
|
||||
id: bookmark.tagId
|
||||
}).update({ lastUse: think.datetime(new Date()) });
|
||||
this.json({ code: 0, data, msg: `书签 ${bookmark.title} 添加成功` });
|
||||
} catch (error) {
|
||||
this.json({ code: 1, data: '', msg: error.toString() });
|
||||
|
|
@ -265,13 +281,13 @@ module.exports = class extends Base {
|
|||
if (page == 0 && tagId == -1) {
|
||||
let count = await this.model('bookmarks').where(condition).count('id');
|
||||
let totalPages = Math.ceil(count / pageSize);
|
||||
// 按照 2:2:1取数据
|
||||
let length = Math.ceil(pageSize * 2 / 5);
|
||||
// 按照 1:1取数据
|
||||
let length = Math.ceil(pageSize / 2);
|
||||
let bookmarks = await this.model('bookmarks').where(condition).order('createdAt DESC').limit(0, length).select(); // 这个取一半
|
||||
|
||||
// 取最近点击部分数据
|
||||
let cnt = 0;
|
||||
let bookmarks2 = await this.model('bookmarks').where(condition).order('lastClick DESC').limit(0, pageSize * 2).select(); // 这个多取一点,有可能跟上面的重复了
|
||||
let bookmarks2 = await this.model('bookmarks').where(condition).order('lastClick DESC').limit(0, pageSize * 4).select(); // 这个多取一点,有可能跟上面的重复了
|
||||
for (const bookmark of bookmarks2) {
|
||||
let find = bookmarks.find(item => item.id == bookmark.id);
|
||||
if (!find) {
|
||||
|
|
@ -281,16 +297,6 @@ module.exports = class extends Base {
|
|||
}
|
||||
}
|
||||
|
||||
// 取点击次数最多部分
|
||||
let bookmarks3 = await this.model('bookmarks').where(condition).order('clickCount DESC').limit(0, pageSize * 2).select(); // 这个多取一点,有可能跟上面的重复了
|
||||
for (const bookmark of bookmarks3) {
|
||||
let find = bookmarks.find(item => item.id == bookmark.id);
|
||||
if (!find) {
|
||||
bookmarks.push(bookmark);
|
||||
if (bookmarks.length >= pageSize) break;
|
||||
}
|
||||
}
|
||||
|
||||
data = {
|
||||
count,
|
||||
totalPages,
|
||||
|
|
@ -340,13 +346,13 @@ module.exports = class extends Base {
|
|||
}
|
||||
|
||||
try {
|
||||
let data = await this.model(tableName).where(condition).page(this.get('page') || 1, this.get('pageSize') || 20).countSelect();
|
||||
let data = await this.model(tableName).where(condition).order('createdAt DESC').page(this.get('page') || 1, this.get('pageSize') || 20).countSelect();
|
||||
if (tableName == "bookmarks") {
|
||||
let ids = [];
|
||||
for (let bookmark of data.data) {
|
||||
ids.push(bookmark.tagId);
|
||||
}
|
||||
let tags = await this.model('tags').where({ id: ['IN', ids] }).select();
|
||||
let tags = ids.length > 0 ? await this.model('tags').where({ id: ['IN', ids] }).select() : [];
|
||||
for (let bookmark of data.data) {
|
||||
bookmark.tagName = (tags.find((tag) => tag.id == bookmark.tagId) || { name: "未知分类" }).name;
|
||||
}
|
||||
|
|
@ -420,97 +426,248 @@ module.exports = class extends Base {
|
|||
// path: 'C:\\Users\\lucq\\AppData\\Local\\Temp\\upload_4ae3b14dacaa107076d3bddd471ebe39.html',
|
||||
// name: 'exportbookmark-lcq-20200402084709.html',
|
||||
// type: 'text/html',
|
||||
const file = this.file("file");
|
||||
|
||||
let bookmarks = [];
|
||||
const getRootFolder = function (body) {
|
||||
let h3 = body.find("h3").first();
|
||||
// let isChrome = typeof h3.attr("personal_toolbar_folder") === "string";
|
||||
// let isIE = typeof h3.attr("item_id") === "string";
|
||||
// let isFireFox = h3.text() === "Mozilla Firefox";
|
||||
let isSafari = typeof h3.attr("folded") === "string";
|
||||
return isSafari ? body : body.children("dl").first();
|
||||
};
|
||||
|
||||
let now = new Date().getTime();
|
||||
let fileName = 'uploadbookmark-' + this.ctx.state.user.username + '-' + now + '.html';
|
||||
if (file) {
|
||||
const filePath = path.join(think.ROOT_PATH, `runtime/upload/${fileName}`);
|
||||
await fs.ensureDir(path.dirname(filePath));
|
||||
await fs.move(file.path, filePath);
|
||||
let data = await fs.readFile(filePath);
|
||||
let $ = cheerio.load(data.toString());
|
||||
const parseByString = function (content) {
|
||||
let $ = cheerio.load(content, { decodeEntities: false });
|
||||
let body = $("body");
|
||||
let root = [];
|
||||
let rdt = getRootFolder(body).children("dt");
|
||||
let parseNode = function (node) {
|
||||
let eq0 = node.children().eq(0);
|
||||
let title = eq0.html() || "无标题";
|
||||
let type = "site";
|
||||
let href = "";
|
||||
let attrCreatedAt = "";
|
||||
let attrLastClick = "";
|
||||
let attrClickCount = "";
|
||||
|
||||
let anchors = $("dl").find("a");
|
||||
anchors.each(async (i, e) => {
|
||||
let url = $(e).attr("href");
|
||||
let title = $(e).text() || "无标题";
|
||||
let children = [];
|
||||
switch (eq0[0].name) {
|
||||
case "h3":
|
||||
// folder
|
||||
type = "folder";
|
||||
let dl = node.children("dl").first();
|
||||
let dts = dl.children();
|
||||
let ls = dts.toArray().map(function (ele) { return ele.name !== "dt" ? null : parseNode($(ele)); });
|
||||
children = ls.filter(function (item) { return item !== null; });
|
||||
case "a":
|
||||
// site
|
||||
href = eq0.attr("href") || "";
|
||||
attrCreatedAt = eq0.attr("add_date");
|
||||
attrLastClick = eq0.attr("last_click");
|
||||
attrClickCount = eq0.attr("click_count");
|
||||
}
|
||||
// 处理name
|
||||
if (title.length > 255) {
|
||||
title = title.substring(255);
|
||||
}
|
||||
title = title.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/gi, "");
|
||||
let attrCreatedAt = $(e).attr("add_date");
|
||||
let attrLastClick = $(e).attr("last_click");
|
||||
let attrClickCount = $(e).attr("click_count");
|
||||
let createdAt = think.datetime(attrCreatedAt ? parseInt(attrCreatedAt) * 1000 : new Date());
|
||||
let lastClick = think.datetime(attrLastClick ? parseInt(attrLastClick) * 1000 : new Date());
|
||||
let clickCount = attrClickCount ? parseInt(attrClickCount) : 1;
|
||||
|
||||
// 只允许用一个标签
|
||||
let tagName = "未分类";
|
||||
$(e).parents("dl").each(function (ii, ee) {
|
||||
let folder = $(ee).prev();
|
||||
let temp = folder.text().replace(/(^\s*)|(\s*$)/g, '').replace(/\s+/g, ' ');
|
||||
if (temp != "Bookmarks" && temp != "书签栏" && temp != "" && temp != undefined) { tagName = temp; }
|
||||
return {
|
||||
title,
|
||||
type,
|
||||
url: href,
|
||||
createdAt: think.datetime(attrCreatedAt ? parseInt(attrCreatedAt) * 1000 : new Date()),
|
||||
lastClick: think.datetime(attrLastClick ? parseInt(attrLastClick) * 1000 : new Date()),
|
||||
clickCount: attrClickCount ? parseInt(attrClickCount) : 1,
|
||||
children: children
|
||||
};
|
||||
};
|
||||
rdt.each(function (_, item) {
|
||||
let node = $(item);
|
||||
let child = parseNode(node);
|
||||
root.push(child);
|
||||
});
|
||||
bookmarks.push({ title, url, createdAt, lastClick, tagName, clickCount, userId: this.ctx.state.user.id })
|
||||
return root;
|
||||
};
|
||||
|
||||
const parseByPath = function (path) {
|
||||
var content = fs.readFileSync(path, 'utf-8');
|
||||
return parseByString(content);
|
||||
};
|
||||
|
||||
const userId = this.ctx.state.user.id;
|
||||
|
||||
const flatBookmarks = (originBookmarks, tagName, bookmarks) => {
|
||||
for (let bookmark of originBookmarks) {
|
||||
if (bookmark.type == "site") {
|
||||
bookmarks.push({
|
||||
title: bookmark.title,
|
||||
url: bookmark.url,
|
||||
createdAt: bookmark.createdAt,
|
||||
lastClick: bookmark.lastClick,
|
||||
tagName,
|
||||
clickCount: bookmark.clickCount,
|
||||
userId
|
||||
});
|
||||
} else if (bookmark.type == "folder") {
|
||||
flatBookmarks(bookmark.children, tagName == '未分类' ? bookmark.title : tagName, bookmarks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bookmarks = [];
|
||||
|
||||
const file = this.file("file");
|
||||
let fileName = 'uploadbookmark-' + this.ctx.state.user.username + '-' + think.datetime(new Date(), "YYYYMMDDHHmmss") + '.html';
|
||||
if (file) {
|
||||
const filePath = path.join(think.ROOT_PATH, `runtime/upload/${fileName}`);
|
||||
await fs.ensureDir(path.dirname(filePath));
|
||||
await fs.move(file.path, filePath);
|
||||
let originBookmarks = parseByPath(filePath);
|
||||
Array.isArray(originBookmarks) && originBookmarks.length >= 0 && (originBookmarks[0].title = "未分类");
|
||||
flatBookmarks(originBookmarks, originBookmarks[0].title, bookmarks); // 传上来的树级目录改为只有一级目录
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
let repeat = 0;
|
||||
let tags = await this.model('tags').where({ userId: this.ctx.state.user.id }).select();
|
||||
let fail = 0;
|
||||
let failStr = "";
|
||||
let tags = await this.model("tags").where({ userId: this.ctx.state.user.id }).select();
|
||||
for (let bookmark of bookmarks) {
|
||||
let find = await this.model('bookmarks').where({ userId: this.ctx.state.user.id, url: bookmark.url }).find();
|
||||
let find = await this.model("bookmarks").where({ userId: this.ctx.state.user.id, url: bookmark.url }).find();
|
||||
if (think.isEmpty(find)) {
|
||||
let tag = tags.find(item => item.name == bookmark.tagName);
|
||||
let tag = tags.find((item) => item.name == bookmark.tagName);
|
||||
if (tag) {
|
||||
bookmark.tagId = tag.id;
|
||||
} else {
|
||||
bookmark.tagId = await this.model("tags").add({ userId: this.ctx.state.user.id, name: bookmark.tagName });
|
||||
tags.push({
|
||||
id: bookmark.tagId,
|
||||
name: bookmark.tagName
|
||||
})
|
||||
name: bookmark.tagName,
|
||||
});
|
||||
}
|
||||
delete bookmark.tagName;
|
||||
try {
|
||||
await this.model("bookmarks").add(bookmark);
|
||||
} catch (error) {
|
||||
fail++;
|
||||
failStr += bookmark.title + ",";
|
||||
}
|
||||
count++;
|
||||
} else {
|
||||
repeat++;
|
||||
}
|
||||
}
|
||||
this.json({ code: 0, data: count, msg: `书签传入${bookmarks.length}个,重复书签${repeat}个,成功导入${count}个。` });
|
||||
this.json({ code: 0, data: count, msg: `书签传入${bookmarks.length}个,重复书签${repeat}个,${fail}个导入失败:${failStr},成功导入${count}个。` });
|
||||
}
|
||||
|
||||
// 书签备份
|
||||
async bookmarkBackupAction() {
|
||||
let init = '<TITLE>Bookmarks</TITLE><H1>Bookmarks</H1><DL id="0"></DL>';
|
||||
let $ = cheerio.load(init, {
|
||||
decodeEntities: false,
|
||||
xmlMode: true,
|
||||
});
|
||||
const sample =
|
||||
`<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>Bookmarks</TITLE>
|
||||
<H1>Bookmarks</H1>
|
||||
<DL><p>
|
||||
<DT><H3 ADD_DATE="1606958496" LAST_MODIFIED="1622450430" PERSONAL_TOOLBAR_FOLDER="true">书签栏</H3>
|
||||
<DL><p>
|
||||
<DT><H3 ADD_DATE="1622427860" LAST_MODIFIED="1622450436">JavaScript</H3>
|
||||
<DL><p>
|
||||
<DT><A HREF="https://github.com/luchenqun/my-bookmark/issues" ADD_DATE="1622427872">Issues · luchenqun/my-bookmark</A>
|
||||
<DT><A HREF="https://mail.google.com/mail/u/0/#inbox" ADD_DATE="1622450430">收件箱 - lcq530485521@gmail.com - Gmail</A>
|
||||
</DL><p>
|
||||
</DL><p>
|
||||
</DL><p>`
|
||||
|
||||
let time = (date) => parseInt(new Date(date).getTime() / 1000); // 日期转时间
|
||||
let now = new Date();
|
||||
let left = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>Bookmarks</TITLE>
|
||||
<H1>Bookmarks</H1>
|
||||
<DL><p>
|
||||
<DT><H3 ADD_DATE="${time(now)}" LAST_MODIFIED="${time(now)}" PERSONAL_TOOLBAR_FOLDER="true">书签栏</H3>
|
||||
<DL><p>\n`;
|
||||
let middle = '';
|
||||
let right = ` </DL><p>
|
||||
</DL><p>`;
|
||||
|
||||
let tags = await this.model('tags').where({ userId: this.ctx.state.user.id }).order('sort ASC, lastUse DESC').select();
|
||||
for (const tag of tags) {
|
||||
$('#0').append(`<DT><H3>${tag.name}</H3></DT><DL id="${tag.id}"></DL>`);
|
||||
let tagStr = ` <DT><H3 ADD_DATE="${time(tag.lastUse)}" LAST_MODIFIED="${time(tag.lastUse)}">${tag.name}</H3>\n <DL><p>\n`;
|
||||
let bookmarks = await this.model('bookmarks').where({ tagId: tag.id }).select();
|
||||
for (const bookmark of bookmarks) {
|
||||
$('#' + tag.id).append(`<DT><A HREF="${bookmark.url}" ADD_DATE="${time(bookmark.createdAt)}" LAST_CLICK="${time(bookmark.lastClick)}" CLICK_COUNT="${bookmark.clickCount}" >${bookmark.title}</A></DT>`)
|
||||
tagStr += ` <DT><A HREF="${bookmark.url}" ADD_DATE="${time(bookmark.createdAt)}" LAST_CLICK="${time(bookmark.lastClick)}" CLICK_COUNT="${bookmark.clickCount}">${bookmark.title}</A>\n`
|
||||
}
|
||||
tagStr += ` </DL><p>\n`;
|
||||
middle += bookmarks.length > 0 ? tagStr : '';
|
||||
}
|
||||
let now = new Date().getTime()
|
||||
let fileName = 'exportbookmark-' + this.ctx.state.user.username + '-' + now + '.html';
|
||||
let fileName = 'exportbookmark-' + this.ctx.state.user.username + '-' + think.datetime(new Date(), "YYYYMMDDHHmmss") + '.html';
|
||||
let filePath = path.join(think.ROOT_PATH, 'runtime', 'backup', fileName);
|
||||
|
||||
await fs.ensureFile(filePath);
|
||||
await fs.writeFile(filePath, $.xml());
|
||||
this.json({ code: 0, data: `runtime/backup/${fileName}` });
|
||||
setTimeout(() => fs.remove(filePath), 10000);
|
||||
// await this.download(filePath, fileName)
|
||||
await fs.writeFile(filePath, left + middle + right);
|
||||
this.json({ code: 0, data: fileName });
|
||||
|
||||
setTimeout(async () => {
|
||||
let exists = await fs.pathExists(filePath);
|
||||
if (exists) {
|
||||
await fs.remove(filePath);
|
||||
}
|
||||
}, 1000 * 60 * 10); // 十分钟内没下载就给删掉
|
||||
}
|
||||
|
||||
async bookmarkDownloadAction() {
|
||||
let fileName = this.get('fileName');
|
||||
let filePath = path.join(think.ROOT_PATH, 'runtime', 'backup', fileName);
|
||||
let exists = await fs.pathExists(filePath);
|
||||
if (exists) {
|
||||
await this.download(filePath);
|
||||
await fs.remove(filePath);
|
||||
} else {
|
||||
this.body = "文件不存在!";
|
||||
}
|
||||
}
|
||||
|
||||
// 获取收趣的热门书签
|
||||
async hotBookmarksAction() {
|
||||
let page = this.get('page');
|
||||
let pageSize = parseInt(this.get('pageSize') || 50);
|
||||
try {
|
||||
// 如果是第0页而且是个人定制的,把 最近点击 与 最近新增 的返回去。
|
||||
let data = {};
|
||||
data = await this.model('hot_bookmarks').order('id DESC').page(page || 1, pageSize).countSelect();
|
||||
for (let bookmark of data.data) {
|
||||
if (!bookmark.tagName) {
|
||||
bookmark.tagName = "未知";
|
||||
}
|
||||
}
|
||||
this.json({ code: 0, data });
|
||||
} catch (error) {
|
||||
this.json({ code: 1, msg: error.toString() });
|
||||
}
|
||||
}
|
||||
|
||||
// 随机获取收趣的热门书签
|
||||
async hotBookmarksRandomAction() {
|
||||
try {
|
||||
let sql = `SELECT * FROM hot_bookmarks ORDER BY RAND() LIMIT 50;`;
|
||||
let data = await this.model('hot_bookmarks').query(sql);
|
||||
for (let bookmark of data) {
|
||||
if (!bookmark.tagName) {
|
||||
bookmark.tagName = "未知";
|
||||
}
|
||||
}
|
||||
this.json({ code: 0, data });
|
||||
} catch (error) {
|
||||
this.json({ code: 1, msg: error.toString() });
|
||||
}
|
||||
}
|
||||
|
||||
// 获取文章
|
||||
|
|
@ -550,6 +707,9 @@ module.exports = class extends Base {
|
|||
async adviceAddAction() {
|
||||
let advice = this.post();
|
||||
advice.userId = this.ctx.state.user.id;
|
||||
if (this.ctx.state.user.username == 'test') {
|
||||
return this.json({ code: 400, data: '', msg: `Test user forbid advice!` });
|
||||
}
|
||||
try {
|
||||
let res = await this.model("advices").add(advice);
|
||||
this.json({ code: 0, data: res, msg: `留言 添加成功` });
|
||||
|
|
@ -573,6 +733,21 @@ module.exports = class extends Base {
|
|||
let note = this.post();
|
||||
note.userId = this.ctx.state.user.id;
|
||||
try {
|
||||
// 没有分类的直接放未分类里面
|
||||
if (!note.tagId) {
|
||||
const name = "未分类";
|
||||
let tag = await this.model("tags").where({ name }).find();
|
||||
if (!think.isEmpty(tag)) {
|
||||
note.tagId = tag.id;
|
||||
} else {
|
||||
let tagId = await this.model("tags").add({
|
||||
userId: this.ctx.state.user.id,
|
||||
name
|
||||
});
|
||||
note.tagId = tagId;
|
||||
}
|
||||
}
|
||||
|
||||
let data = await this.model("notes").add(note);
|
||||
this.json({ code: 0, data, msg: `备忘添加成功` });
|
||||
} catch (error) {
|
||||
|
|
@ -626,7 +801,11 @@ module.exports = class extends Base {
|
|||
|
||||
async noteShareAction() {
|
||||
let id = this.get("id");
|
||||
let json = this.get("json");
|
||||
let note = await this.model('notes').where({ id, public: 1 }).find();
|
||||
if (json) {
|
||||
this.json(JSON.parse(note.content))
|
||||
} else {
|
||||
let body = think.isEmpty(note) ? "备忘为非公开或者已删除!" : note.content;
|
||||
this.body = `<body style="margin:0px;height:100%;">
|
||||
<head>
|
||||
|
|
@ -646,4 +825,5 @@ module.exports = class extends Base {
|
|||
</div>
|
||||
</body>`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const Base = require('./base.js');
|
||||
|
||||
module.exports = class extends Base {
|
||||
indexAction() {
|
||||
return this.display();
|
||||
async indexAction() {
|
||||
await this.display("index.html");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@ CHANGE COLUMN `fav_count` `clickCount` smallint(6) NULL DEFAULT 1 AFTER `url`,
|
|||
CHANGE COLUMN `created_by` `tagName` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `clickCount`,
|
||||
CHANGE COLUMN `snap_url` `snap` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `last_click`,
|
||||
CHANGE COLUMN `favicon_url` `icon` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL AFTER `snap`,
|
||||
ADD COLUMN `createAt` datetime NULL AFTER `tagName`,
|
||||
ADD COLUMN `lastClick` datetime NULL AFTER `createAt`,
|
||||
ADD COLUMN `createdAt` datetime NULL AFTER `tagName`,
|
||||
ADD COLUMN `lastClick` datetime NULL AFTER `createdAt`,
|
||||
MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT FIRST;
|
||||
UPDATE hot_bookmarks SET createAt = FROM_UNIXTIME(created_at/1000), lastClick = FROM_UNIXTIME(last_click/1000);
|
||||
UPDATE hot_bookmarks SET createdAt = FROM_UNIXTIME(created_at/1000), lastClick = FROM_UNIXTIME(last_click/1000);
|
||||
ALTER TABLE `hot_bookmarks`
|
||||
DROP COLUMN `created_at`,
|
||||
DROP COLUMN `last_click`;
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@
|
|||
|
||||
<body>
|
||||
<div>
|
||||
<div id="content" style="height: 530px;">
|
||||
<div id="content" style="height: 530px">
|
||||
<p>
|
||||
对不起,您的风筝已掉线,请时光倒流回前一秒。<br />
|
||||
<span id="totalSecond">5</span>秒后自动
|
||||
<a href="https://mybookmark.cn" class="backhome"><span>返回首页</span></a>
|
||||
<a href="https://b.lucq.fun" class="backhome"><span>返回首页</span></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 496 KiB After Width: | Height: | Size: 496 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
|
@ -3,7 +3,7 @@ body {
|
|||
background-repeat: repeat;
|
||||
background-position: top left;
|
||||
background-attachment: scroll;
|
||||
padding-top: 50px;
|
||||
padding-top: 3px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
|
|
@ -189,3 +189,7 @@ img.operator {
|
|||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.js-search-input {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 705 B After Width: | Height: | Size: 705 B |
|
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 662 B After Width: | Height: | Size: 662 B |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 536 B After Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 291 B After Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 438 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 425 B |
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 292 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 249 B |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 427 B |
|
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 389 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 529 B After Width: | Height: | Size: 529 B |
|
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 438 B |
|
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 777 B |
|
Before Width: | Height: | Size: 623 B After Width: | Height: | Size: 623 B |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 805 B After Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 808 B After Width: | Height: | Size: 808 B |
|
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 507 B |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
|
@ -37,6 +37,14 @@
|
|||
var text = e.text.length >= 180 ? e.text.substr(0, 180) + "..." : e.text;
|
||||
toastr.error(text + "<br/>复制失败", "提示");
|
||||
});
|
||||
|
||||
if (window.location.hostname.indexOf("mybookmark.cn") >= 0) {
|
||||
toastr.warning("域名【mybookmark.cn】将于2021年11月份到期,届时将不再续费无法访问。后续将使用新域名【http://b.lucq.fun】为您提供服务。5分钟后会自动跳转到新的域名。", "提示");
|
||||
$(".js-domain").removeClass("hidden");
|
||||
setTimeout(function () {
|
||||
window.location = "http://b.lucq.fun/#/tags";
|
||||
}, 5 * 60 * 1000);
|
||||
}
|
||||
};
|
||||
let resizeContainer = () => {
|
||||
let count = 1;
|
||||
|
|
@ -53,18 +61,25 @@
|
|||
</head>
|
||||
|
||||
<body ng-app="bookmarkApp">
|
||||
<div class="ui container" id="js-container" style="position: absolute;left: 86;">
|
||||
<div class="ui container" id="js-container" style="position: absolute; left: 86;width: 70%;">
|
||||
<div class="ui error hidden message js-domain" style="margin-bottom: 3px">
|
||||
<div class="header">域名更换提示!</div>
|
||||
<ul class="list">
|
||||
<li>域名【mybookmark.cn】将于2021年11月份到期,届时将不再续费无法访问。目前已使用新域名【<a href="http://b.lucq.fun/">http://b.lucq.fun</a>】为您提供服务。</li>
|
||||
<li>5分钟后会自动跳转到新的域名。<a href="http://b.lucq.fun/">立即跳转</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- directive:菜单 -->
|
||||
<menus></menus>
|
||||
<div class="ui container" style="width: 100%; height: 2px;"></div>
|
||||
<div class="ui container" style="width: 100%; height: 2px"></div>
|
||||
<div class="ui container">
|
||||
<div ui-view></div>
|
||||
</div>
|
||||
<div class="ui container" style="width: 100%; height: 10px;"></div>
|
||||
<div class="foot" style="margin-bottom: 10px;">
|
||||
<div class="ui segment container" style="text-align: center;">我爱佳佳与这个世界 | <a href="http://m.mybookmark.cn/">移动设备访问</a> | 联系我(QQ群:1026967226) | <a href="https://github.com/luchenqun/my-bookmark" target="_blank">网站源码</a> | V2.0.0 | <span>加载失败,请按 Ctrl + Shift + R 强制刷新!(●'◡'●)</span><br /></div>
|
||||
<div class="ui container" style="width: 100%; height: 2px"></div>
|
||||
<div class="foot">
|
||||
<div class="ui segment container" style="text-align: center">我爱佳佳与这个世界 | <a href="http://mb.lucq.fun/">移动设备访问</a> | 联系我(QQ群:1026967226) | <a href="http://beian.miit.gov.cn/" target="_blank">粤ICP备18032994号</a> | <a href="https://github.com/luchenqun/my-bookmark" target="_blank">网站源码</a> | V2.0.0 | <span>加载失败,请按 Ctrl + Shift + R 强制刷新!(●'◡'●)</span><br /></div>
|
||||
<!-- 主要用来配合clipboard.min.js复制文本的 -->
|
||||
<div id="clipboard" data-clipboard-text="i love this world and jiajia!" style="opacity: 0; cursor: default;">
|
||||
<div id="clipboard" data-clipboard-text="i love this world and jiajia!" style="opacity: 0; cursor: default">
|
||||
<span>Copy</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -95,7 +110,7 @@
|
|||
<script src="scripts/controllers/edit-controller.js"></script>
|
||||
<script src="scripts/controllers/bookmark-info-controller.js"></script>
|
||||
<script src="scripts/controllers/search-controller.js"></script>
|
||||
<script src="scripts/controllers/weixin-article-controller.js"></script>
|
||||
<script src="scripts/controllers/hot-controller.js"></script>
|
||||
<script src="scripts/controllers/note-controller.js"></script>
|
||||
<script src="scripts/externe/semantic.min.js"></script>
|
||||
<script src="scripts/externe/calendar.min.js"></script>
|
||||
|
|
@ -109,5 +124,10 @@
|
|||
<script src="scripts/externe/md5.js"></script>
|
||||
<script src="scripts/externe/pnglib.js"></script>
|
||||
<script src="scripts/externe/identicon.js"></script>
|
||||
<style>
|
||||
.ui.container {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -53,10 +53,10 @@ app.config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
|
|||
templateUrl: 'views/bookmarks.html',
|
||||
controller: 'bookmarksCtr'
|
||||
})
|
||||
.state('weixin-article', {
|
||||
url: '/weixin-article',
|
||||
templateUrl: 'views/weixin-article.html',
|
||||
controller: 'weixinArticleCtr'
|
||||
.state('hot', {
|
||||
url: '/hot',
|
||||
templateUrl: 'views/hot.html',
|
||||
controller: 'hotCtr'
|
||||
})
|
||||
.state('note', {
|
||||
url: '/note',
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
app.controller('adviceCtr', ['$scope', '$state', '$timeout', '$window', 'pubSubService', 'dataService', function ($scope, $state, $timeout, $window, pubSubService, dataService) {
|
||||
console.log("Hello adviceCtr");
|
||||
console.log($window.location.hostname);
|
||||
if (dataService.smallDevice()) {
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
$scope.comment = '';
|
||||
$scope.advices = [];
|
||||
$scope.user = {};
|
||||
$scope.loading = false;
|
||||
|
||||
pubSubService.subscribe('Common.user', $scope, function (event, user) {
|
||||
$scope.user = user;
|
||||
});
|
||||
|
||||
getAdvices();
|
||||
|
||||
$scope.ok = async function () {
|
||||
if ($scope.comment == '') {
|
||||
toastr.error('留言失败内容不能为空', "错误");
|
||||
} else if ($scope.user.username == 'test') {
|
||||
toastr.error('test用户不允许留言!', "错误");
|
||||
} else {
|
||||
await post('adviceAdd', { comment: $scope.comment });
|
||||
await getAdvices();
|
||||
}
|
||||
}
|
||||
|
||||
async function getAdvices() {
|
||||
$scope.loading = true;
|
||||
$scope.comment = "";
|
||||
let advices = await get("advices");
|
||||
advices.forEach(element => {
|
||||
element.imgData = new Identicon(md5(element.userId)).toString();
|
||||
});
|
||||
$timeout(function () {
|
||||
$scope.advices = advices;
|
||||
});
|
||||
$scope.loading = false;
|
||||
}
|
||||
}]);
|
||||
|
|
@ -9,34 +9,9 @@ app.controller('bookmarkInfoCtr', ['$scope', '$state', '$timeout', '$sce', '$win
|
|||
$('.ui.modal.js-bookmark-info').modal({
|
||||
closable: false,
|
||||
}).modal('setting', 'transition', dataService.animation()).modal('show');
|
||||
bookmark.favicon_url = 'http://favicon.luchenqun.com/?url=' + bookmark.url;
|
||||
bookmark.favicon_url = 'https://favicon.lucq.fun/?url=' + bookmark.url;
|
||||
$scope.bookmark = bookmark;
|
||||
$scope.bookmark.description = $sce.trustAsHtml(bookmark.description);
|
||||
$scope.content = $sce.trustAsHtml(bookmark.content) || '';
|
||||
if (!$scope.content) {
|
||||
$timeout(function () {
|
||||
$('.ui.modal.js-bookmark-info').modal("refresh");
|
||||
$("p").css("word-wrap", "break-word");
|
||||
}, 500);
|
||||
$scope.loading = true;
|
||||
try {
|
||||
let data = get("article", { url: bookmark.url });
|
||||
$scope.content = data.content ? $sce.trustAsHtml(data.content) : $sce.trustAsHtml('<p>数据获取失败,可能是服务器不允许获取,或者是https网站!</p>');
|
||||
setTimeout(function () {
|
||||
$('.ui.modal.js-bookmark-info').modal && $('.ui.modal.js-bookmark-info').modal("refresh");
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
$scope.loading = false;
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
$('.ui.modal.js-bookmark-info').modal && $('.ui.modal.js-bookmark-info').modal("refresh");
|
||||
}, 10);
|
||||
setTimeout(function () {
|
||||
$('.modals').animate({ scrollTop: 0 }, 100);
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.jumpToUrl = async function (url, id) {
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
app.controller('bookmarksCtr', ['$scope', '$state', '$stateParams', '$filter', '$window', '$timeout', '$document', 'ngDialog', 'pubSubService', 'dataService', function ($scope, $state, $stateParams, $filter, $window, $timeout, $document, ngDialog, pubSubService, dataService) {
|
||||
console.log("Hello bookmarksCtr...", $stateParams);
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
$state.go('tags');
|
||||
}]);
|
||||
|
|
@ -105,7 +105,7 @@ app.controller('editCtr', ['$scope', '$state', '$timeout', '$document', 'ngDialo
|
|||
}
|
||||
|
||||
$scope.showAddTag = function () {
|
||||
if ($scope.tags.length < 30) {
|
||||
if ($scope.tags.length < 50) {
|
||||
console.log('showAddTag..........')
|
||||
$scope.newTag = "";
|
||||
dialog = ngDialog.open({
|
||||
|
|
@ -114,14 +114,14 @@ app.controller('editCtr', ['$scope', '$state', '$timeout', '$document', 'ngDialo
|
|||
scope: $scope
|
||||
});
|
||||
} else {
|
||||
toastr.error('标签个数总数不能超过30个!不允许再添加新分类,如有需求,请联系管理员。', "提示");
|
||||
toastr.error('标签个数总数不能超过50个!不允许再添加新分类,如有需求,请联系管理员。', "提示");
|
||||
}
|
||||
}
|
||||
|
||||
$scope.addTag = async function (tag) {
|
||||
console.log(tag);
|
||||
if ($scope.tags.length >= 30) {
|
||||
toastr.error('标签个数总数不能超过30个!不允许再添加新分类,如有需求,请联系管理员。', "提示");
|
||||
if ($scope.tags.length >= 50) {
|
||||
toastr.error('标签个数总数不能超过50个!不允许再添加新分类,如有需求,请联系管理员。', "提示");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +188,9 @@ app.controller('editCtr', ['$scope', '$state', '$timeout', '$document', 'ngDialo
|
|||
});
|
||||
$scope.public = (bookmark && bookmark.id) || '1';
|
||||
$('.ui.checkbox.js-public').checkbox((bookmark && bookmark.public && bookmark.public == '1') ? 'set checked' : 'set unchecked')
|
||||
$timeout(function () {
|
||||
$scope.loadTags = false;
|
||||
}, 10);
|
||||
});
|
||||
|
||||
pubSubService.subscribe('TagCtr.storeBookmark', $scope, function (event, bookmark) {
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
app.controller('homeCtr', ['$scope', '$stateParams', '$filter', '$state', '$window', 'pubSubService', 'dataService', function ($scope, $stateParams, $filter, $state, $window, pubSubService, dataService) {
|
||||
console.log('Hello homeCtr......');
|
||||
if (dataService.smallDevice()) {
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
pubSubService.subscribe('Common.user', $scope, function (event, user) {
|
||||
user.id && $state.go('tags');
|
||||
});
|
||||
}]);
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
app.controller('hotCtr', ['$scope', '$state', '$sce', '$filter', '$window', '$timeout', '$document', 'pubSubService', 'dataService', function ($scope, $state, $sce, $filter, $window, $timeout, $document, pubSubService, dataService) {
|
||||
console.log("Hello hotCtr...");
|
||||
if (dataService.smallDevice()) {
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
const pageSize = 40;
|
||||
var timeagoInstance = timeago();
|
||||
|
||||
$scope.hoverBookmark = null;
|
||||
$scope.bookmarks = []; // 书签数据
|
||||
$scope.bookmark = {};
|
||||
$scope.bookmarkNormalHover = false;
|
||||
$scope.bookmarkEditHover = false;
|
||||
|
||||
$scope.count = 0;
|
||||
$scope.totalPages = 0;
|
||||
$scope.currentPage = 1;
|
||||
$scope.channelId = 0; // 0 默认是后台抓取的收趣
|
||||
|
||||
$scope.inputPage = '';
|
||||
$scope.loading = false;
|
||||
$scope.toastrId = 0;
|
||||
$scope.random = 0;
|
||||
$scope.channels = JSON.parse(`[{"id":0,"name":"收趣"},{"id":-1,"name":"随机一批"},{"id":1,"name":"热门"},{"id":2,"name":"搞笑"},{"id":3,"name":"养生堂"},{"id":4,"name":"私房话"},{"id":5,"name":"八卦精"},{"id":6,"name":"科技咖"},{"id":7,"name":"财经迷"},{"id":8,"name":"汽车控"},{"id":9,"name":"生活家"},{"id":10,"name":"时尚圈"},{"id":11,"name":"育儿"},{"id":12,"name":"旅游"},{"id":13,"name":"职场"},{"id":14,"name":"美食"},{"id":15,"name":"历史"},{"id":16,"name":"教育"},{"id":17,"name":"星座"},{"id":18,"name":"体育"},{"id":19,"name":"军事"},{"id":20,"name":"游戏"},{"id":21,"name":"萌宠"}]`);
|
||||
|
||||
$scope.jumpToUrl = async function (url) {
|
||||
$window.open(url, '_blank');
|
||||
}
|
||||
|
||||
$scope.favoriteBookmark = async function (b) {
|
||||
var menusScope = $('div[ng-controller="menuCtr"]').scope();
|
||||
var login = (menusScope && menusScope.login) || false;
|
||||
if (!login) {
|
||||
$scope.toastrId = toastr.info('请先登录再收藏书签!', "提示");
|
||||
} else {
|
||||
let bookmark = {}
|
||||
bookmark.title = b.title;
|
||||
bookmark.url = b.url;
|
||||
let id = await post("bookmarkAdd", bookmark);
|
||||
bookmark = await get("bookmark", { id })
|
||||
pubSubService.publish('EditCtr.inserBookmarsSuccess', bookmark);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.storeBookmark = async function (bookmark) {
|
||||
var menusScope = $('div[ng-controller="menuCtr"]').scope();
|
||||
var login = (menusScope && menusScope.login) || false;
|
||||
if (!login) {
|
||||
$scope.toastrId = toastr.info('请先登录再转存书签!', "提示");
|
||||
} else {
|
||||
pubSubService.publish('TagCtr.storeBookmark', $.extend(true, {}, bookmark));
|
||||
}
|
||||
}
|
||||
|
||||
$scope.copy = async function (url) {
|
||||
dataService.clipboard(url);
|
||||
}
|
||||
|
||||
$scope.detailBookmark = async function (bookmark) {
|
||||
if (!bookmark.content) {
|
||||
$scope.jumpToUrl(bookmark.url);
|
||||
return;
|
||||
}
|
||||
$scope.bookmark = bookmark;
|
||||
$('.js-weixin-content').modal({ blurring: true }).modal('setting', 'transition', dataService.animation()).modal('show')
|
||||
$timeout(function () {
|
||||
$('.js-main-content').animate({ scrollTop: 0 }, 100);
|
||||
$('.js-weixin-content').modal("refresh");
|
||||
}, 10)
|
||||
}
|
||||
|
||||
$scope.close = async function () {
|
||||
$('.js-weixin-content').modal('setting', 'transition', dataService.animation()).modal('hide');
|
||||
}
|
||||
|
||||
// 快捷键r随机推荐
|
||||
$document.bind("keydown", function (event) {
|
||||
$scope.$apply(async () => {
|
||||
let key = event.key.toUpperCase();
|
||||
let menusScope = $('div[ng-controller="menuCtr"]').scope();
|
||||
let blur = (menusScope && menusScope.blur) || false;
|
||||
if (key == 'R' && (!blur)) {
|
||||
$scope.getWeixinArticles(-1, 1);
|
||||
}
|
||||
|
||||
if ($scope.hoverBookmark && dataService.keyShortcuts()) {
|
||||
if (key == 'I') {
|
||||
$scope.detailBookmark($scope.hoverBookmark)
|
||||
} else if (key == 'C') {
|
||||
$scope.copy($scope.hoverBookmark.url)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$scope.setHoverBookmark = async function (bookmark) {
|
||||
$scope.hoverBookmark = bookmark;
|
||||
}
|
||||
|
||||
$scope.changeCurrentPage = async function (currentPage) {
|
||||
currentPage = parseInt(currentPage) || 0;
|
||||
if (currentPage <= $scope.totalPages && currentPage >= 1) {
|
||||
$scope.getWeixinArticles($scope.channelId, currentPage);
|
||||
$scope.currentPage = currentPage;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.getWeixinArticles = async function (channelId, page) {
|
||||
$scope.bookmarks = [];
|
||||
$scope.bookmark = {};
|
||||
$scope.loading = true;
|
||||
$scope.channelId = channelId;
|
||||
$scope.currentPage = page;
|
||||
$scope.totalPages = 0;
|
||||
$scope.count = 0;
|
||||
if (channelId == -1) {
|
||||
let data = await get("hotBookmarksRandom");
|
||||
$timeout(() => {
|
||||
$scope.bookmarks = data;
|
||||
$scope.totalPages = 1;
|
||||
$scope.count = data.length;
|
||||
$scope.loading = false;
|
||||
})
|
||||
} else if (channelId == 0) {
|
||||
let reply = await get("hotBookmarks", { page, pageSize });
|
||||
$timeout(() => {
|
||||
$scope.bookmarks = reply.data;
|
||||
$scope.totalPages = reply.totalPages;
|
||||
$scope.count = reply.count;
|
||||
$scope.loading = false;
|
||||
})
|
||||
} else {
|
||||
$.ajax({
|
||||
url: `https://api.jisuapi.com/weixinarticle/get?channelid=${channelId}&start=${(page - 1) * pageSize}&num=${pageSize}&appkey=e95887468ab87d69`,
|
||||
type: 'get',
|
||||
dataType: "jsonp",
|
||||
jsonp: "callback",
|
||||
complete: function () { $scope.loading = false },
|
||||
success: function (body) { dealBody(body) },
|
||||
error: function (json) { toastr.error('获取热门失败!失败原因:' + json.msg, "提示") }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function dealBody(body) {
|
||||
console.log('success............', body);
|
||||
$timeout(function () {
|
||||
var defaultSnap = "./images/default.jpg"
|
||||
var defaultFavicon = "./images/weixin.ico"
|
||||
if (body.status == 0) {
|
||||
var weixinArticles = body.result.list;
|
||||
var total = body.result.total;
|
||||
$scope.count = total;
|
||||
$scope.totalPages = parseInt(total / pageSize) + 1;
|
||||
weixinArticles.forEach((articl, index) => {
|
||||
let bookmark = {};
|
||||
bookmark.index = index;
|
||||
bookmark.title = articl.title;
|
||||
bookmark.url = articl.url;
|
||||
bookmark.icon = defaultFavicon;
|
||||
bookmark.tagName = articl.weixinname;
|
||||
bookmark.account = articl.weixinaccount;
|
||||
bookmark.snap = articl.pic || defaultSnap;
|
||||
bookmark.clickCount = articl.likenum;
|
||||
bookmark.createdAt = timeagoInstance.format(articl.addtime * 1000, 'zh_CN');
|
||||
bookmark.content = articl.content.replace(/https:\/\/mmbiz.qpic.cn/gi, "https://favicon.lucq.fun/qpic?url=https://mmbiz.qpic.cn").replace(/http:\/\/mmbiz.qpic.cn/gi, "https://favicon.lucq.fun/qpic?url=https://mmbiz.qpic.cn");
|
||||
bookmark.content = $sce.trustAsHtml(bookmark.content);
|
||||
$scope.bookmarks.push(bookmark);
|
||||
})
|
||||
} else {
|
||||
toastr.error('获取热门失败!失败原因:' + body.msg, "提示");
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
$scope.getWeixinArticles($scope.channelId, $scope.currentPage);
|
||||
}]);
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
app.controller('loginCtr', ['$scope', '$filter', '$state', '$http', '$cookieStore', '$window', 'pubSubService', 'dataService', function ($scope, $filter, $state, $http, $cookieStore, $window, pubSubService, dataService) {
|
||||
console.log("Hello loginCtr...", $cookieStore.get("username"));
|
||||
console.log("Hello loginCtr...");
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: false,
|
||||
index: dataService.NotLoginIndexLogin
|
||||
pubSubService.subscribe('Common.user', $scope, function (event, user) {
|
||||
user.id && $state.go('tags');
|
||||
});
|
||||
|
||||
$scope.username = $cookieStore.get("username") || "";
|
||||
|
|
@ -39,12 +41,12 @@ app.controller('loginCtr', ['$scope', '$filter', '$state', '$http', '$cookieStor
|
|||
$cookieStore.put("username", $scope.username);
|
||||
|
||||
let data = await post('userLogin', params);
|
||||
pubSubService.publish('Login', true);
|
||||
|
||||
// 更新token信息
|
||||
localStorage.setItem("authorization", data.token);
|
||||
|
||||
pubSubService.publish('loginCtr.login', { login: true });
|
||||
$state.go('tags')
|
||||
$state.go('tags');
|
||||
}
|
||||
|
||||
$scope.showRegister = async function () {
|
||||
|
|
@ -70,7 +72,7 @@ app.controller('loginCtr', ['$scope', '$filter', '$state', '$http', '$cookieStor
|
|||
toastr.error('账号只能是数字字母,且长度必须为3到12位', "错误");
|
||||
return;
|
||||
}
|
||||
if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test($scope.emailRegister)) {
|
||||
if (!/^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test($scope.emailRegister)) {
|
||||
toastr.error('邮箱格式输入有误', "错误");
|
||||
return;
|
||||
}
|
||||
|
|
@ -1,43 +1,51 @@
|
|||
app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$timeout', '$document', 'pubSubService', 'dataService', function ($scope, $stateParams, $state, $window, $timeout, $document, pubSubService, dataService) {
|
||||
console.log("Hello menuCtr")
|
||||
$scope.login = false; /**< 是否登陆 */
|
||||
$scope.selectLoginIndex = 0; /**< 默认登陆之后的选择的菜单索引,下表从 0 开始 */
|
||||
$scope.selectNotLoginIndex = 0; /**< 默认未登陆之后的选择的菜单索引,下表从 0 开始 */
|
||||
$scope.keyword = ''; /**< 搜索关键字 */
|
||||
$scope.login = true;
|
||||
$scope.selectLoginIndex = 0; // 默认登陆之后的选择的菜单索引,下表从 0 开始
|
||||
$scope.selectNotLoginIndex = 0; // 默认未登陆之后的选择的菜单索引,下表从 0 开始
|
||||
$scope.keyword = '';
|
||||
$scope.searchHistory = [];
|
||||
$scope.historyTypes = dataService.historyTypes;
|
||||
$scope.quickUrl = {};
|
||||
$scope.longPress = false;
|
||||
$scope.user = {};
|
||||
$scope.loaded = false; // 是否加载完毕
|
||||
|
||||
// 防止在登陆的情况下,在浏览器里面直接输入url,这时候要更新菜单选项
|
||||
pubSubService.subscribe('Common.menuActive', $scope, function (event, params) {
|
||||
console.log("subscribe Common.menuActive, login = " + params.login + ", index = " + params.index);
|
||||
$scope.login = (params && params.login) || false;
|
||||
var index = $scope.login ? ($scope.selectLoginIndex = (params && params.index) || 0) : ($scope.selectNotLoginIndex = (params && params.index) || 0);
|
||||
updateMenuActive(index);
|
||||
pubSubService.subscribe('Login', $scope, function (event, login) {
|
||||
$scope.login = login;
|
||||
});
|
||||
|
||||
pubSubService.subscribe('Settings.quickUrl', $scope, function (event, params) {
|
||||
$scope.quickUrl = params.quickUrl;
|
||||
function sleep(time) { return new Promise((resolve) => setTimeout(resolve, time)); }
|
||||
|
||||
pubSubService.subscribe('Menus.active', $scope, async function () {
|
||||
while (!$scope.loaded) { await sleep(10); }
|
||||
updateMenuActive();
|
||||
});
|
||||
|
||||
$scope.loginMenus = dataService.loginMenus; // 登陆之后显示的菜单数据。uiSerf:内部跳转链接。
|
||||
$scope.notLoginMenus = dataService.notLoginMenus; // 未登陆显示的菜单数据
|
||||
|
||||
get('user', { full: true }).then(user => {
|
||||
$timeout(() => {
|
||||
(async () => {
|
||||
$timeout(async () => {
|
||||
try {
|
||||
let user = await get('user', { full: true });
|
||||
$scope.login = true;
|
||||
$scope.user = user;
|
||||
$scope.searchHistory = JSON.parse(user.searchHistory || '[]');
|
||||
$scope.quickUrl = JSON.parse(user.quickUrl || '{}');
|
||||
$scope.searchHistory.forEach((item, index) => {
|
||||
if (user.username === 'lcq') {
|
||||
$scope.loginMenus[dataService.LoginIndexHot].show = false;
|
||||
}
|
||||
for (const item of $scope.searchHistory) {
|
||||
$scope.searchIcon(item);
|
||||
}
|
||||
} catch (error) {
|
||||
$scope.login = false;
|
||||
}
|
||||
pubSubService.publish('Common.user', $scope.user);
|
||||
$scope.loaded = true;
|
||||
})
|
||||
// if ($scope.user.username === 'lcq') {
|
||||
// $scope.loginMenus[dataService.LoginIndexHot].show = false;
|
||||
// }
|
||||
})
|
||||
});
|
||||
})()
|
||||
|
||||
$scope.toggleReady = function (ready) {
|
||||
if (ready) {
|
||||
|
|
@ -84,7 +92,6 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
}, {
|
||||
reload: true,
|
||||
})
|
||||
updateMenuActive($scope.selectLoginIndex = 0);
|
||||
} else if (searchOption == 1) {
|
||||
$window.open('https://www.google.com.hk/#newwindow=1&safe=strict&q=' + encodeURIComponent(keyword), '_blank');
|
||||
} else if (searchOption == 2) {
|
||||
|
|
@ -92,15 +99,10 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
} else if (searchOption == 3) {
|
||||
$window.open('https://stackoverflow.com/search?q=' + encodeURIComponent(keyword), '_blank');
|
||||
} else if (searchOption == 4) {
|
||||
$window.open('http://www.baidu.com/s?tn=mybookmark.cn&ch=3&ie=utf-8&wd=' + encodeURIComponent(keyword), '_blank');
|
||||
$window.open('http://www.baidu.com/s?tn=b.lucq.fun&ch=3&ie=utf-8&wd=' + encodeURIComponent(keyword), '_blank');
|
||||
} else if (searchOption == 5) {
|
||||
console.log('search note, word = ', keyword);
|
||||
$state.go('note', {
|
||||
keyword: keyword,
|
||||
}, {
|
||||
reload: true,
|
||||
})
|
||||
updateMenuActive($scope.selectLoginIndex = dataService.LoginIndexNote);
|
||||
$state.go('note', { keyword }, { reload: true })
|
||||
}
|
||||
|
||||
if (!keyword) {
|
||||
|
|
@ -186,29 +188,31 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
$window.open(url, '_blank');
|
||||
}
|
||||
|
||||
$scope.showUpdate = function () {
|
||||
$state.go('settings', {
|
||||
formIndex: 5,
|
||||
});
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexSettings
|
||||
});
|
||||
}
|
||||
|
||||
$scope.coffee = function () {
|
||||
$state.go('settings', {
|
||||
formIndex: 6,
|
||||
});
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexSettings
|
||||
});
|
||||
}
|
||||
|
||||
function updateMenuActive(index) {
|
||||
async function updateMenuActive() {
|
||||
await sleep(10); // 阻塞 10ms 是因为 document.location.hash 还没切换过来等待切换
|
||||
let mapIndex = {
|
||||
"#/bookmarks": dataService.LoginIndexBookmarks,
|
||||
"#/tags": dataService.LoginIndexTags,
|
||||
"#/note": dataService.LoginIndexNote,
|
||||
"#/hot": $scope.login ? dataService.LoginIndexHot : dataService.NotLoginIndexHot,
|
||||
"#/settings": dataService.LoginIndexSettings,
|
||||
"#/advice": dataService.LoginIndexAdvice,
|
||||
"#/": $scope.login ? dataService.LoginIndexBookmarks : dataService.NotLoginIndexHome,
|
||||
"#/login": dataService.NotLoginIndexLogin,
|
||||
}
|
||||
|
||||
console.log('updateMenuActive', $scope.login, document.location.hash, mapIndex[document.location.hash]);
|
||||
|
||||
$scope.selectLoginIndex = mapIndex[document.location.hash];
|
||||
$scope.selectNotLoginIndex = mapIndex[document.location.hash];
|
||||
$('.ui.menu a.item').removeClass('selected');
|
||||
$('.ui.menu a.item:eq(' + index + ')').addClass('selected');
|
||||
$('.ui.menu a.item:eq(' + mapIndex[document.location.hash] + ')').addClass('selected');
|
||||
}
|
||||
|
||||
async function saveHistory() {
|
||||
|
|
@ -249,7 +253,6 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
// 全局处理添加备忘录
|
||||
if (key == 'A') {
|
||||
if ($scope.selectLoginIndex !== dataService.LoginIndexNote) {
|
||||
updateMenuActive($scope.selectLoginIndex = dataService.LoginIndexNote);
|
||||
$state.go('note', { key: key }, { reload: true })
|
||||
}
|
||||
return;
|
||||
|
|
@ -269,10 +272,6 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
}
|
||||
|
||||
if (key == ',' || key == '.' || key == '/') {
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: $scope.login,
|
||||
index: dataService.LoginIndexTags
|
||||
});
|
||||
var stateParams = {
|
||||
tagId: -1,
|
||||
orderIndex: (key == ',' ? 0 : (key == '.' ? 1 : 2)),
|
||||
|
|
@ -283,11 +282,7 @@ app.controller('menuCtr', ['$scope', '$stateParams', '$state', '$window', '$time
|
|||
// 数字键用来切换菜单
|
||||
if (!isNaN(key)) {
|
||||
var num = parseInt(key);
|
||||
if (num < 0 || num > 6) return;
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: $scope.login,
|
||||
index: num - 1
|
||||
});
|
||||
if (num < 0 || num > 6 || (!$scope.login)) return;
|
||||
$state.go(dataService.loginMenus[num - 1].uiSref, {}, {
|
||||
reload: true,
|
||||
})
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
app.controller('noteCtr', ['$scope', '$state', '$stateParams', '$filter', '$window', '$timeout', '$document', 'ngDialog', 'pubSubService', 'dataService', function ($scope, $state, $stateParams, $filter, $window, $timeout, $document, ngDialog, pubSubService, dataService) {
|
||||
console.log("Hello noteCtr...", $stateParams);
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
var dialog = null;
|
||||
$scope.hoverNote = null;
|
||||
|
|
@ -25,11 +28,6 @@ app.controller('noteCtr', ['$scope', '$state', '$stateParams', '$filter', '$wind
|
|||
|
||||
var timeagoInstance = timeago();
|
||||
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexNote
|
||||
});
|
||||
|
||||
getTags();
|
||||
|
||||
$scope.changeCurrentPage = function (currentPage) {
|
||||
|
|
@ -309,11 +307,15 @@ app.controller('noteCtr', ['$scope', '$state', '$stateParams', '$filter', '$wind
|
|||
$scope.loading = true;
|
||||
var params = {
|
||||
page: $scope.currentPage,
|
||||
pageSize: 35,
|
||||
keyword: $scope.keyword,
|
||||
tagId: tagId || $scope.currentTagId
|
||||
pageSize: 35
|
||||
};
|
||||
|
||||
if (tagId || $scope.currentTagId) {
|
||||
params.tagId = tagId || $scope.currentTagId;
|
||||
} else if ($scope.keyword) {
|
||||
params.keyword = $scope.keyword;
|
||||
}
|
||||
|
||||
let reply = await get("notes", params);
|
||||
$timeout(function () {
|
||||
let notes = reply.data;
|
||||
|
|
@ -363,6 +365,7 @@ app.controller('noteCtr', ['$scope', '$state', '$stateParams', '$filter', '$wind
|
|||
|
||||
$timeout(() => {
|
||||
$scope.loading = false;
|
||||
tags.sort((a, b) => a.sort - b.sort);
|
||||
$scope.tags = tags;
|
||||
getNotes();
|
||||
})
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
app.controller('searchCtr', ['$scope', '$state', '$stateParams', '$filter', '$window', '$timeout', '$document', 'ngDialog', 'pubSubService', 'dataService', function ($scope, $state, $stateParams, $filter, $window, $timeout, $document, ngDialog, pubSubService, dataService) {
|
||||
console.log("Hello searchCtr...", $stateParams);
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
$scope.hoverBookmark = null;
|
||||
$scope.bookmarks = []; // 书签数据
|
||||
|
|
@ -36,16 +39,13 @@ app.controller('searchCtr', ['$scope', '$state', '$stateParams', '$filter', '$wi
|
|||
$scope.search();
|
||||
}
|
||||
}
|
||||
pubSubService.subscribe('Common.user', $scope, function (event, user) {
|
||||
$scope.user = user;
|
||||
});
|
||||
|
||||
get('tags').then((tags) => $scope.tags = tags)
|
||||
get('user').then((user) => $scope.user = user)
|
||||
|
||||
// 默认登陆
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexBookmarks
|
||||
});
|
||||
|
||||
$scope.jumpToUrl = async function (url, id) {
|
||||
if (!$scope.edit) {
|
||||
$window.open(url);
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$window', '$timeout', 'pubSubService', 'dataService', function ($scope, $stateParams, $filter, $state, $window, $timeout, pubSubService, dataService) {
|
||||
console.log('Hello settingsCtr......', $stateParams);
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
$scope.forbidQuickKey = dataService.forbidQuickKey
|
||||
$scope.form = [false, false, false, false, false, false, false];
|
||||
|
|
@ -17,9 +20,12 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
$scope.key = '';
|
||||
$scope.url = '';
|
||||
$scope.quickUrl = {};
|
||||
$scope.loading = false;
|
||||
$scope.href = "";
|
||||
|
||||
$scope.changeForm = async function (index) {
|
||||
console.log("changeForm = ", index);
|
||||
$scope.href = "";
|
||||
$scope.form = $scope.form.map(() => false);
|
||||
$scope.form[index] = true;
|
||||
if (index == 0 || index == 1 || index == 4) {
|
||||
|
|
@ -40,6 +46,11 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
$scope.changeForm($scope.form.indexOf(true)); // 马上调用一次
|
||||
|
||||
$scope.resetPassword = async function () {
|
||||
if($scope.user.username == 'test') {
|
||||
toastr.error('此用户不允许修改密码', "错误");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$scope.passwordOrgin || !$scope.passwordNew1 || !$scope.passwordNew2) {
|
||||
toastr.error('原密码跟新密码不能为空', "错误");
|
||||
return;
|
||||
|
|
@ -49,12 +60,7 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
await post('userResetPwd', { old: $scope.passwordOrgin, password: $scope.passwordNew1 });
|
||||
await post('userLogout');
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = "";
|
||||
localStorage.setItem("authorization", "");
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: false,
|
||||
index: dataService.NotLoginIndexLogin
|
||||
});
|
||||
$state.go('login', {})
|
||||
} else {
|
||||
toastr.error('新密码两次输入不一致', "错误");
|
||||
|
|
@ -117,8 +123,13 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
}
|
||||
|
||||
$scope.exportBookmark = async function () {
|
||||
let data = await get('bookmarkBackup');
|
||||
console.log(data);
|
||||
$scope.loading = true;
|
||||
let fileName = await get('bookmarkBackup');
|
||||
$timeout(() => {
|
||||
$scope.href = `${document.location.origin}/api/bookmarkDownload?fileName=${fileName}`;
|
||||
$scope.loading = false;
|
||||
$window.open($scope.href, '_blank');
|
||||
})
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
|
|
@ -136,10 +147,6 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
console.log(files, response);
|
||||
if (response.code == 0) {
|
||||
setTimeout(function () {
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexBookmarks
|
||||
});
|
||||
$state.go('tags', {})
|
||||
}, 3000);
|
||||
toastr.success(response.msg, "提示");
|
||||
|
|
@ -151,11 +158,6 @@ app.controller('settingsCtr', ['$scope', '$stateParams', '$filter', '$state', '$
|
|||
$(".ui.pointing.menu .item").removeClass("selected");
|
||||
}, 500);
|
||||
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexSettings
|
||||
});
|
||||
|
||||
async function saveQuickUrl() {
|
||||
await post("userUpdate", { quickUrl: JSON.stringify($scope.quickUrl) });
|
||||
toastr.success('全局快捷键更新成功', "提示");
|
||||
|
|
@ -1,12 +1,19 @@
|
|||
app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$stateParams', '$timeout', '$document', 'ngDialog', 'pubSubService', 'dataService', function ($scope, $filter, $state, $window, $stateParams, $timeout, $document, ngDialog, pubSubService, dataService) {
|
||||
console.log("Hello tagsCtr...", $stateParams);
|
||||
if (dataService.smallDevice()) {
|
||||
$window.location = "http://m.mybookmark.cn/#/tags";
|
||||
if ($window.location.hostname.indexOf("b.lucq.fun") >= 0) {
|
||||
$window.location = "http://mb.lucq.fun/#/tags";
|
||||
return;
|
||||
}
|
||||
}
|
||||
pubSubService.publish('Menus.active');
|
||||
|
||||
(async () => {
|
||||
await getTags();
|
||||
$scope.user = await get('user');
|
||||
if ($scope.user.username != 'lcq') {
|
||||
$(".globalTag").show(); // 自己知道这个功能,不显示
|
||||
}
|
||||
})()
|
||||
|
||||
let dialog = null;
|
||||
|
|
@ -17,10 +24,12 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
$scope.showType = "createdAt";
|
||||
$scope.loading = true;
|
||||
$scope.tags = []; // 书签数据
|
||||
$scope.user = { username: "test" };
|
||||
$scope.tagsIndex = []; // 书签索引
|
||||
$scope.bookmarks = [];
|
||||
$scope.totalPages = 0;
|
||||
$scope.currentPage = 0;
|
||||
$scope.pageSize = 80;
|
||||
$scope.inputPage = '';
|
||||
$scope.currentTagId = ($stateParams && $stateParams.tagId) || (-1);
|
||||
$scope.editMode = false;
|
||||
|
|
@ -30,11 +39,6 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
$scope.waitDelBookmark = {};
|
||||
$scope.bookmarkNormalHover = false;
|
||||
|
||||
pubSubService.subscribe('MenuCtr.tags', $scope, function (event, data) {
|
||||
console.log('subscribe MenuCtr.tags', data);
|
||||
getTags();
|
||||
});
|
||||
|
||||
$scope.getBookmarks = async function (tagId, page, showType) {
|
||||
console.log(tagId, page, showType);
|
||||
|
||||
|
|
@ -44,7 +48,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
showType && ($scope.showType = showType);
|
||||
$scope.loading = true;
|
||||
|
||||
let pageSize = ($scope.showMode == 'item') ? 50 : 20;
|
||||
let pageSize = ($scope.showMode == 'item') ? $scope.pageSize : 20;
|
||||
|
||||
for (let tag of $scope.tags) {
|
||||
tag.bookmarkClicked = (tag.id == $scope.currentTagId);
|
||||
|
|
@ -84,13 +88,12 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
clearInterval(id);
|
||||
}
|
||||
}, 10);
|
||||
} else if ($scope.showMode == 'item' && bookmarks.length > $scope.pageSize / 2 && $scope.currentTagId == -1) {
|
||||
$timeout(() => {
|
||||
$("#" + bookmarks[bookmarks.length / 2 - 1].id).after(`<div class="ui divider" style="width:100%;margin:0px 15px -1px 15px"></div>`);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexTags
|
||||
});
|
||||
|
||||
$timeout(function () {
|
||||
dataService.transition('#' + addBookmarkId, {
|
||||
duration: 1000,
|
||||
|
|
@ -277,7 +280,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
|
||||
$scope.addTag = async function (tag) {
|
||||
console.log(tag);
|
||||
if ($scope.tags.length >= 30) {
|
||||
if ($scope.tags.length >= 50) {
|
||||
toastr.error('标签个数总数不能超过30个!不允许再添加新分类,如有需求,请联系管理员。', "提示");
|
||||
return;
|
||||
}
|
||||
|
|
@ -355,6 +358,10 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
})
|
||||
});
|
||||
|
||||
$scope.globalTag = function () {
|
||||
$state.go('settings', { formIndex: 4 });
|
||||
}
|
||||
|
||||
async function updateTags(_tags) {
|
||||
let tags = JSON.parse(JSON.stringify(_tags));
|
||||
|
||||
|
|
@ -365,8 +372,9 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
id: -1,
|
||||
bookmarkCount: '...',
|
||||
bookmarkClicked: false,
|
||||
name: '个人定制',
|
||||
show: 1
|
||||
name: '全部',
|
||||
show: 1,
|
||||
sort: -1
|
||||
})
|
||||
|
||||
let find = false;
|
||||
|
|
@ -384,10 +392,7 @@ app.controller('tagsCtr', ['$scope', '$filter', '$state', '$window', '$statePara
|
|||
tags[0].bookmarkClicked = true;
|
||||
}
|
||||
|
||||
pubSubService.publish('Common.menuActive', {
|
||||
login: true,
|
||||
index: dataService.LoginIndexTags
|
||||
});
|
||||
tags.sort((a, b) => a.sort - b.sort);
|
||||
|
||||
$timeout(() => {
|
||||
$scope.loading = false;
|
||||
|
|
@ -150,34 +150,9 @@ app.directive('jsMenuInit', function ($compile) {
|
|||
link: function ($scope, $element, $attrs) {
|
||||
if ($scope.$last === true) {
|
||||
console.log('jsMenuInit......')
|
||||
$('.js-bookmark-dropdown').dropdown({
|
||||
action: 'hide',
|
||||
on: 'hover',
|
||||
});
|
||||
|
||||
$('.js-bookmark-dropdown .ui.checkbox').checkbox();
|
||||
$('.ui.checkbox.js-radio-navigate').checkbox('check');
|
||||
$('.ui.menu a.item').on('click', function () {
|
||||
$(this).addClass('selected').siblings().removeClass('selected');
|
||||
});
|
||||
|
||||
$(".ui.menu a.item:first").hover(
|
||||
function () {
|
||||
$('.js-bookmark-dropdown').dropdown('show');
|
||||
},
|
||||
function () {
|
||||
setTimeout(() => {
|
||||
if ($('.js-menu-option:hover').length === 0) {
|
||||
$('.js-bookmark-dropdown').dropdown('hide');
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
);
|
||||
|
||||
$('.ui.menu a.item').on('click', function () {
|
||||
$(this).addClass('selected').siblings().removeClass('selected');
|
||||
});
|
||||
|
||||
$('.search-item').popup({
|
||||
on: 'focus',
|
||||
inline: true
|
||||