Просмотр исходного кода

Merge branch 'laravel-migrate-wbw' of https://github.com/visuddhinanda/mint into laravel

bhikkhu-kosalla-china 4 лет назад
Родитель
Сommit
f7eb9a2b3a
100 измененных файлов с 2822 добавлено и 744 удалено
  1. 1 1
      .env.example
  2. 11 0
      app/Models/Article.php
  3. 11 0
      app/Models/ArticleCollection.php
  4. 11 0
      app/Models/Channel.php
  5. 11 0
      app/Models/Collection.php
  6. 11 0
      app/Models/SentBlock.php
  7. 11 0
      app/Models/SentHistory.php
  8. 11 0
      app/Models/SentPr.php
  9. 11 0
      app/Models/Sentence.php
  10. 11 0
      app/Models/UserDict.php
  11. 11 0
      app/Models/UserOperationDaily.php
  12. 11 0
      app/Models/UserOperationFrame.php
  13. 11 0
      app/Models/UserOperationLog.php
  14. 11 0
      app/Models/Wbw.php
  15. 11 0
      app/Models/WbwBlock.php
  16. 13 1
      app/Providers/AppServiceProvider.php
  17. 2 9
      change-logs.md
  18. 10 0
      config/database.php
  19. 52 0
      database/migrations/2022_01_19_090727_create_wbws_table.php
  20. 63 0
      database/migrations/2022_01_19_110604_create_wbw_blocks_table.php
  21. 46 0
      database/migrations/2022_01_20_135745_create_channels_table.php
  22. 78 0
      database/migrations/2022_01_22_152901_create_sentences_table.php
  23. 73 0
      database/migrations/2022_01_27_130346_create_sent_blocks_table.php
  24. 58 0
      database/migrations/2022_01_27_132319_create_sent_prs_table.php
  25. 47 0
      database/migrations/2022_01_27_133456_create_sent_histories_table.php
  26. 56 0
      database/migrations/2022_01_28_081954_create_user_dicts_table.php
  27. 39 0
      database/migrations/2022_01_28_092534_create_user_operation_dailies_table.php
  28. 40 0
      database/migrations/2022_01_28_102330_create_user_operation_frames_table.php
  29. 55 0
      database/migrations/2022_01_28_105209_create_user_operation_logs_table.php
  30. 54 0
      database/migrations/2022_01_28_121154_create_articles_table.php
  31. 53 0
      database/migrations/2022_01_28_123829_create_collections_table.php
  32. 41 0
      database/migrations/2022_01_28_124816_create_article_collections_table.php
  33. 4 4
      public/app/admin/update_user_active_time.php
  34. 25 0
      public/app/api/bootstrap.php
  35. 24 0
      public/app/api/controller/controller.php
  36. 32 0
      public/app/api/controller/sent_prs.php
  37. 258 0
      public/app/api/controller/user_dicts.php
  38. 80 0
      public/app/api/controller/user_operation_logs.php
  39. 9 0
      public/app/api/model/sent_prs.php
  40. 9 0
      public/app/api/model/user_dicts.php
  41. 9 0
      public/app/api/model/user_operation_dailys.php
  42. 9 0
      public/app/api/model/user_operation_frames.php
  43. 9 0
      public/app/api/model/user_operation_logs.php
  44. 34 0
      public/app/api/sent_prs.php
  45. 34 0
      public/app/api/user_dicts.php
  46. 26 9
      public/app/article/add_article_to_collect.php
  47. 6 6
      public/app/article/collect_get.php
  48. 5 4
      public/app/article/collect_list.php
  49. 28 20
      public/app/article/function.php
  50. 2 10
      public/app/article/list.php
  51. 8 6
      public/app/article/list_article_in_collect.php
  52. 4 4
      public/app/article/list_new.php
  53. 4 3
      public/app/article/my_article_post.php
  54. 34 3
      public/app/article/my_article_put.php
  55. 22 7
      public/app/article/my_collect_post.php
  56. 34 4
      public/app/article/my_collect_put.php
  57. 198 0
      public/app/auth/README.md
  58. 159 0
      public/app/auth/api.php
  59. 0 1
      public/app/auth/casbin-test.php
  60. 6 4
      public/app/channal/card.php
  61. 4 5
      public/app/channal/channal.js
  62. 10 10
      public/app/channal/function.php
  63. 10 7
      public/app/channal/get.php
  64. 9 7
      public/app/channal/my_channal_get.php
  65. 8 5
      public/app/channal/my_channal_post.php
  66. 6 3
      public/app/channal/my_channal_put.php
  67. 2 2
      public/app/collect/card.php
  68. 33 19
      public/app/collect/function.php
  69. 4 4
      public/app/collect/list.php
  70. 7 10
      public/app/commit/commit.js
  71. 18 2
      public/app/commit/commit.php
  72. 5 0
      public/app/config.sample.php
  73. 31 29
      public/app/config.table.php
  74. 5 11
      public/app/db/channel.php
  75. 2 1
      public/app/db/database.php
  76. 3 0
      public/app/db/table.php
  77. 5 3
      public/app/db/test.php
  78. 5 5
      public/app/db/wbw_block.php
  79. 17 14
      public/app/dict/dict_lookup.php
  80. 11 10
      public/app/dict/redis_import_user.php
  81. 4 4
      public/app/dict/redis_pali_word_statistic.php
  82. 13 10
      public/app/doc/edit_wbw.php
  83. 63 129
      public/app/doc/fork.php
  84. 203 170
      public/app/doc/fork_channel.php
  85. 6 6
      public/app/doc/load_channal_para.php
  86. 29 33
      public/app/doc/pcs2db.php
  87. 1 1
      public/app/group/group.js
  88. 2 2
      public/app/pali_sent/get_sim.php
  89. 3 1
      public/app/pali_sent/pali_sent_list.php
  90. 2 2
      public/app/pcdl/reader1.php
  91. 15 0
      public/app/public/snowflakeid.php
  92. 4 0
      public/app/setting.php
  93. 1 1
      public/app/share/function.php
  94. 65 83
      public/app/studio/dict_updata_wbw.php
  95. 1 1
      public/app/studio/index_head.php
  96. 70 3
      public/app/studio/js/editor.js
  97. 27 17
      public/app/studio/js/render.js
  98. 3 3
      public/app/studio/js/wizard.js
  99. 9 10
      public/app/studio/pc_get_word_num.php
  100. 99 25
      public/app/studio/project.php

+ 1 - 1
.env.example

@@ -60,5 +60,5 @@ ASSETS_SERVER="https://assets-hk.wikipali.org"
 HELP_SERVER="https://help-hk.wikipali.org"
 GRAMMAR_SERVER="https://grammar-hk.wikipali.org"
 
-SNOWFLAKE_DATA_CENTER_ID = 1
+SNOWFLAKE_DATACENTER_ID = 1
 SNOWFLAKE_WORKER_ID = 1

+ 11 - 0
app/Models/Article.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Article extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/ArticleCollection.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class ArticleCollection extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/Channel.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Channel extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/Collection.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Collection extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/SentBlock.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class SentBlock extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/SentHistory.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class SentHistory extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/SentPr.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class SentPr extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/Sentence.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Sentence extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/UserDict.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class UserDict extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/UserOperationDaily.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class UserOperationDaily extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/UserOperationFrame.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class UserOperationFrame extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/UserOperationLog.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class UserOperationLog extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/Wbw.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Wbw extends Model
+{
+    use HasFactory;
+}

+ 11 - 0
app/Models/WbwBlock.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class WbwBlock extends Model
+{
+    use HasFactory;
+}

+ 13 - 1
app/Providers/AppServiceProvider.php

@@ -2,6 +2,9 @@
 
 namespace App\Providers;
 
+use Godruoyi\Snowflake\Snowflake;
+use Godruoyi\Snowflake\LaravelSequenceResolver;
+
 use Illuminate\Support\ServiceProvider;
 
 class AppServiceProvider extends ServiceProvider
@@ -13,7 +16,16 @@ class AppServiceProvider extends ServiceProvider
      */
     public function register()
     {
-        //
+        //雪花算法
+		
+		$this->app->singleton('snowflake', function () {
+            return (new Snowflake())
+                ->setStartTimeStamp(strtotime(config('database.snowflake.start'))*1000)
+                ->setSequenceResolver(
+                    new LaravelSequenceResolver($this->app->get('cache')->store()
+                ));
+        });
+		
     }
 
     /**

+ 2 - 9
change-logs.md

@@ -34,15 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - rename RPC_DOMAIN_NAME -> RPC_SERVER in config.sample.js
 - add RPC_SERVER to .env.example
 
-## [1.0.4] - 2022-01-21
+## [1.0.4] - 2022-01-19
 
 - add SNOWFLAKE to .env.example
-- add SnowFlake to config.sample.php
-- add SnowFlakeDate to config.table.php
+- add snowflake to database.php
 - add dependency godruoyi/php-snowflake
-
-## [1.0.5] - 2022-01-24
-
-- add 帮助文件路径 URL_HELP to config.dir.php
-- add 巴利语手册路径 URL_PALI_HANDBOOK to config.dir.php
-- add help & handbook link 

+ 10 - 0
config/database.php

@@ -144,4 +144,14 @@ return [
 
     ],
 
+	/*
+    |--------------------------------------------------------------------------
+    | snowflake id start date don't modify
+    |--------------------------------------------------------------------------
+    |
+    |
+    */
+	'snowflake' => [
+		'start'=>"2021-12-22",
+	],
 ];

+ 52 - 0
database/migrations/2022_01_19_090727_create_wbws_table.php

@@ -0,0 +1,52 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateWbwsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('wbws', function (Blueprint $table) {
+            $table->bigInteger('id')->primary();
+			$table->string('uid',36)->uniqid()->index();
+			$table->string('block_uid',36)->nullable()->index();
+            $table->bigInteger('block_id')->nullable()->index();
+            $table->bigInteger('channel_id')->nullable()->index();
+			$table->integer('book_id');
+			$table->integer('paragraph');
+			$table->bigInteger('wid');
+			$table->string("word",1024);
+			$table->text("data")->default('');
+			$table->integer('status')->default(10);
+			$table->string('creator_uid',36);
+            $table->bigInteger('editor_id');
+            $table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+ 
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['book_id','paragraph','wid']);
+			$table->index(['book_id','paragraph']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('wbws');
+    }
+}

+ 63 - 0
database/migrations/2022_01_19_110604_create_wbw_blocks_table.php

@@ -0,0 +1,63 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateWbwBlocksTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+		/*
+
+ 
+
+ 
+    style VARCHAR (16), 
+    lang VARCHAR (16)  NOT NULL, 
+    status INTEGER  NOT NULL, 
+		*/
+        Schema::create('wbw_blocks', function (Blueprint $table) {
+            $table->bigInteger('id')->primary();
+			$table->string('uid',36)->uniqid()->index();			
+			$table->string('parent_id',36)->nullable();
+			$table->string('block_uid',36)->nullable()->index();
+            $table->bigInteger('block_id')->nullable()->index();
+            $table->bigInteger('channel_id')->nullable()->index();
+            $table->string('channel_uid',36)->nullable()->index();
+			$table->string('parent_channel_uid',36)->nullable();
+			$table->string('creator_uid',36);
+            $table->bigInteger('editor_id');
+			$table->integer('book_id');
+			$table->integer('paragraph');
+			$table->string('style',16)->nullable();
+			$table->string("lang",16);
+			$table->integer('status')->default(10);
+
+            $table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+ 
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['book_id','paragraph']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('wbw_blocks');
+    }
+}

+ 46 - 0
database/migrations/2022_01_20_135745_create_channels_table.php

@@ -0,0 +1,46 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateChannelsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('channels', function (Blueprint $table) {
+            $table->bigInteger('id')->primary();
+			$table->string('uid',36)->uniqid()->index();
+			$table->enum('type',['original','translation','nissaya','commentary'])->default('translation');
+			$table->string('owner_uid',36);
+            $table->bigInteger('editor_id');
+			$table->string('name',128)->index();
+			$table->string('summary',1024)->nullable();
+			$table->string('lang',16);
+			$table->integer('status')->default(10);
+			$table->text('setting')->nullable();
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('channels');
+    }
+}

+ 78 - 0
database/migrations/2022_01_22_152901_create_sentences_table.php

@@ -0,0 +1,78 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateSentencesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+		/*
+
+	parent_uid VARCHAR (36), 
+	block_uid VARCHAR (36), 
+	channel_uid VARCHAR (36), 
+	book_id INTEGER NOT NULL, 
+	paragraph INTEGER NOT NULL, 
+	word_start INTEGER NOT NULL, 
+	word_end INTEGER NOT NULL, 
+	author TEXT, 
+	editor_uid VARCHAR (36), 
+	content TEXT, 
+	language VARCHAR (16), 
+	version INTEGER NOT NULL DEFAULT (1), 
+	status INTEGER NOT NULL DEFAULT (10), 
+	strlen INTEGER, 
+
+		*/
+        Schema::create('sentences', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+
+			$table->string('uid',36)->uniqid()->index();
+			$table->string('parent_uid',36)->nullable()->index();
+			$table->string('block_uid',36)->nullable()->index();
+			$table->string('channel_uid',36)->nullable()->index();
+			$table->integer('book_id');
+			$table->integer('paragraph');
+			$table->integer('word_start');
+			$table->integer('word_end');
+			$table->string('author',512)->nullable();
+
+			$table->string('editor_uid',36);
+            $table->text('content')->nullable();
+            $table->enum('content_type',['markdown','text','html'])->default('markdown');
+			$table->string('language',16);
+			$table->integer('version')->default(1);
+			$table->integer('strlen');
+			$table->integer('status')->default(10);
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['book_id','paragraph','word_start','word_end']);
+			$table->index(['book_id','paragraph','word_start','word_end','channel_uid']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('sentences');
+    }
+}

+ 73 - 0
database/migrations/2022_01_27_130346_create_sent_blocks_table.php

@@ -0,0 +1,73 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateSentBlocksTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+     /*
+     CREATE TABLE sent_blocks 
+(
+    id SERIAL PRIMARY KEY,
+	uid VARCHAR (36), 
+	parent_uid VARCHAR (36), 
+	book_id INTEGER, 
+	paragraph INTEGER, 
+	owner_uid VARCHAR (36), 
+	lang VARCHAR (16), 
+	author VARCHAR (50), 
+	editor_uid VARCHAR (36),
+	status INTEGER NOT NULL DEFAULT (10), 
+	modify_time BIGINT, 
+	create_time BIGINT,
+	created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+	updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+	deleted_at TIMESTAMP
+);
+
+CREATE UNIQUE INDEX sent_blocks_uid ON sent_blocks (uid);
+CREATE INDEX sent_blocks_book_para ON sent_blocks (book_id,paragraph);
+     */
+    public function up()
+    {
+        Schema::create('sent_blocks', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+			$table->string('uid',36)->uniqid()->index();
+			$table->string('parent_uid',36)->nullable()->index();
+			$table->integer('book_id');
+			$table->integer('paragraph');
+			$table->string('owner_uid',36);
+			$table->string('editor_uid',36);
+			$table->string('lang',16);
+			$table->string('author',64);
+			$table->integer('status')->default(10);
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['book_id','paragraph']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('sent_blocks');
+    }
+}

+ 58 - 0
database/migrations/2022_01_27_132319_create_sent_prs_table.php

@@ -0,0 +1,58 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateSentPrsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+
+    public function up()
+    {
+        Schema::create('sent_prs', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+            //用作数据迁移时的相同数据比对
+			$table->integer('old_id')->nullable();
+
+			$table->integer('book_id');
+			$table->integer('paragraph');
+            $table->integer('word_start');
+			$table->integer('word_end');
+			$table->string('channel_uid',36);
+
+			$table->string('author',512)->nullable();
+			$table->string('editor_uid',36);
+
+			$table->text('content');
+			$table->string('language',16);
+			$table->integer('status')->default(10);
+			$table->integer('strlen')->default(0);
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['book_id','paragraph','word_start','word_end','channel_uid']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('sent_prs');
+    }
+}

+ 47 - 0
database/migrations/2022_01_27_133456_create_sent_histories_table.php

@@ -0,0 +1,47 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateSentHistoriesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+     /*
+         id SERIAL PRIMARY KEY,
+	sent_uid VARCHAR (36), 
+	user_uid VARCHAR (36), 
+	content TEXT, 
+	landmark VARCHAR (64),
+	date BIGINT,
+	created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+     */
+    public function up()
+    {
+        Schema::create('sent_histories', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+			$table->string('sent_uid',36)->index();
+			$table->string('user_uid',36);
+			$table->text('content');
+			$table->string('landmark',64)->nullable();
+
+			$table->bigInteger('create_time')->index();
+			$table->timestamp('created_at')->useCurrent();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('sent_histories');
+    }
+}

+ 56 - 0
database/migrations/2022_01_28_081954_create_user_dicts_table.php

@@ -0,0 +1,56 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserDictsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_dicts', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+
+			$table->string('word',1024)->index();
+			$table->string('type',128)->nullable();
+			$table->string('grammar',128)->nullable();
+			$table->string('parent',1024)->nullable();
+			$table->text('mean')->nullable();
+			$table->text('note')->nullable();
+			$table->string('factors',1024)->nullable();
+			$table->string('factormean',1024)->nullable();
+		    $table->integer('status')->default(10);
+			$table->string('source',1024)->nullable();
+
+			$table->string('language',16)->default('en-US');
+		    $table->integer('confidence')->default(100);
+		    $table->integer('exp')->default(0);
+            $table->bigInteger('creator_id')->index();
+            $table->bigInteger('ref_counter')->default(1);
+
+			$table->bigInteger('create_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+
+			$table->index(['word','creator_id']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_dicts');
+    }
+}

+ 39 - 0
database/migrations/2022_01_28_092534_create_user_operation_dailies_table.php

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserOperationDailiesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_operation_dailies', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+		    $table->bigInteger('user_id')->index();
+		    $table->bigInteger('date_int')->index();
+		    $table->bigInteger('duration');
+		    $table->integer('hit')->default(1);
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_operation_dailies');
+    }
+}

+ 40 - 0
database/migrations/2022_01_28_102330_create_user_operation_frames_table.php

@@ -0,0 +1,40 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserOperationFramesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_operation_frames', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+		    $table->bigInteger('user_id')->index();
+		    $table->bigInteger('duration');
+            $table->integer('hit')->default(1);
+		    $table->bigInteger('timezone')->default(0);
+		    $table->bigInteger('op_start');
+		    $table->bigInteger('op_end');
+		    
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_operation_frames');
+    }
+}

+ 55 - 0
database/migrations/2022_01_28_105209_create_user_operation_logs_table.php

@@ -0,0 +1,55 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserOperationLogsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_operation_logs', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+		    $table->bigInteger('user_id')->index();
+		    $table->bigInteger('op_type_id')->index();
+            $table->enum('op_type',['channel_update',
+                                    'channel_create',
+                                    'article_update',
+                                    'article_create',
+                                    'dict_lookup',
+                                    'term_create',
+                                    'term_update',
+                                    'term_lookup',
+                                    'wbw_update',
+                                    'wbw_create',
+                                    'sent_update',
+                                    'sent_create',
+                                    'collection_update',
+                                    'collection_create',
+                                    'nissaya_open'
+                                    ]);
+            $table->text('content')->nullable();
+		    $table->bigInteger('timezone')->default(0);
+		    $table->bigInteger('create_time');
+			$table->timestamp('created_at')->useCurrent();
+
+            $table->index(['user_id','op_type_id']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_operation_logs');
+    }
+}

+ 54 - 0
database/migrations/2022_01_28_121154_create_articles_table.php

@@ -0,0 +1,54 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateArticlesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('articles', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+
+			$table->string('uid',36)->uniqid()->index();
+			$table->bigInteger('parent_id')->nullable()->index();
+			$table->bigInteger('default_channel_id')->nullable()->index();
+			$table->string('title',128)->index();
+			$table->string('subtitle',128)->nullable();
+			$table->string('summary',1024)->nullable();
+			$table->text('cover')->nullable();
+            $table->text('content')->nullable();
+            $table->enum('content_type',['markdown','text','html'])->default('markdown');
+            $table->string('owner',36)->index();
+            $table->bigInteger('owner_id')->index();
+            $table->bigInteger('editor_id')->index();
+			$table->text('setting')->nullable();
+            $table->integer('status')->default(10)->index();
+            $table->string('lang',16)->default('none')->index();
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('articles');
+    }
+}

+ 53 - 0
database/migrations/2022_01_28_123829_create_collections_table.php

@@ -0,0 +1,53 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateCollectionsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('collections', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+
+			$table->string('uid',36)->uniqid()->index();
+			$table->bigInteger('parent_id')->nullable()->index();
+			$table->bigInteger('default_channel_id')->nullable()->index();
+			$table->string('title',128)->index();
+			$table->string('subtitle',128)->nullable();
+			$table->string('summary',1024)->nullable();
+			$table->text('cover')->nullable();
+            $table->text('article_list')->nullable();
+            $table->string('owner',36)->index();
+            $table->bigInteger('owner_id')->index();
+            $table->bigInteger('editor_id')->index();
+			$table->text('setting')->nullable();
+            $table->integer('status')->default(10)->index();
+            $table->string('lang',16)->default('none')->index();
+
+			$table->bigInteger('create_time')->index();
+            $table->bigInteger('modify_time')->index();
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+			$table->timestamp('deleted_at')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('collections');
+    }
+}

+ 41 - 0
database/migrations/2022_01_28_124816_create_article_collections_table.php

@@ -0,0 +1,41 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateArticleCollectionsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('article_collections', function (Blueprint $table) {
+			#使用雪花id
+            $table->bigInteger('id')->primary();
+
+			$table->string('collect_id',36)->index();
+			$table->string('article_id',36)->index();
+			$table->integer('level');
+            $table->string('title',128)->nullable()->index();
+			$table->integer('children')->default(0);
+            $table->bigInteger('editor_id')->default(0);
+
+			$table->timestamp('created_at')->useCurrent();
+			$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('article_collections');
+    }
+}

+ 4 - 4
public/app/admin/update_user_active_time.php

@@ -9,14 +9,14 @@ $start = strtotime($last . " +1 day");
 $end = strtotime($last . " +2 day");
 $today = strtotime("today");
 
-$dbh = new PDO(_FILE_DB_USER_ACTIVE_, "", "", array(PDO::ATTR_PERSISTENT => true));
+$dbh = new PDO(_FILE_DB_USER_ACTIVE_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
 $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
-$dbh_index = new PDO(_FILE_DB_USER_ACTIVE_INDEX_, "", "", array(PDO::ATTR_PERSISTENT => true));
+$dbh_index = new PDO(_FILE_DB_USER_ACTIVE_INDEX_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
 $dbh_index->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 /* 开始一个事务,关闭自动提交 */
 $dbh_index->beginTransaction();
-$query = "INSERT INTO active_index (user_id, date , duration , hit) VALUES (?, ?, ? , ?)";
+$query = "INSERT INTO "._TABLE_SRC_USER_OPERATION_DAILY_." (user_id, date_int , duration , hit) VALUES (?, ?, ? , ?)";
 $sth_index = $dbh_index->prepare($query);
 
 $runing = $last;
@@ -25,7 +25,7 @@ while ($end <= $today) {
     echo "runing:" . $runing . "\n";
 
     # do one day
-    $query = "SELECT user_id, sum(duration) as time , sum(hit) as hit  FROM edit WHERE end between ? and ?  group by user_id ";
+    $query = "SELECT user_id, sum(duration) as time , sum(hit) as hit  FROM "._TABLE_SRC_USER_OPERATION_FRAME_." WHERE end between ? and ?  group by user_id ";
     $stmt = $dbh->prepare($query);
     $stmt->execute(array($start * 1000, $end * 1000));
     while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {

+ 25 - 0
public/app/api/bootstrap.php

@@ -0,0 +1,25 @@
+<?php
+require __DIR__."/../../vendor/autoload.php";
+require_once __DIR__."/../config.php";
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+
+$capsule = new Capsule;
+$capsule->addConnection([
+	'driver' => Database["type"],
+	'host' => Database["server"],
+	'port' => Database["port"],
+	'database' => Database["name"],
+	'username' =>  Database["user"],
+	'password' => Database["password"],
+	'charset' => 'utf8',
+	'options' => [
+		PDO::ATTR_PERSISTENT => true,
+	],
+	'prefix' => '',
+	'prefix_indexes' => true,
+	'schema' => 'public',
+	'sslmode' => 'prefer',
+]);
+$capsule->setAsGlobal();
+$capsule->bootEloquent();

+ 24 - 0
public/app/api/controller/controller.php

@@ -0,0 +1,24 @@
+<?php
+require_once __DIR__."/../../redis/function.php";
+
+Class Controller{
+	protected $redis;
+	protected $response;
+
+	function __construct($redis=true) {
+		if($redis){
+			$this->redis = redis_connect();
+		}
+		$response = ["ok"=>true,"message"=>"","data"=>null];
+	}
+
+	public function error($message){
+		$this->response = ["ok"=>false,"message"=>$message,"data"=>null];
+		echo json_encode($this->response, JSON_UNESCAPED_UNICODE);
+	}
+
+	public function ok($data){
+		$this->response = ["ok"=>true,"message"=>"","data"=>$data];
+		echo json_encode($this->response, JSON_UNESCAPED_UNICODE);
+	}
+}

+ 32 - 0
public/app/api/controller/sent_prs.php

@@ -0,0 +1,32 @@
+<?php
+require_once __DIR__."/../model/sent_prs.php";
+require_once __DIR__."/controller.php";
+
+
+Class CtlSentPr extends Controller{
+	public function index(){
+		$result = SentPr::find($_GET["id"]);
+		echo $result["content"];
+	}	
+	public function create(){
+		$result = SentPr::find($_GET["id"]);
+		echo $result["content"];
+	}	
+		
+	public function show(){
+		$result = SentPr::find($_GET["id"]);
+		if($result){
+			$this->ok($result);
+		}else{
+			$this->error("没有查询到数据");
+		}
+	}
+	public function update(){
+		$result = SentPr::find($_GET["id"]);
+		echo $result["content"];
+	}	
+	public function delete(){
+		$result = SentPr::find($_GET["id"]);
+		echo $result["content"];
+	}
+} 

+ 258 - 0
public/app/api/controller/user_dicts.php

@@ -0,0 +1,258 @@
+<?php
+require_once __DIR__."/../model/user_dicts.php";
+require_once __DIR__."/controller.php";
+require_once __DIR__."/../../public/snowflakeid.php";
+require_once __DIR__."/../../public/function.php";
+
+Class CtlUserDict extends Controller{
+	public function index(){
+		$result=false;
+		$indexCol = ['id','word','type','grammar','mean','factors','confidence','updated_at'];
+		switch ($_GET["view"]) {
+			case 'user':
+				# code...
+				$table = UserDict::select($indexCol)
+									->where('creator_id', $_COOKIE["user_id"])
+									->where('source', '<>', "_SYS_USER_WBW_");
+				if(isset($_GET["search"])){
+					$table->where('word', 'like', $_GET["search"]."%");
+				}
+				if(isset($_GET["order"]) && isset($_GET["dir"])){
+					$table->orderBy($_GET["order"],$_GET["dir"]);
+				}else{
+					$table->orderBy('updated_at','desc');
+				}
+				$count = $table->count();
+				if(isset($_GET["limit"])){
+					$offset = 0;
+					if(isset($_GET["offset"])){
+						$offset = $_GET["offset"];
+					}
+					$table->skip($offset)->take($_GET["limit"]);
+				}			
+				$result = $table->get();
+				break;
+			case 'word':
+				$result = UserDict::select($indexCol)
+									->where('word', $_GET["word"])
+									->orderBy('created_at','desc')
+									->get();				
+				break;
+			default:
+				# code...
+				break;
+		}
+		if($result){
+			$this->ok(["rows"=>$result,"count"=>$count]);
+		}else{
+			$this->error("没有查询到数据");
+		}
+
+	}	
+	public function create(){
+		if(!isset($_COOKIE["user_id"])){
+			$this->error("not login");
+		}
+        $snowflake = new SnowFlakeId();
+
+		$_data = json_decode($_POST["data"],true);
+		switch($_POST["view"]){
+			case "wbw":
+				#查询用户重复的数据
+				$iOk = 0;
+				$updateOk=0;
+				foreach ($_data as $key => $word) {
+					# code...
+					$isDoesntExist = UserDict::where('creator_id', $_COOKIE["user_id"])
+										->where('word',$word["word"])
+										->where('type',$word["type"])
+										->where('grammar',$word["grammar"])
+										->where('parent',$word["parent"])
+										->where('mean',$word["mean"])
+										->where('factors',$word["factors"])
+										->where('factormean',$word["factormean"])
+										->where('source','_USER_WBW_')
+										->doesntExist();
+					
+					if($isDoesntExist){
+						#不存在插入数据
+						$word["id"]=$snowflake->id();
+						$word["source"]='_USER_WBW_';
+						$word["create_time"]=mTime();
+						$word["creator_id"]=$_COOKIE["user_id"];
+						$id = UserDict::insert($word);
+						$updateOk = $this->update_sys_wbw($word);
+						$this->update_redis($word);
+						$iOk++;
+					}
+				}
+				$this->ok([$iOk,$updateOk]);
+				break;
+			case "dict":
+				break;
+		}
+	}	
+		
+	public function show(){
+
+		$result = UserDict::find($_GET["id"]);
+		if($result){
+			$this->ok($result);
+		}else{
+			$this->error("没有查询到数据");
+		}
+	}
+	public function update(){
+        $snowflake = new SnowFlakeId();
+		$data = json_decode($_POST["data"],true);
+
+		$result = UserDict::where('id', $data["id"])
+						  ->update($data);
+		if($result){
+			$updateOk = $this->update_sys_wbw($data);
+			$this->update_redis($data);
+			$this->ok([$result,$updateOk]);
+		}else{
+			$this->error("没有查询到数据");
+		}
+	}	
+	public function delete(){
+		$arrId = json_decode($_GET["id"],true) ;
+		$count = 0;
+		foreach ($arrId as $key => $id) {
+			# code...
+			$data = UserDict::find($id);
+			$result = UserDict::where('id', $id)
+							->where('creator_id', $_COOKIE["user_id"])
+							->delete();
+			if($result){
+				$count++;
+				$updateOk = $this->update_sys_wbw($data);	
+				$this->update_redis($data);
+			}
+		}
+		$this->ok([$count,$updateOk]);
+	}
+
+	/*
+	更新系统wbw汇总表
+	*/
+	private function update_sys_wbw($data){
+        $snowflake = new SnowFlakeId();
+		#查询用户重复的数据
+		$count = UserDict::where('word',$data["word"])
+		->where('type',$data["type"])
+		->where('grammar',$data["grammar"])
+		->where('parent',$data["parent"])
+		->where('mean',$data["mean"])
+		->where('factors',$data["factors"])
+		->where('factormean',$data["factormean"])
+		->where('source','_USER_WBW_')
+		->count();
+
+		if($count==0){
+            # 没有任何用户有这个数据
+			#删除数据
+			$result = UserDict::where('word',$data["word"])
+			->where('type',$data["type"])
+			->where('grammar',$data["grammar"])
+			->where('parent',$data["parent"])
+			->where('mean',$data["mean"])
+			->where('factors',$data["factors"])
+			->where('factormean',$data["factormean"])
+			->where('source','_SYS_USER_WBW_')
+			->delete();
+			return($result);
+
+		}else{
+            #更新或新增
+			#查询最早上传这个数据的用户
+			$creator_id = UserDict::where('word',$data["word"])
+							->where('type',$data["type"])
+							->where('grammar',$data["grammar"])
+							->where('parent',$data["parent"])
+							->where('mean',$data["mean"])
+							->where('factors',$data["factors"])
+							->where('factormean',$data["factormean"])
+							->where('source','_USER_WBW_')
+							->orderby("created_at",'asc')
+							->value("creator_id");
+
+            $count = UserDict::where('word',$data["word"])
+                        ->where('type',$data["type"])
+                        ->where('grammar',$data["grammar"])
+                        ->where('parent',$data["parent"])
+                        ->where('mean',$data["mean"])
+                        ->where('factors',$data["factors"])
+                        ->where('factormean',$data["factormean"])
+                        ->where('source','_SYS_USER_WBW_')
+                        ->count();
+            if($count==0){
+                #系统字典没有 新增
+                $result = UserDict::insert(
+				[
+                    'id' =>$snowflake->id(),
+					'word'=>$data["word"],
+					'type'=>$data["type"],
+					'grammar'=>$data["grammar"],
+					'parent'=>$data["parent"],
+					'mean'=>$data["mean"],
+					'factors'=>$data["factors"],
+					'factormean'=>$data["factormean"],
+					'source'=>"_SYS_USER_WBW_",
+                    'creator_id' => $creator_id,
+					'ref_counter' => 1,
+                    "create_time"=>mTime()
+                    ]);
+            }else{
+                #有,更新
+                $result = UserDict::where('word',$data["word"])
+                        ->where('type',$data["type"])
+                        ->where('grammar',$data["grammar"])
+                        ->where('parent',$data["parent"])
+                        ->where('mean',$data["mean"])
+                        ->where('factors',$data["factors"])
+                        ->where('factormean',$data["factormean"])
+                        ->where('source','_SYS_USER_WBW_')
+                        ->update(
+                    [
+                        'creator_id'=>$creator_id,
+                        'ref_counter'=>$count
+                    ]);
+            }
+			return($result);
+		}
+	}
+
+	private function update_redis($word){
+		#更新 redis
+
+		if ($this->redis != false) {
+			{
+				$Fetch = UserDict::where(['word'=>$word['word'],"source"=>"_SYS_USER_WBW_"])->get();
+				$redisWord=array();
+				foreach ($Fetch as  $one) {
+					# code...
+					$redisWord[] = array(
+									$one["id"],
+									$one["word"],
+									$one["type"],
+									$one["grammar"],
+									$one["parent"],
+									$one["mean"],
+									$one["note"],
+									$one["factors"],
+									$one["factormean"],
+									$one["status"],
+									$one["confidence"],
+									$one["creator_id"],
+									$one["source"],
+									$one["language"]
+									);
+				}
+				$this->redis->hSet("dict://user",$word['word'],json_encode($redisWord,JSON_UNESCAPED_UNICODE));			
+			}
+		}
+		#更新redis结束
+	}
+} 

+ 80 - 0
public/app/api/controller/user_operation_logs.php

@@ -0,0 +1,80 @@
+<?php
+require_once __DIR__."/../model/user_operation_logs.php";
+require_once __DIR__."/../model/user_operation_frames.php";
+require_once __DIR__."/../model/user_operation_dailys.php";
+require_once __DIR__."/controller.php";
+
+
+Class CtlUserOperationLog extends Controller{
+	public function index(){
+		$result=false;
+		switch ($_GET["view"]) {
+			case 'day':
+				# code...
+				$result = UserOperationDaily::where('user_id', $_COOKIE["user_id"])
+											->get();		
+				$count = UserOperationDaily::where('user_id', $_COOKIE["user_id"])
+											->count();
+				break;
+			case 'frame':
+				$result = UserOperationFrame::where('user_id', $_COOKIE["user_id"])
+									->get();		
+				$count = UserOperationFrame::where('user_id', $_COOKIE["user_id"])
+				->count();
+				break;
+			case 'log':
+				$result = UserOperationLog::where('user_id', $_COOKIE["user_id"])
+											->whereBeteen()
+											->get();
+				$count = UserOperationLog::where('user_id', $_COOKIE["user_id"])
+											->count();
+				break;
+			default:
+				# code...
+				break;
+		}
+		if($result){
+			$this->ok(["rows"=>$result,"count"=>$count]);
+		}else{
+			$this->error("没有查询到数据");
+		}
+
+	}	
+	public function create($op_type = "", $content = null){
+		if(!isset($_COOKIE["user_id"])){
+			$this->error("not login");
+			return false;
+		}
+
+		if(isset($_POST["data"])){
+			$_data = json_decode($_POST["data"],true);
+		}else{
+			$_data = ['op_type'=>$op_type,"content"=>$content];
+		}
+		#获取客户端时区偏移 beijing = +8
+		if(!isset($_data['timezone'])){
+			if (isset($_COOKIE["timezone"])) {
+				$_data['timezone'] = (0 - (int) $_COOKIE["timezone"]) * 60 * 1000;
+			} else{
+				$_data['timezone'] = 0;
+			}	
+		}
+		$_data["user_id"] = $_COOKIE["user_id"];
+		UserOperationLog::insert($_data);
+
+
+		
+	}	
+		
+	public function show(){
+		$result = UserOperationLog::find($_GET["id"]);
+		if($result){
+			$this->ok($result);
+		}else{
+			$this->error("没有查询到数据");
+		}
+	}
+	/*
+	更新系统wbw汇总表
+	*/
+}

+ 9 - 0
public/app/api/model/sent_prs.php

@@ -0,0 +1,9 @@
+<?php
+require __DIR__."/../bootstrap.php";
+
+
+use Illuminate\Database\Eloquent\Model as Model;
+class SentPr extends Model
+{
+
+}

+ 9 - 0
public/app/api/model/user_dicts.php

@@ -0,0 +1,9 @@
+<?php
+require __DIR__."/../bootstrap.php";
+
+
+use Illuminate\Database\Eloquent\Model as Model;
+class UserDict extends Model
+{
+
+}

+ 9 - 0
public/app/api/model/user_operation_dailys.php

@@ -0,0 +1,9 @@
+<?php
+require __DIR__."/../bootstrap.php";
+
+
+use Illuminate\Database\Eloquent\Model as Model;
+class UserOperationDaily extends Model
+{
+
+}

+ 9 - 0
public/app/api/model/user_operation_frames.php

@@ -0,0 +1,9 @@
+<?php
+require __DIR__."/../bootstrap.php";
+
+
+use Illuminate\Database\Eloquent\Model as Model;
+class UserOperationFrame extends Model
+{
+
+}

+ 9 - 0
public/app/api/model/user_operation_logs.php

@@ -0,0 +1,9 @@
+<?php
+require __DIR__."/../bootstrap.php";
+
+
+use Illuminate\Database\Eloquent\Model as Model;
+class UserOperationLog extends Model
+{
+
+}

+ 34 - 0
public/app/api/sent_prs.php

@@ -0,0 +1,34 @@
+<?php
+require_once __DIR__."/controller/sent_prs.php";
+
+
+$SentPr = new CtlSentPr;
+
+switch ($_REQUEST["op"]) {
+	case 'index':
+		# get
+		$SentPr->index();
+		break;
+	case 'create':
+		# post
+		$SentPr->create();
+		break;
+	case 'show':
+		# get
+		$SentPr->show();
+		break;	
+	case 'update':
+		# post
+		$SentPr->update();
+		break;	
+	case 'delete':
+		# get
+		$SentPr->delete();
+		break;	
+	default:
+		# code...
+		break;
+}
+
+
+

+ 34 - 0
public/app/api/user_dicts.php

@@ -0,0 +1,34 @@
+<?php
+require_once __DIR__."/controller/user_dicts.php";
+
+
+$UserDict = new CtlUserDict;
+
+switch ($_REQUEST["op"]) {
+	case 'index':
+		# get
+		$UserDict->index();
+		break;
+	case 'create':
+		# post
+		$UserDict->create();
+		break;
+	case 'show':
+		# get
+		$UserDict->show();
+		break;	
+	case 'update':
+		# post
+		$UserDict->update();
+		break;	
+	case 'delete':
+		# get
+		$UserDict->delete();
+		break;	
+	default:
+		# code...
+		break;
+}
+
+
+

+ 26 - 9
public/app/article/add_article_to_collect.php

@@ -1,10 +1,14 @@
 <?php
 //添加文章到文集
-
+# TODO 需要判断文集的修改权限
+# TODO children >0 不能删除
+# TODO 因为要保证顺序不变,已经存在的不能删除
 require_once "../config.php";
 require_once "../public/_pdo.php";
 require_once '../public/function.php';
 require_once '../ucenter/function.php';
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
 
 $output  = array();
 $respond = array();
@@ -16,24 +20,37 @@ if(isset($_POST["id"])){
     $dirty_collect = array();
     $data = json_decode($_POST["data"]);
     $title = $_POST["title"];
-    PDO_Connect(_FILE_DB_USER_ARTICLE_);
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
     $article_id=$_POST["id"];
     //找出脏的collect
-    $query = "SELECT collect_id FROM article_list  WHERE article_id = ? ";
+    $query = "SELECT collect_id FROM "._TABLE_ARTICLE_COLLECTION_."  WHERE article_id = ? ";
     $collect = PDO_FetchAll($query,array($article_id));
     foreach ($collect as $key => $value) {
         # code...
         $dirty_collect[$value["collect_id"]] = 1;
     }
-    $query = "DELETE FROM article_list WHERE article_id = ? ";
+    $query = "DELETE FROM "._TABLE_ARTICLE_COLLECTION_." WHERE article_id = ? ";
      PDO_Execute($query,array($article_id));
      if(count($data)>0){
         /* 开始一个事务,关闭自动提交 */
         $PDO->beginTransaction();
-        $query = "INSERT INTO article_list (collect_id, article_id,level,title) VALUES (?, ?, ? , ?)";
+        $query = "INSERT INTO "._TABLE_ARTICLE_COLLECTION_." 
+                    (
+                        id,
+                        collect_id, 
+                        article_id,
+                        level,
+                        title
+                    ) VALUES (? , ?, ?, ? , ?)";
         $sth = $PDO->prepare($query);
         foreach ($data as $row) {
-            $sth->execute(array($row,$article_id,1,$title));
+            $sth->execute(array(
+                        $snowflake->id() , 
+                        $row,
+                        $article_id,
+                        1,
+                        $title
+                        ));
         }
         $PDO->commit();
         if (!$sth || ($sth && $sth->errorCode() != 0)) {
@@ -46,7 +63,7 @@ if(isset($_POST["id"])){
      }
 
      # 更新collect
-     $query = "SELECT collect_id FROM article_list WHERE article_id  = ?";
+     $query = "SELECT collect_id FROM "._TABLE_ARTICLE_COLLECTION_." WHERE article_id  = ?";
      $collect = PDO_FetchAll($query,array($article_id));
      foreach ($collect as $key => $value) {
         # code...
@@ -54,9 +71,9 @@ if(isset($_POST["id"])){
     }
      foreach ($dirty_collect as $key => $value) {
          # code...
-         $query = "SELECT level,article_id as article , title FROM article_list WHERE collect_id  = ?";
+         $query = "SELECT level,article_id as article , title FROM "._TABLE_ARTICLE_COLLECTION_." WHERE collect_id  = ? order by id ASC";
          $collect_info = PDO_FetchAll($query,array($key));
-         $query = "UPDATE collect SET article_list = ? WHERE id = ? ";
+         $query = "UPDATE "._TABLE_COLLECTION_." SET article_list = ? WHERE uid = ? ";
          $strArticleList = json_encode($collect_info, JSON_UNESCAPED_UNICODE);
          $stmt = PDO_Execute($query,array( $strArticleList ,$key));
          if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {

+ 6 - 6
public/app/article/collect_get.php

@@ -18,16 +18,16 @@ if(isset($_GET["id"])){
 		echo json_encode(array(), JSON_UNESCAPED_UNICODE);
         exit;
 	}
-    PDO_Connect(_FILE_DB_USER_ARTICLE_);
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
     $id=$_GET["id"];
-    $query = "select * from collect  where id = ? ";
+    $query = "SELECT uid as id,title, subtitle,summary,article_list,owner,setting,status,lang,create_time,modify_time from "._TABLE_COLLECTION_."  where uid = ? ";
     $Fetch = PDO_FetchRow($query,array($id));
     if($Fetch){
         $userinfo = new UserInfo();
         $user = $userinfo->getName($Fetch["owner"]);
         $Fetch["username"] = $user;
         #查询文集中文档列表
-        $query = "select level,article_id as article,title from article_list  where collect_id = ? ";
+        $query = "SELECT level,article_id as article,title from "._TABLE_ARTICLE_COLLECTION_."  where collect_id = ? order by id ASC";
         $fArticle_list = PDO_FetchAll($query,array($id));    
         $Fetch["article_list"] = json_encode($fArticle_list, JSON_UNESCAPED_UNICODE);
         echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
@@ -36,9 +36,9 @@ if(isset($_GET["id"])){
 }
 else if(isset($_GET["article"])){
     # 给文章编号,查文集信息
-    PDO_Connect(""._FILE_DB_USER_ARTICLE_);
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
     $article=$_GET["article"];
-    $query = "SELECT collect_id FROM article_list  WHERE article_id = ? ";
+    $query = "SELECT collect_id FROM "._TABLE_ARTICLE_COLLECTION_."  WHERE article_id = ? ";
     $Fetch = PDO_FetchAll($query,array($article));
     
     /*  使用一个数组的值执行一条含有 IN 子句的预处理语句 */
@@ -50,7 +50,7 @@ else if(isset($_GET["article"])){
     /*  创建一个填充了和params相同数量占位符的字符串 */
     $place_holders = implode(',', array_fill(0, count($params), '?'));
 
-    $query = "SELECT * FROM collect WHERE id IN ($place_holders)";
+    $query = "SELECT * FROM "._TABLE_COLLECTION_." WHERE uid IN ($place_holders)";
 
     $Fetch = PDO_FetchAll($query,$params);
         echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);

+ 5 - 4
public/app/article/collect_list.php

@@ -8,14 +8,15 @@ require_once '../ucenter/function.php';
 
 
 if(isset($_GET["userid"])){
-    PDO_Connect(""._FILE_DB_USER_ARTICLE_);
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
     $userid=$_GET["userid"];
-    $query = "SELECT * from collect  where owner = ? and status <> 0 order by modify_time DESC";
+    $query = "SELECT uid as id,title,subtitle,summary,article_list,owner,status,lang,create_time,modify_time from "._TABLE_COLLECTION_."  where owner = ? and status <> 0 order by modify_time DESC";
     $Fetch = PDO_FetchAll($query,array($userid));
     echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
-    exit;
+}else{
+	echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
 }
 
-echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
+
 
 ?>

+ 28 - 20
public/app/article/function.php

@@ -6,7 +6,7 @@ require_once "../db/table.php";
 class Article extends Table
 {
     function __construct($redis=false) {
-		parent::__construct(_FILE_DB_USER_ARTICLE_, "article", "", "",$redis);
+		parent::__construct(_FILE_DB_USER_ARTICLE_, _TABLE_ARTICLE_, _DB_USERNAME_,_DB_PASSWORD_,$redis);
     }
 
     public function getInfo($id){
@@ -19,14 +19,14 @@ class Article extends Table
 				$output["owner"]=$this->redis->hGet("article://".$id,"owner");
 				$output["summary"]=$this->redis->hGet("article://".$id,"summary");
 				$output["lang"]=$this->redis->hGet("article://".$id,"lang");
-				$output["tag"]=$this->redis->hGet("article://".$id,"tag");
+				$output["tag"]="";
 				$output["status"]=$this->redis->hGet("article://".$id,"status");
 				$output["create_time"]=$this->redis->hGet("article://".$id,"create_time");
 				$output["modify_time"]=$this->redis->hGet("article://".$id,"modify_time");
 				return $output;
 			}
 		}
-        $query = "SELECT id,title,owner,subtitle,summary,lang,tag,status,create_time,modify_time FROM article WHERE id= ? ";
+        $query = "SELECT uid as id,title,owner,subtitle,summary,lang,status,create_time,modify_time FROM "._TABLE_ARTICLE_." WHERE uid= ? ";
         $stmt = $this->dbh->prepare($query);
         $stmt->execute(array($id));
         $output = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -40,7 +40,6 @@ class Article extends Table
 				$this->redis->hSet("article://".$id,"summary",$output["summary"]);
 				$this->redis->hSet("article://".$id,"lang",$output["lang"]);
 				$this->redis->hSet("article://".$id,"owner",$output["owner"]);
-				$this->redis->hSet("article://".$id,"tag",$output["tag"]);
 				$this->redis->hSet("article://".$id,"status",$output["status"]);
 				$this->redis->hSet("article://".$id,"create_time",$output["create_time"]);
 				$this->redis->hSet("article://".$id,"modify_time",$output["modify_time"]);
@@ -60,7 +59,7 @@ class Article extends Table
 				return $content;
 			}
 		}
-        $query = "SELECT content FROM article WHERE id= ? ";
+        $query = "SELECT content FROM ".$this->table." WHERE uid= ? ";
         $stmt = $this->dbh->prepare($query);
         $stmt->execute(array($id));
         $output = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -77,39 +76,41 @@ class Article extends Table
 
 	public function getPower($id,$collectionId=""){
 		#查询用户对此是否有权限	
-		if(isset($_COOKIE["userid"])){
-			$userId = $_COOKIE["userid"];
+		if(isset($_COOKIE["user_uid"])){
+			$userId = $_COOKIE["user_uid"];
 		}
 		else{
 			$userId=0;
 		}
+
 		if($this->redis!==false){
 			$power = $this->redis->hGet("power://article/".$id,$userId);
 			if($power!==FALSE){
 				return $power;
 			}
 		}
+
 		$iPower = 0;
-		$query = "SELECT owner,status FROM article WHERE id=?  ";
+		$query = "SELECT owner,status FROM "._TABLE_ARTICLE_." WHERE uid=?  ";
 		$stmt = $this->dbh->prepare($query);
 		$stmt->execute(array($id));
 		$channel = $stmt->fetch(PDO::FETCH_ASSOC);
 		if($channel){
-			if(!isset($_COOKIE["userid"])){
+			if(!isset($_COOKIE["user_uid"])){
 				#未登录用户
 				if($channel["status"]==30){
 					#全网公开有读取和建议权限
-					return 10;
+					$iPower =  10;
 				}
 				else{
 					#其他状态没有任何权限
-					return 0;
+					$iPower =  0;
 				}
 			}
 			else{
-				if($channel["owner"]==$_COOKIE["userid"]){
+				if($channel["owner"]==$_COOKIE["user_uid"]){
 					#自己的
-					return 30;
+					$iPower =  30;
 				}
 				else if($channel["status"]>=30){
 					#全网公开的 可以提交pr
@@ -118,9 +119,9 @@ class Article extends Table
 			}
 		}
 		#查询共享权限,如果共享权限更大,覆盖上面的的
-		$sharePower = share_get_res_power($_COOKIE["userid"],$id);
+		$sharePower = share_get_res_power($_COOKIE["user_uid"],$id);
 		if($collectionId!=""){
-			$sharePowerCollection = share_get_res_power($_COOKIE["userid"],$collectionId);
+			$sharePowerCollection = share_get_res_power($_COOKIE["user_uid"],$collectionId);
 		}
 		else{
 			$sharePowerCollection =0;
@@ -132,7 +133,7 @@ class Article extends Table
 			$iPower=$sharePowerCollection;
 		}
 		if($this->redis!==false){
-			$this->redis->hSet("power://article/".$id,$_COOKIE["userid"],$iPower);
+			$this->redis->hSet("power://article/".$id,$_COOKIE["user_uid"],$iPower);
 		}
 		return $iPower;
 	}
@@ -143,12 +144,12 @@ class Article extends Table
 class ArticleList extends Table
 {
     function __construct($redis=false) {
-		parent::__construct(_FILE_DB_USER_ARTICLE_, "article_list", "", "",$redis);
+		parent::__construct(_FILE_DB_USER_ARTICLE_, _TABLE_ARTICLE_COLLECTION_, _DB_USERNAME_,_DB_PASSWORD_,$redis);
     }
 
 	function upgrade($collectionId,$articleList=array()){
 		# 更新 article_list 表
-		$query = "DELETE FROM article_list WHERE collect_id = ? ";
+		$query = "DELETE FROM ".$this->table." WHERE collect_id = ? ";
 		$stmt = $this->dbh->prepare($query);
 		if($stmt){
 			$stmt->execute(array($collectionId));
@@ -157,10 +158,17 @@ class ArticleList extends Table
 		if(count($articleList)>0){
 			/* 开始一个事务,关闭自动提交 */
 			$this->dbh->beginTransaction();
-			$query = "INSERT INTO article_list (collect_id, article_id,level,title) VALUES ( ?, ?, ? , ? )";
+			$query = "INSERT INTO ".$this->table." (id, collect_id, article_id,level,title) VALUES (?, ?, ?, ? , ? )";
 			$sth = $this->dbh->prepare($query);
 			foreach ($articleList as $row) {
-				$sth->execute(array($collectionId,$row["article"],$row["level"],$row["title"]));
+				$sth->execute(
+                    array(
+                        $this->SnowFlake->id(),
+                        $collectionId,
+                        $row["article"],
+                        $row["level"],
+                        $row["title"]
+                        ));
 				if($this->redis){
 					#删除article权限缓存
 					$this->redis->del("power://article/".$row["article"]);

+ 2 - 10
public/app/article/list.php

@@ -5,24 +5,16 @@ require_once "../config.php";
 require_once "../public/_pdo.php";
 require_once '../public/function.php';
 require_once '../ucenter/function.php';
-PDO_Connect(""._FILE_DB_USER_ARTICLE_);
+PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
 if(isset($_GET["userid"])){
     $userid=$_GET["userid"];
-    $query = "SELECT * from article  where owner = ? and status <> 0 order by modify_time DESC";
+    $query = "SELECT uid as id , title,subtitle ,summary,content,owner,setting,status,lang,create_time,modify_time from "._TABLE_ARTICLE_."  where owner = ? and status <> 0 order by modify_time DESC";
     $Fetch = PDO_FetchAll($query,array($userid));
     if($Fetch){
-        /*
-        $userinfo = new UserInfo();
-        $user = $userinfo->getName($Fetch["owner"]);
-        $Fetch["username"] = $user;
-        */
         echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
         exit;
     }
 }
-else{
-
-}
 
 echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
 

+ 8 - 6
public/app/article/list_article_in_collect.php

@@ -1,5 +1,5 @@
 <?php
-//查询term字典
+//查询某article 在哪几个collection里面出现
 
 require_once "../config.php";
 require_once "../public/_pdo.php";
@@ -8,21 +8,23 @@ require_once '../ucenter/function.php';
 
 $output  = array();
 if(isset($_GET["id"])){
-    PDO_Connect(""._FILE_DB_USER_ARTICLE_);
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
     $article_id=$_GET["id"];
-    $query = "SELECT collect_id as id from article_list  where article_id = ?  ";
+    $query = "SELECT collect_id as id from "._TABLE_ARTICLE_COLLECTION_."  where article_id = ?  ";
     $exist = PDO_FetchAll($query,array($article_id));
     $exist_id = array();
+	#查询已经存在的collection详细信息
     for ($i=0; $i < count($exist) ; $i++) { 
         # query collect title
-        $query = "SELECT title from collect  where id = ?  ";
+        $query = "SELECT title from "._TABLE_COLLECTION_."  where uid = ?  ";
         $exist[$i]["title"] = PDO_FetchOne($query,array($exist[$i]["id"]));        
         $exist_id[$exist[$i]["id"]] = 1;
     }
     $output["exist"] = $exist;
 
-    $query = "SELECT id,title from collect  where owner = ? AND status <> 0 order by modify_time DESC limit 0,50";
-    $others = PDO_FetchAll($query,array($_COOKIE["userid"])); 
+	#查询所有的
+    $query = "SELECT uid as id,title from "._TABLE_COLLECTION_."  where owner = ? AND status <> 0 order by modify_time DESC limit 50";
+    $others = PDO_FetchAll($query,array($_COOKIE["user_uid"])); 
     foreach ($others as $key => $value) {
         # remove exist record
         if(!isset($exist_id[$value["id"]])){

+ 4 - 4
public/app/article/list_new.php

@@ -24,8 +24,8 @@ require_once '../collect/function.php';
     else{
         $begin = 0;
     }
-    PDO_Connect(_FILE_DB_USER_ARTICLE_);
-    $query = "SELECT id,title,subtitle,summary,owner,modify_time from article  where status >= 30 ";
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid as id,title,subtitle,summary,owner,modify_time from "._TABLE_ARTICLE_."  where status >= 30 ";
     
     if(isset($_GET["orderby"])){
         switch ($_GET["orderby"]) {
@@ -42,7 +42,7 @@ require_once '../collect/function.php';
     else{
         $query .="ORDER BY modify_time DESC";
     }
-    $query .=" LIMIT $begin , $onepage ";
+    $query .=" LIMIT $onepage OFFSET $begin  ";
     $Fetch = PDO_FetchAll($query);
     $collect_info = new CollectInfo();
     foreach ($Fetch as $key => $value) {
@@ -50,7 +50,7 @@ require_once '../collect/function.php';
         $userinfo = new UserInfo();
         $user = $userinfo->getName($value["owner"]);
         $Fetch[$key]["username"] = $user;
-        $query = "SELECT collect_id from article_list  where article_id = ? ";
+        $query = "SELECT collect_id from "._TABLE_ARTICLE_COLLECTION_."  where article_id = ? ";
         $collect = PDO_FetchRow($query,array($Fetch[$key]["id"]));
         if($collect){
             $Fetch[$key]["collect"] = $collect_info->get($collect["collect_id"]);

+ 4 - 3
public/app/article/my_article_post.php

@@ -8,6 +8,7 @@ require_once "../article/function.php";
 require_once "../redis/function.php";
 require_once "../db/custom_book.php";
 
+
 add_edit_event(_ARTICLE_EDIT_,$_POST["id"]);
 
 $respond=array("status"=>0,"message"=>"");
@@ -54,11 +55,11 @@ if(isset($_POST["import"]) && $_POST["import"]=='on'){
 }
 
 
-PDO_Connect(_FILE_DB_USER_ARTICLE_);
+PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
 
-$query="UPDATE article SET title = ? , subtitle = ? , summary = ?, lang = ? , content = ?  , tag = ? , setting = ? , status = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$query="UPDATE "._TABLE_ARTICLE_." SET title = ? , subtitle = ? , summary = ?, lang = ? , content = ?   , setting = ? , status = ? , updated_at=now()  , modify_time= ?   where  uid = ?  ";
 $sth = $PDO->prepare($query);
-$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"] ,$_POST["lang"], $_content , $_POST["tag"] , "{}" , $_POST["status"] ,   mTime() , mTime() , $_POST["id"]));
+$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"] ,$_POST["lang"], $_content  , "{}" , $_POST["status"] ,   mTime() , $_POST["id"]));
 $respond=array("status"=>0,"message"=>"");
 if (!$sth || ($sth && $sth->errorCode() != 0)) {
 	$error = PDO_ErrorInfo();

+ 34 - 3
public/app/article/my_article_put.php

@@ -7,6 +7,8 @@ require_once "../public/_pdo.php";
 require_once '../public/function.php';
 require_once '../hostsetting/function.php';
 require_once "../ucenter/active.php";
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
 
 $respond=array("ok"=>true,"message"=>"");
 if(!isset($_COOKIE["userid"])){
@@ -29,15 +31,44 @@ if(isset($_POST["content"])){
 else{
 	$content = "";
 }
-PDO_Connect(_FILE_DB_USER_ARTICLE_);
+PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
 
-$query="INSERT INTO article ( id,  title  , subtitle  , summary , content   , tag  , owner, setting  , status  , create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ";
+$query="INSERT INTO "._TABLE_ARTICLE_." 
+        ( 
+            id,
+			uid,  
+			title  , 
+			subtitle  , 
+			summary , 
+			content  , 
+			owner, 
+			owner_id, 
+			editor_id, 
+			setting  , 
+			status  , 
+			create_time , 
+			modify_time    
+			)  VALUES  ( ? , ? ,  ? , ? , ? , ? , ? , ? , ? ,? ,?, ? , ? ) ";
 $sth = $PDO->prepare($query);
 $uuid = UUID::v4();
 //写入日志
 add_edit_event(_ARTICLE_NEW_,$uuid);
 #新建文章默认私有
-$sth->execute(array($uuid , $_POST["title"] , "" ,"", $content , "" , $_COOKIE["userid"] , "{}" , 10 , mTime() ,  mTime() , mTime() ));
+$sth->execute(array(
+                $snowflake->id() , 
+                $uuid , 
+                $_POST["title"] , 
+                "" ,
+                "", 
+                $content  , 
+                $_COOKIE["user_uid"] , 
+                $_COOKIE["user_id"] , 
+                $_COOKIE["user_id"] , 
+                "{}" , 
+                10 , 
+                mTime() ,  
+                mTime()  
+                ));
 
 if (!$sth || ($sth && $sth->errorCode() != 0)) {
 	$error = PDO_ErrorInfo();

+ 22 - 7
public/app/article/my_collect_post.php

@@ -5,7 +5,8 @@ require_once '../public/function.php';
 require_once '../collect/function.php';
 require_once "../ucenter/active.php";
 require_once "../redis/function.php";
-
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
 
 $respond=array("status"=>0,"message"=>"");
 if(!isset($_COOKIE["userid"])){
@@ -29,11 +30,11 @@ if($power<20){
 
 add_edit_event(_COLLECTION_EDIT_,$_POST["id"]);
 
-PDO_Connect(_FILE_DB_USER_ARTICLE_);
+PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
 
-$query="UPDATE collect SET title = ? , subtitle = ? , summary = ?, article_list = ?  ,  status = ? , lang = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$query="UPDATE "._TABLE_COLLECTION_." SET title = ? , subtitle = ? , summary = ?, article_list = ?  ,  status = ? , lang = ? , updated_at= now()  , modify_time= ?   where  uid = ?  ";
 $sth = $PDO->prepare($query);
-$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"], $_POST["article_list"] , $_POST["status"] , $_POST["lang"] ,  mTime() , mTime() , $_POST["id"]));
+$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"], $_POST["article_list"] , $_POST["status"] , $_POST["lang"] ,  mTime() ,  $_POST["id"]));
 $respond=array("status"=>0,"message"=>"");
 if (!$sth || ($sth && $sth->errorCode() != 0)) {
 	$error = PDO_ErrorInfo();
@@ -46,16 +47,30 @@ else{
 		$redis->del("power://collection/".$_POST["id"]);
 	}
     # 更新 article_list 表
-    $query = "DELETE FROM article_list WHERE collect_id = ? ";
+    $query = "DELETE FROM "._TABLE_ARTICLE_COLLECTION_." WHERE collect_id = ? ";
     PDO_Execute($query,array($_POST["id"]));
     $arrList = json_decode($_POST["article_list"]);
     if(count($arrList)>0){
         /* 开始一个事务,关闭自动提交 */
         $PDO->beginTransaction();
-        $query = "INSERT INTO article_list (collect_id, article_id,level,title,children) VALUES ( ? , ?, ?, ? , ? )";
+        $query = "INSERT INTO "._TABLE_ARTICLE_COLLECTION_." (
+                            id,
+                            collect_id, 
+                            article_id,
+                            level,
+                            title,
+                            children
+                            ) VALUES (?, ? , ?, ?, ? , ? )";
         $sth = $PDO->prepare($query);
         foreach ($arrList as $row) {
-            $sth->execute(array($_POST["id"],$row->article,$row->level,$row->title,$row->children));
+            $sth->execute(array(
+                            $snowflake->id(),
+                            $_POST["id"],
+                            $row->article,
+                            $row->level,
+                            $row->title,
+                            $row->children
+                            ));
 			if($redis){
 				#删除article权限缓存
 				$redis->del("power://article/".$row->article);

+ 34 - 4
public/app/article/my_collect_put.php

@@ -4,6 +4,8 @@ require_once "../public/_pdo.php";
 require_once '../public/function.php';
 require_once '../hostsetting/function.php';
 require_once "../ucenter/active.php";
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
 
 $respond=array("status"=>0,"message"=>"");
 if(!isset($_COOKIE["userid"])){
@@ -24,11 +26,39 @@ if(!isset($_POST["title"])){
 $uuid = UUID::v4();
 add_edit_event(_COLLECTION_NEW_,$uuid);
 
-PDO_Connect(""._FILE_DB_USER_ARTICLE_);
-$query="INSERT INTO collect ( id,  title  , subtitle  , summary , article_list   , owner, lang  , status  , create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ?  , ? , ? , ? , ? , ? , ? , ? ) ";
-$sth = $PDO->prepare($query);
 
-$sth->execute(array($uuid , $_POST["title"] , "" ,"", "[]" ,  $_COOKIE["userid"] , "" , $_POST["status"] , mTime() ,  mTime() , mTime() ));
+PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
+$query="INSERT INTO "._TABLE_COLLECTION_." ( 
+        id,
+		uid ,  
+		title  , 
+		subtitle  , 
+		summary , 
+		article_list   , 
+		owner, 
+		owner_id, 
+		editor_id, 
+		lang  , 
+		status  , 
+		create_time , 
+		modify_time    
+		)  VALUES  ( ? , ? , ? , ?  , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ";
+$sth = $PDO->prepare($query);
+$sth->execute(array(
+                $snowflake->id() , 
+                $uuid , 
+                $_POST["title"] , 
+                "" ,
+                "",
+                 "[]" ,  
+                 $_COOKIE["user_uid"] ,  
+                 $_COOKIE["user_id"],  
+                 $_COOKIE["user_id"], 
+                 "" , 
+                 $_POST["status"] , 
+                 mTime() ,  
+                 mTime() 
+                 ));
 $respond=array("status"=>0,"message"=>"");
 if (!$sth || ($sth && $sth->errorCode() != 0)) {
 	$error = PDO_ErrorInfo();

+ 198 - 0
public/app/auth/README.md

@@ -0,0 +1,198 @@
+# 权限管理
+
+## 业务需求
+
+实现网站资源的权限管理。设置和查询某用户对某资源的拥有的权限。权限包括但不限于 转让,创建,修改,删除,读取等。
+
+## 业务实现
+
+分为三个部分
+1. 角色管理-所有用户都至少有一个角色
+2. 资源-所有资源都在一个资源树上资源树的根节点称为studio 也就是github的orginaze。
+3. 权限设置-某角色对某资源有某种权限
+4. 权限查询-某用户对某资源是否有某种权限
+4. 资源列表-某用户列出某资源的直接子资源(有读取或更高权限)的列表
+
+## 角色
+
+每个studio 必定拥有下面的几种角色。
+角色权限有从高到低的权限继承关系。高级角色必定有低级角色的所有权限。
+角色由高到低分别是
+1. 拥有者(owner)——一个资源的拥有者只限一个
+	- 转让
+1. 管理员(manager)
+	- 分享权限给其他人(share)
+3. 编辑者(editor)
+	- 建立资源(create)
+	- 修改资源(update)
+	- 删除资源(delete)
+4. 成员(member)
+	- 读取(read)
+
+每一个studio 建立的时候默认建立上述角色。
+
+群组权限管理用新建角色的方法。每个群组在建立的时候,在该studio下新建一个角色。
+此角色对任何资源都没有权限。需要手工指定某资源对这个群组的权限。添加成员实际上是将某user加到这个角色。
+
+网站建立的时候默认建立一个"public" studio。
+所有的注册用户都加入 public/member 角色。
+所有访问网站者,包括未登录者,都加入 public/visitor 角色。
+当某资源设置为全网公开,实际上是分享读取权限给public/visitor
+
+## 资源
+资源为树结构
+
+- studio
+	- channel
+		- translation
+		- orginal
+		- nissaya
+		- commentray
+		- term
+		- wbw
+	- collection-templet
+		- article-templet
+			- sentence
+	- user dictionary
+	- group
+	- course
+		- lesson
+
+网站建立时,建立根资源节点
+
+- root
+	- studio
+
+user-01 账号建立时,同时建立studio-01.并在 root/studio 下面建立下面的父资源。
+
+- studio-01
+	- channel
+	- collection-templet
+	- user-dictionary
+	- group
+	- course
+
+user-01 建立 channel-01 挂在 studio-01/channel下面
+
+- root
+	- studio
+		- studio-01
+			- channel
+				- channel-01
+## 授权
+
+1. 注册用户user-01在注册时同时注册一个与用户名相同的studio-01。
+1. 添加角色 public/member/user-01
+1. 添加角色 studio-01/owner
+1. 建立studio-01下所有默认资源根节点
+1. 建立studio-01下所有默认角色
+1. user-01与studio-01绑定。不能转让。
+2. 设置user-01为 studio-01/owner。这样,此用户拥有该studio-01下全部权限。 
+3. user-01 添加新的channel-01 为 在studio-01/channel 添加子资源 channel-01
+4. user-01 将 channel-01 分享 给 user-02 = 授权 studio-01/channel/channel-01 给 studio-02/owner 
+
+## 鉴权
+
+- 只对角色进行鉴权操作
+- 需要获取某角色在某资源节点下所有子资源列表(包括自己拥有的,共享资源等)
+- 需要获取某角色在某资源下是否有某操作的权限
+- 需要获取某用户(实际上是studio/owner角色)在某资源节点下所有子资源列表
+- 需要获取某用户(实际上是studio/owner角色)在某资源下是否有某操作的权限
+
+
+## 接口
+
+每个api 有五个接口
+1. **index** 列出资源列表(如:用户的所有文章)
+1. **create** 创建资源
+1. **show** 获取单个资源详细信息
+1. **update** 修改资源
+1. **delete** 删除资源
+
+针对这五个接口实现鉴权函数。就是说在api::***中将会调用如下函数。
+
+1. api::index
+	- auth::Index($user,$resId,$resType)
+1. api::create
+	- auth::UserCanCreate($user,$resId,$resType)
+	- auth::UserCteate($user,$resId,$resType)
+1. api::show
+	- auth::UserCanRead($user,$resId,$resType)
+1. api::update
+	- auth::UserCanUpdate($user,$resId,$resType)
+	- auth::DeletePolicy($role,$resId,$resType,$act) // 删除授权
+	- auth::CreatePolicy($role,$resId,$resType,$act) // 授权
+1. api::delete
+	- auth::DeleteObject($role,$resId,$resType) // 删除资源
+
+## 场景模拟
+
+### step-0 网站建立
+
+网站建立时,建立根资源节点
+
+- root
+	- studio
+
+### 注册新用户
+
+1. 注册用户user-01在注册时同时注册一个与用户名相同的studio-01。
+	- root
+		- studio
+			studio-01
+1. 添加角色 public/member/user-01
+1. 建立studio-01下所有默认资源根节点
+	- studio-01
+		- channel
+		- collection-templet
+		- user-dictionary
+		- group
+		- course
+1. 建立studio-01下所有默认角色和继承关系
+	- studio-01
+		- owner
+		- manager
+		- editor
+		- member
+1. 将user-01与studio-01/owner 绑定
+1. user-01与studio-01绑定。不能转让。
+
+
+### 用户添加channel
+
+user-01 建立 channel-01 挂在 studio-01/channel下面
+
+- root
+	- studio
+		- studio-01
+			- channel
+				- channel-01
+
+添加channel-01下面的资源根节点
+- channel-01
+	- translation
+	- orginal
+	- nissaya
+	- commentray
+	- term
+	- wbw
+
+>句子译文挂在 channel-01/translation下面。这样能够实现channel-01的信息如标题等和译文的修改分开鉴权。
+比如我是channel-01的拥有者。我把channel-01的翻译权限给user-02。我希望user-02修改译文,而不是channel名称。
+我只需分享channel-01/translation的edit权限给user-02。
+
+### user-01修改channel信息
+鉴权:user-01 是否 有channel写入权限
+auth::UserCanUpdate($user-01,"channel-01","channel")
+
+
+### 在channel下添加译文
+
+鉴权:user-01 是否 有译文写入权限
+
+auth::UserCanUpdate($user-01,"channel-01/translation","channel/translation")
+
+### 分享channel
+user-01将channel-01的翻译权限给user-02
+
+auth::CreatePolicy("studio-02/owner","channel-01/translation","channel/translation","edit") // 授权

+ 159 - 0
public/app/auth/api.php

@@ -0,0 +1,159 @@
+<?php
+require_once '../../vendor/autoload.php';
+require_once '../config.php';
+
+use Casbin\Enforcer;
+use CasbinAdapter\Medoo\Adapter as DatabaseAdapter;
+
+define("IDPrefixTranslation" , "it_");
+define("IDPrefixChannel", "ic_");
+define("IDPrefixArticle", "ia_");
+define("IDPrefixUser" , "iu_");
+define("IDPrefixOrg"  , "io_");
+define("IDPrefixOrgGroup", "iog_");
+
+// 资源分组:版本风格
+define("ResStudio" , "s_studio");
+// 资源分组:版本风格
+define("ResChannel" , "s_channel");
+// 资源分组:文章
+define("ResArticle" , "s_article");
+// 资源分组:文集
+define("ResArticle" , "s_collection");
+// 资源分组:译文(版本风格 + 文章)句子库
+define("ResTranslation" , "s_translation");
+// 资源分组:逐词译段落
+define("ResArticle" , "s_wbw");
+// 资源分组:术语
+define("ResArticle" , "s_term");
+// 资源分组:用户字典
+define("ResArticle" , "s_userdict");
+
+// 组织拥有者 转让
+define("RoleOrgOwner" , "r_owner");
+// 组织管理员 创建 删除 修改 文章/文集模版 channel group
+define("RoleOrgAdmin" , "r_admin");
+// 组织编辑 修改译文
+define("RoleOrgEditor" , "r_editor");
+// 组织成员 读取任意资源
+define("RoleOrgMember" , "r_member");
+// 组织访客(比如未注册用户) 只读取公开资源
+define("RoleOrgVisitor" , "r_visitor");
+
+// 权限:角色分组
+define("GroupRole" , "g");
+// 权限:资源分组
+define("GroupRes" , "g2");
+
+// 权限:阅读权限
+define("PermRead" , "p_read");
+// 权限:翻译权限
+define("PermTrans" , "p_trans");
+// 权限:修改权限
+define("PermWrite" , "p_write");
+// 权限:创建
+define("PermCreate" , "p_create");
+// 权限:删除
+define("PermDelete" , "p_delete");
+// 权限:修改
+define("PermUpdate" , "p_update");
+
+/*
+
+所有的注册用户都加入 public/member 角色
+所有访问网站者,包括未登录者,都加入 public/visitor 角色
+注册用户在注册时同时注册一个与用户名相同的studio
+
+*/
+
+class CasbinAuth{
+	protected $config = [
+		'database_type' => Database["type"],
+		'server' => Database['server'],
+		'database_name' => Database['name'],
+		'username' => Database['user'],
+		'password' => Database['password'],
+		'port' => Database['port'],
+	];
+	protected $adapter;
+	protected $e;
+	function __construct() {
+		$this->adapter = DatabaseAdapter::newAdapter($config);
+		$this->e = new Enforcer(__DIR__.'/rbac.model.conf', $adapter);
+	}
+
+	/*
+	列出某用户有权限的资源列表
+	例如 zhang3 在 org1 下的 所有 有权限的 channel 列表
+	Index( "zhang3" , "org1" , "channel" )
+	*/
+	public function IndexRes($user,$resNodeId,$resType){
+
+	}
+
+	/*
+	某用户某个资源列表
+	例如 zhang3 在 org1 下的 所有 channel 列表
+	Index( "zhang3" , "org1" , "channel" )
+	*/
+	public function UserCanReadRes($user,$resNodeId,$resType){
+
+	}
+
+	/*
+	某用户建立某个资源
+	*/
+	public function UserCreateRes($user,$resNode,$resType){
+
+	}
+	/*
+	查询某用户是否可以建立某个资源
+	*/
+	public function UserCanCreateRes($user,$resNode,$resType){
+
+	}
+
+	/*
+	某用户删除某个资源
+	*/
+	public function UserDeleteRes($user,$resId,$resType){
+
+	}
+	/*
+	查询某用户是否可以删除某个资源
+	*/
+	public function UserCanDeleteRes($user,$resId,$resType){
+
+	}
+
+	/*
+	查询某用户是否可以修改某个资源
+	返回值 true/fasle
+	*/
+	public function CanUpdateRes($user,$resId,$resType){
+
+	}
+
+
+	public function setRoleRight($role,$resId,$resType,$right){
+
+	}
+	public function testRoleRight($role,$resId,$resType,$right){
+		
+	}
+
+	public function setUserRight($user,$resId,$resType,$right){
+
+	}
+	public function testUserRight($user,$resId,$resType,$right){
+		
+	}
+
+	public function addRole($user,$role){
+
+	}
+
+	public function removeRole($user,$role){
+		
+	}
+}

+ 0 - 1
public/app/auth/casbin-test.php

@@ -2,7 +2,6 @@
 
 require_once '../../vendor/autoload.php';
 require_once '../config.php';
-require_once '../config.php';
 
 use Casbin\Enforcer;
 use CasbinAdapter\Medoo\Adapter as DatabaseAdapter;

+ 6 - 4
public/app/channal/card.php

@@ -1,5 +1,7 @@
 <?php
-//
+/*
+显示channel简介卡片
+*/
 
 require_once "../config.php";
 require_once "../public/_pdo.php";
@@ -10,16 +12,16 @@ require_once '../public/load_lang.php';
 if (isset($_GET["id"])) {
 	$output["id"]=$_GET["id"];
 	PDO_Connect( _FILE_DB_CHANNAL_);
-	$query = "SELECT name,create_time,owner,summary,lang FROM channal  WHERE id = ? ";
+	$query = "SELECT name,created_at,owner_uid ,summary,lang FROM "._TABLE_CHANNEL_."  WHERE uid = ? ";
 	$channel = PDO_FetchRow($query, array($_GET["id"]));
 	$strData="";
 	if ($channel) {
 		$_userinfo = new UserInfo();
-		$name = $_userinfo->getName($channel["owner"]);
+		$name = $_userinfo->getName($channel["owner_uid"]);
 
 		$strData .= "<div>{$_local->gui->name}:".$channel["name"]."</div>";
 		$strData .=  "<div>{$_local->gui->owner}:".$name["nickname"]."</div>";
-		$strData .=  "<div>{$_local->gui->created_time}:".date("Y/m/d",$channel["create_time"]/1000)."</div>";
+		$strData .=  "<div>{$_local->gui->created_time}:".$channel["created_at"]."</div>";
 		$strData .=  "<div>{$_local->gui->language}:".$channel["lang"]."</div>";
 		$strData .=  "<div>{$_local->gui->introduction}:".$channel["summary"]."</div>";
 	} else {

+ 4 - 5
public/app/channal/channal.js

@@ -23,7 +23,7 @@ function channal_list() {
 
 function channal_getById(id) {
 	for (const iterator of _my_channal) {
-		if (iterator.id == id) {
+		if (iterator.uid == id) {
 			return iterator;
 		}
 	}
@@ -60,7 +60,7 @@ function my_channal_list() {
 						html += '<div style="max-width:2em;flex:1;"><input type="checkbox" /></div>';
 						html += "<div style='flex:0.5;'>" + key++ + "</div>";
 						html += "<div style='flex:2;'>";
-						html += "<guide url='../channal/card.php' gid='" + iterator.id + "'>";
+						html += "<guide url='../channal/card.php' gid='" + iterator.uid + "'>";
 						html += iterator.name;
 						html += "</guide>";
 						html += "</div>";
@@ -118,18 +118,17 @@ function my_channal_list() {
 								html += "<div style='flex:1;'>";
 								html +=
 									"<a href='../channal/my_channal_edit.php?id=" +
-									iterator.id +
+									iterator.uid +
 									"'>✏️" +
 									gLocal.gui.edit +
 									"</a></div><div style='flex:1;'>";
-								html += " <a onclick=\"channel_share('" + iterator.id + "')\">🔑"+gLocal.gui.share_to+"</a>";
+								html += " <a onclick=\"channel_share('" + iterator.uid + "')\">🔑"+gLocal.gui.share_to+"</a>";
 								html += "</div>";
 
 								break;
 							default:
 								break;
 						}
-
 						html += "</div>";
 					}
 					$("#my_channal_list").html(html);

+ 10 - 10
public/app/channal/function.php

@@ -6,11 +6,11 @@ require_once "../db/table.php";
 class Channal extends Table
 {
     function __construct($redis=false) {
-		parent::__construct(_FILE_DB_CHANNAL_, "channal", "", "",$redis);
+		parent::__construct(_FILE_DB_CHANNAL_, _TABLE_CHANNEL_, _DB_USERNAME_,_DB_PASSWORD_,$redis);
     }
 
     public function getChannal($id){
-        $query = "SELECT * FROM channal WHERE id= ? ";
+        $query = "SELECT * FROM ".$this->table." WHERE uid =? ";
         $stmt = $this->dbh->prepare($query);
         $stmt->execute(array($id));
         $channal = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -24,7 +24,7 @@ class Channal extends Table
 	public function getTitle($id)
 	{
 		if (isset($id)) {
-			$query = "SELECT name FROM channal  WHERE id = ? ";
+			$query = "SELECT name FROM ".$this->table."  WHERE  uid = ? ";
 			$stmt = $this->dbh->prepare($query);
 			$stmt->execute(array($id));
 			$channal = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -48,8 +48,8 @@ class Channal extends Table
 	}
 	public function getPower($id){
 		#查询用户对此channel是否有权限
-		if(isset($_COOKIE["userid"])){
-			$userId = $_COOKIE["userid"];
+		if(isset($_COOKIE["user_id"])){
+			$userId = $_COOKIE["user_id"];
 		}
 		else{
 			$userId='0';
@@ -61,12 +61,12 @@ class Channal extends Table
 			}
 		}
 		$channelPower = 0;
-		$query = "SELECT owner,status FROM channal WHERE id=? and status>0 ";
+		$query = "SELECT owner_uid,status FROM "._TABLE_CHANNEL_." WHERE uid=? and status>0 ";
 		$stmt = $this->dbh->prepare($query);
 		$stmt->execute(array($id));
 		$channel = $stmt->fetch(PDO::FETCH_ASSOC);
 		if($channel){
-			if(!isset($_COOKIE["userid"])  ){
+			if(!isset($_COOKIE["user_id"])  ){
 				#未登录用户
 				if($channel["status"]==30){
 					#全网公开有建议权限
@@ -78,7 +78,7 @@ class Channal extends Table
 				}
 				
 			}
-			if($channel["owner"]==$_COOKIE["userid"]){
+			if($channel["owner_uid"]==$_COOKIE["user_uid"]){
 				return 30;
 			}
 			else if($channel["status"]>=30){
@@ -87,12 +87,12 @@ class Channal extends Table
 			}
 		}
 		#查询共享权限,如果共享权限更大,覆盖上面的的
-		$sharePower = share_get_res_power($_COOKIE["userid"],$id);
+		$sharePower = share_get_res_power($_COOKIE["user_uid"],$id);
 		if($sharePower>$channelPower){
 			$channelPower=$sharePower;
 		}
 		if($this->redis){
-			$this->redis->hSet("power://channel/".$id,$_COOKIE["userid"],$channelPower);
+			$this->redis->hSet("power://channel/".$id,$_COOKIE["user_uid"],$channelPower);
 		}
 		
 		return $channelPower;

+ 10 - 7
public/app/channal/get.php

@@ -27,17 +27,18 @@ foreach ($my_group as $key => $value) {
 $channelList = array();
 
 //找自己的
-PDO_Connect(_FILE_DB_CHANNAL_);
-$query = "SELECT id,owner,name,status,lang FROM channal WHERE owner = ?  LIMIT 0,100";
-$Fetch_my = PDO_FetchAll($query,array($_COOKIE["userid"]));
+PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+$query = "SELECT uid,owner_uid,name,status,lang FROM "._TABLE_CHANNEL_." WHERE owner_uid = ?  LIMIT 100";
+$Fetch_my = PDO_FetchAll($query,array($_COOKIE["user_uid"]));
 
+#去掉重复的
 foreach ($Fetch_my as $key => $value) {
 	# code...
-	$channelList[$value["id"]]=array("id"=>$value["id"],"owner"=>$value["owner"],"name"=>$value["name"],"power"=>30,"status"=>$value["status"],"lang"=>$value["lang"]);
+	$channelList[$value["uid"]]=array("uid"=>$value["uid"],"owner_uid"=>$value["owner_uid"],"name"=>$value["name"],"power"=>30,"status"=>$value["status"],"lang"=>$value["lang"]);
 }
 
 # 找协作的
-$coop_channal =  share_res_list_get($_COOKIE["userid"],2);
+$coop_channal =  share_res_list_get($_COOKIE["user_uid"],2);
 foreach ($coop_channal as $key => $value) {
 	# return res_id,res_type,power res_title  res_owner_id
 	if(isset($channelList[$value["res_id"]])){
@@ -46,7 +47,7 @@ foreach ($coop_channal as $key => $value) {
 		}
 	}
 	else{
-		$channelList[$value["res_id"]]=array("id"=>$value["res_id"],"owner"=>$value["res_owner_id"],"name"=>$value["res_title"],"power"=>(int)$value["power"],"status"=>(int)$value["status"],"lang"=>(int)$value["lang"]);
+		$channelList[$value["res_id"]]=array("uid"=>$value["res_id"],"owner_uid"=>$value["res_owner_id"],"name"=>$value["res_title"],"power"=>(int)$value["power"],"status"=>(int)$value["status"],"lang"=>(int)$value["lang"]);
 	}
 }
 
@@ -56,11 +57,13 @@ $output = array();
 foreach ($channelList as $key => $value) {
     # code...
 	$new = $value;
-	$name = $_userinfo->getName($value["owner"]);	
+	$name = $_userinfo->getName($value["owner_uid"]);	
 	$new["username"] = $name["username"];
 	$new["nickname"] = $name["nickname"];	
 	$new["count"] = 0;
     $new["all"] = 1;
+    $new["owner"] = $value["owner_uid"];
+
     $output[]=$new;
 }
 

+ 9 - 7
public/app/channal/my_channal_get.php

@@ -1,5 +1,5 @@
 <?php
-//查询term字典
+//获取我的channel 列表,已经废弃
 
 require_once "../config.php";
 require_once "../public/_pdo.php";
@@ -9,12 +9,13 @@ require_once '../group/function.php';
 
 
 if(isset($_GET["id"])){
-    PDO_Connect(""._FILE_DB_CHANNAL_);
+    PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
     $id=$_GET["id"];
-    $query = "SELECT * FROM channal  WHERE id = ? ";
+    $query = "SELECT uid as id ,owner_uid as owner, name , summary , status , lang , create_time,modify_time  FROM "._TABLE_CHANNEL_."  WHERE uid=? ";
 	$Fetch = PDO_FetchRow($query,array($id));
 
-	#获取协作者
+	#TODO获取协作者
+	/*
 	if($Fetch){
 		$user_info = new UserInfo();
 		$group_info = new GroupInfo();
@@ -31,12 +32,13 @@ if(isset($_GET["id"])){
 		}
 		$Fetch["coop"]=$coop;
 	}
+	*/
     echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
 }
 else{
-    PDO_Connect(""._FILE_DB_CHANNAL_);
-    $query = "SELECT * FROM channal  WHERE owner = ? ";
-    $Fetch = PDO_FetchAll($query,array($_COOKIE["userid"]));
+    PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid as id ,owner_uid as owner, name , summary , status , lang , create_time,modify_time FROM "._TABLE_CHANNEL_."  WHERE owner_uid = ? ";
+    $Fetch = PDO_FetchAll($query,array($_COOKIE["user_uid"]));
     echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
 }
 

+ 8 - 5
public/app/channal/my_channal_post.php

@@ -1,4 +1,7 @@
 <?php
+/*
+修改channel
+*/
 require_once "../config.php";
 require_once "../public/_pdo.php";
 require_once '../public/function.php';
@@ -8,7 +11,7 @@ require_once '../hostsetting/function.php';
 $respond=array("status"=>0,"message"=>"");
 
 #先查询对此channal是否有权限修改
-PDO_Connect(_FILE_DB_CHANNAL_);
+PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
 $cooperation = 0;
 if(isset($_POST["id"])){
 	$redis = redis_connect();
@@ -30,9 +33,9 @@ if($channelPower<30){
 
 $channelOldInfo = $channel->getChannal($_POST["id"]);
 
-$query="UPDATE channal SET name = ? ,  summary = ?,  status = ? , lang = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$query="UPDATE "._TABLE_CHANNEL_." SET editor_id=?, name = ? ,  summary = ?,  status = ? , lang = ? , updated_at = now()  , modify_time= ?   where uid = ?  ";
 $sth = $PDO->prepare($query);
-$sth->execute(array($_POST["name"] , $_POST["summary"], $_POST["status"] , $_POST["lang"] ,  mTime() , mTime() , $_POST["id"]));
+$sth->execute(array($_COOKIE["user_id"],$_POST["name"] , $_POST["summary"], $_POST["status"] , $_POST["lang"] ,  mTime() , $_POST["id"]));
 $respond=array("status"=>0,"message"=>"");
 if (!$sth || ($sth && $sth->errorCode() != 0)) {
 	$error = PDO_ErrorInfo();
@@ -47,7 +50,7 @@ else{
 	}
     // 设置 句子库和逐词译库可见性
     PDO_Connect(_FILE_DB_SENTENCE_);
-    $query="UPDATE sentence SET language = ?  , status = ? where  channal = ?  ";
+    $query="UPDATE "._TABLE_SENTENCE_." SET language = ?  , status = ? where  channel_uid = ?  ";
     $sth = PDO_Execute($query,array($_POST["lang"],$_POST["status"],$_POST["id"]));
     if (!$sth || ($sth && $sth->errorCode() != 0)) {
         $error = PDO_ErrorInfo();
@@ -57,7 +60,7 @@ else{
 
 	// 设置 逐词译库可见性
 	PDO_Connect(_FILE_DB_USER_WBW_);
-	$query="UPDATE "._TABLE_USER_WBW_BLOCK_." SET lang = ?  , status = ? where  channal = ?  ";
+	$query="UPDATE "._TABLE_USER_WBW_BLOCK_." SET lang = ?  , status = ? where  channel_uid = ?  ";
 	$sth = PDO_Execute($query,array($_POST["lang"],$_POST["status"],$_POST["id"]));
 	if (!$sth || ($sth && $sth->errorCode() != 0)) {
 		$error = PDO_ErrorInfo();

+ 6 - 3
public/app/channal/my_channal_put.php

@@ -4,12 +4,15 @@ require_once "../config.php";
 require_once "../public/_pdo.php";
 require_once '../public/function.php';
 require_once '../hostsetting/function.php';
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
+
 $respond=array("status"=>0,"message"=>"");
 if(isset($_COOKIE["userid"])){
-	PDO_Connect(_FILE_DB_CHANNAL_);
-	$query="INSERT INTO channal ( id,  owner  , name  , summary ,  status  , lang, create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ? , ? , ? , ? , ? , ?  ) ";
+	PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+	$query="INSERT INTO "._TABLE_CHANNEL_." ( id, uid,  owner_uid  , editor_id, name  , summary ,  status  , lang, create_time , modify_time    )  VALUES  ( ?, ? , ? , ? , ? , ? , ? , ? , ? , ?  ) ";
 	$sth = $PDO->prepare($query);
-	$sth->execute(array(UUID::v4() , $_COOKIE["userid"] , $_POST["name"] , "" , $_POST["status"] ,$_POST["lang"]  ,  mTime() ,  mTime() , mTime() ));
+	$sth->execute(array($snowflake->id() , UUID::v4() , $_COOKIE["user_uid"] , $_COOKIE["user_id"] , $_POST["name"] , "" , $_POST["status"] ,$_POST["lang"]  ,  mTime() ,  mTime() ));
 	$respond=array("status"=>0,"message"=>"");
 	if (!$sth || ($sth && $sth->errorCode() != 0)) {
 		$error = PDO_ErrorInfo();

+ 2 - 2
public/app/collect/card.php

@@ -8,8 +8,8 @@ require_once '../ucenter/function.php';
 
 if (isset($_GET["id"])) {
 	$output["id"]=$_GET["id"];
-	PDO_Connect( _FILE_DB_USER_ARTICLE_);
-	$query = "SELECT title,create_time,owner,summary FROM collect  WHERE id = ? ";
+	PDO_Connect( _FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
+	$query = "SELECT title,create_time,owner,summary FROM "._TABLE_COLLECTION_."  WHERE uid = ? ";
 	$result = PDO_FetchRow($query, array($_GET["id"]));
 	$strData="";
 	if ($result) {

+ 33 - 19
public/app/collect/function.php

@@ -11,8 +11,8 @@ class CollectInfo
 	private $_redis;
 	private $errorMsg;
     public function __construct($redis=false) {
-        $dns = ""._FILE_DB_USER_ARTICLE_;
-        $this->dbh = new PDO($dns, "", "",array(PDO::ATTR_PERSISTENT=>true));
+        $dns = _FILE_DB_USER_ARTICLE_;
+        $this->dbh = new PDO($dns, _DB_USERNAME_,_DB_PASSWORD_,array(PDO::ATTR_PERSISTENT=>true));
         $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);  
 		$this->_redis=$redis;
         $buffer = array();
@@ -30,7 +30,7 @@ class CollectInfo
             return $buffer[$id];
         }
         if($this->dbh){
-            $query = "SELECT id,title,owner,status,lang,article_list FROM collect WHERE id= ?";
+            $query = "SELECT uid as id,title,owner,status,lang,article_list FROM "._TABLE_COLLECTION_." WHERE uid= ?";
             $stmt = $this->dbh->prepare($query);
             $stmt->execute(array($id));
 			$collect = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -54,7 +54,7 @@ class CollectInfo
             return array();
         }
         if($this->dbh){
-            $query = "SELECT article_id FROM article_list WHERE collect_id= ? limit 0,1000";
+            $query = "SELECT article_id FROM "._TABLE_ARTICLE_COLLECTION_." WHERE collect_id= ? limit 1000";
             $stmt = $this->dbh->prepare($query);
             $stmt->execute(array($id));
 			$article_list = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -72,39 +72,41 @@ class CollectInfo
 
 	public function getPower($id){
 		#查询用户对此是否有权限	
-		if(isset($_COOKIE["userid"])){
-			$userId = $_COOKIE["userid"];
+		if(isset($_COOKIE["user_uid"])){
+			$userId = $_COOKIE["user_uid"];
 		}
 		else{
 			$userId='0';
 		}
+		/*
 		if($this->_redis!==false){
 			$power = $this->_redis->hGet("power://collection/".$id,$userId);
 			if($power!==FALSE){
 				return $power;
 			}
 		}
+		*/
 		$iPower = 0;
-		$query = "SELECT owner,status FROM collect WHERE id=?  ";
+		$query = "SELECT owner,status FROM "._TABLE_COLLECTION_." WHERE uid=?  ";
 		$stmt = $this->dbh->prepare($query);
 		$stmt->execute(array($id));
 		$result = $stmt->fetch(PDO::FETCH_ASSOC);
 		if($result){
-			if(!isset($_COOKIE["userid"])){
+			if(!isset($_COOKIE["user_uid"])){
 				#未登录用户
 				if($result["status"]==30){
 					#全网公开有读取和建议权限
-					return 10;
+					$iPower =  10;
 				}
 				else{
 					#其他状态没有任何权限
-					return 0;
+					$iPower =  0;
 				}
 			}
 			else{
-				if($result["owner"]==$_COOKIE["userid"]){
+				if($result["owner"]==$_COOKIE["user_uid"]){
 					#自己的
-					return 30;
+					$iPower =  30;
 				}
 				else if($result["status"]>=30){
 					#全网公开的 可以提交pr
@@ -128,15 +130,15 @@ class CollectInfo
 	
 		if (count($arrData) > 0) {
 			$this->dbh->beginTransaction();
-			$query="UPDATE collect SET title = ? , 
+			$query="UPDATE "._TABLE_COLLECTION_." SET title = ? , 
 									   subtitle = ? , 
 									   summary = ?, 
 									   article_list = ?  ,  
 									   status = ? , 
 									   lang = ? , 
-									   receive_time= ?  , 
+									   updated_at= now()  , 
 									   modify_time= ?   
-									   where  id = ?  ";
+									   where  uid = ?  ";
 			$sth = $this->dbh->prepare($query);
 			foreach ($arrData as $data) {
 				$sth->execute(array(
@@ -146,7 +148,6 @@ class CollectInfo
 									$data["article_list"] , 
 									$data["status"] , 
 									$data["lang"] ,  
-									$data["receive_time"] , 
 									$data["modify_time"] , 
 									$data["id"])
 								);
@@ -182,7 +183,7 @@ class CollectInfo
 		$respond=array("status"=>0,"message"=>"");
 		if (count($arrData) > 0) {
 			$this->dbh->beginTransaction();
-			$query="INSERT INTO collect ( id,  title  , subtitle  , summary , article_list , owner, lang  , status  , create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ?  , ? , ? , ? , ? , ? , ? , ? ) ";
+			$query="INSERT INTO "._TABLE_COLLECTION_." ( uid,  title  , subtitle  , summary , article_list , owner, lang  , status  , create_time , modify_time    )  VALUES  (  ? , ? , ?  , ? , ? , ? , ? , ? , ? , ? ) ";
 			$sth = $this->dbh->prepare($query);
 			$newDataList=array();
 			foreach ($arrData as $data) {
@@ -217,7 +218,7 @@ class CollectInfo
 						$newData["owner"]=$data["owner"];
 					}
 					else{
-						$newData["owner"]=$_COOKIE["userid"];
+						$newData["owner"]=$_COOKIE["user_uid"];
 					}	
 					if(isset($data["lang"])){
 						$newData["lang"]=$data["lang"];
@@ -244,7 +245,20 @@ class CollectInfo
 						$newData["modify_time"]=mTime();
 					}
 					$newDataList[]=$newData;
-					$sth->execute(array($newData["id"] , $newData["title"] , $newData["subtitle"] ,$newData["summary"], $newData["article_list"] , $newData["owner"] , $newData["lang"] , $newData["status"] , $newData["create_time"] ,  $newData["modify_time"] , mTime() ));				
+					$sth->execute(
+							array(
+								$newData["id"] , 
+								$newData["title"] , 
+								$newData["subtitle"] ,
+								$newData["summary"], 
+								$newData["article_list"] , 
+								$newData["owner"] , 
+								$newData["lang"] , 
+								$newData["status"] , 
+								$newData["create_time"] ,  
+								$newData["modify_time"] 
+								)
+							);				
 				}
 				else{
 					$this->errorMsg="标题不能为空";

+ 4 - 4
public/app/collect/list.php

@@ -23,8 +23,8 @@ require_once '../ucenter/function.php';
     else{
         $begin = 0;
     }
-    PDO_Connect(_FILE_DB_USER_ARTICLE_);
-    $query = "SELECT * FROM collect  where  status>=30 ";
+    PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid as id,title,subtitle,summary,owner,article_list FROM "._TABLE_COLLECTION_."  where  status>=30 ";
     if(isset($_GET["orderby"])){
         switch ($_GET["orderby"]) {
             case 'like':
@@ -40,8 +40,8 @@ require_once '../ucenter/function.php';
     else{
         $query .="ORDER BY modify_time DESC";
     }
-    $query .=" LIMIT ? , ? ";
-    $Fetch = PDO_FetchAll($query,array($begin,$onepage));
+    $query .=" LIMIT ? OFFSET ? ";
+    $Fetch = PDO_FetchAll($query,array($onepage,$begin));
     foreach ($Fetch as $key => $value) {
         # code...
         $userinfo = new UserInfo();

+ 7 - 10
public/app/commit/commit.js

@@ -28,7 +28,7 @@ function commit_render_channel_select() {
 		html += "<div class='channel'>";
 		let isFound = false;
 		for (const iterator of _my_channal) {
-			if (_commit_data.src == iterator.id) {
+			if (_commit_data.src == iterator.uid) {
 				html += iterator.name;
 				isFound = true;
 				break;
@@ -36,7 +36,7 @@ function commit_render_channel_select() {
 		}
 		if (!isFound) {
 			for (const iterator of _channalData) {
-				if (_commit_data.src == iterator.id) {
+				if (_commit_data.src == iterator.uid) {
 					html += iterator.name;
 					isFound = true;
 					break;
@@ -63,12 +63,12 @@ function commit_render_channel_select() {
 		}
 	}
 	for (const iterator of _my_channal) {
-		if (iterator.status > 0 && _commit_data.src != iterator.id) {
-			html += "<option value='" + iterator.id + "' ";
-			if (_commit_data.dest == iterator.id) {
+		if (iterator.status > 0 && _commit_data.src != iterator.uid) {
+			html += "<option value='" + iterator.uid + "' ";
+			if (_commit_data.dest == iterator.uid) {
 				html += " selected ";
 			}
-			if (typeof _commit_data.src != "undefined" && _commit_data.src == iterator.id) {
+			if (typeof _commit_data.src != "undefined" && _commit_data.src == iterator.uid) {
 				html += "style:'display:none;' ";
 			}
 			html += " >" + iterator.name + "-";
@@ -145,10 +145,7 @@ function commit_preview_render() {
 				},
 				function (data, status) {
 					if (status == "success") {
-						try {
-							sentData = JSON.parse(data);
-						} catch (e) {}
-
+						sentData = JSON.parse(data);
 						previewWin.show(commit_render_comp(0));
 					}
 				}

+ 18 - 2
public/app/commit/commit.php

@@ -37,10 +37,26 @@ if($destChannelPower<10){
 	exit;		
 }
 
-$db_trans_sent = new PDO(_FILE_DB_SENTENCE_, "", "", array(PDO::ATTR_PERSISTENT => true));
+$db_trans_sent = new PDO(_FILE_DB_SENTENCE_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
 $db_trans_sent->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
-$query = "SELECT * FROM sentence WHERE book= ? AND paragraph= ? AND begin= ? AND end= ?  AND channal = ?  ";
+$query = "SELECT uid as id,
+parent_uid as parent,
+block_uid as block_id,
+channel_uid as channal,
+book_id as book,
+paragraph,
+word_start as begin,
+word_end as end,
+author,
+editor_uid as editor,
+content as text,
+language,
+version as ver,
+status,
+strlen,
+modify_time,
+create_time FROM "._TABLE_SENTENCE_." WHERE book_id= ? AND paragraph= ? AND word_start= ? AND word_end= ?  AND channel_uid = ?  ";
 $stmt = $db_trans_sent->prepare($query);
 
 if($stmt){

+ 5 - 0
public/app/config.sample.php

@@ -36,6 +36,11 @@ define("Database",[
 ]);
 
 
+# 雪花id
+define("SnowFlake",[
+	"DatacenterId"=>1,
+	"WorkerId"=>1
+]);
 /*
 Redis 设置,
 */

+ 31 - 29
public/app/config.table.php

@@ -1,7 +1,9 @@
 <?php 
+
 # 雪花算法id 起始日期2021-12-22 绝对不可修改!!!
 define("_SnowFlakeDate_","2021-12-22");
 
+
 #表名设置,不能更改
 define("_DB_ENGIN_", Database["type"]);
 define("_DB_HOST_", Database["server"]);
@@ -213,20 +215,20 @@ define("_SQLITE_TABLE_SENTENCE_HISTORAY_", "sent_historay");
 
 //PostgreSQL
 define("_PG_DB_USER_SENTENCE_HISTORAY_", _PDO_DB_DSN_);
-define("_PG_TABLE_SENTENCE_HISTORAY_", "sent_historaies");
+define("_PG_TABLE_SENTENCE_HISTORAY_", "sent_histories");
 
 
 
 # 逐词解析字典
 # sqlite
 define("_SQLITE_DB_WBW_", "sqlite:" . __DIR__ . "/../tmp/user/wbw.db3");
-define("_SQLITE_TABLE_DICT_WBW_", "wbw");
-define("_SQLITE_TABLE_DICT_WBW_INDEX_", "wbw_index");
+define("_SQLITE_TABLE_DICT_WBW_", "dict");
+define("_SQLITE_TABLE_DICT_WBW_INDEX_", "user_index");
 
 //PostgreSQL
 define("_PG_DB_WBW_", _PDO_DB_DSN_);
 define("_PG_TABLE_DICT_WBW_", "user_dicts");
-
+define("_PG_TABLE_DICT_WBW_INDEX_", "user_index");
 
 //写入频繁 读取不频繁
 # 用户行为记录
@@ -237,7 +239,7 @@ define("_SQLITE_TABLE_USER_OPERATION_FRAME_", "edit");
 
 //PostgreSQL
 define("_PG_DB_USER_ACTIVE_", _PDO_DB_DSN_);
-define("_PG_TABLE_USER_OPERATION_DAILY_", "user_operation_dailys");
+define("_PG_TABLE_USER_OPERATION_DAILY_", "user_operation_dailies");
 define("_PG_TABLE_USER_OPERATION_FRAME_", "user_operation_frames");
 
 #sqlite
@@ -283,7 +285,7 @@ define("_SQLITE_TABLE_ARTICLE_COLLECTION_", "article_list");
 define("_PG_DB_USER_ARTICLE_", _PDO_DB_DSN_);
 define("_PG_TABLE_ARTICLE_", "articles");
 define("_PG_TABLE_COLLECTION_", "collections");
-define("_PG_TABLE_ARTICLE_COLLECTION_", "article_collection");
+define("_PG_TABLE_ARTICLE_COLLECTION_", "article_collections");
 
 # 术语
 define("_SQLITE_DB_TERM_", "sqlite:" . __DIR__ . "/../tmp/user/dhammaterm.db");
@@ -585,43 +587,43 @@ define("_TABLE_REF_INDEX_", _SQLITE_TABLE_REF_INDEX_);
 # 用户数据表
 
 #sqlite
-define("_FILE_DB_USER_WBW_", _SQLITE_DB_USER_WBW_);
-define("_TABLE_USER_WBW_", _SQLITE_TABLE_USER_WBW_);
-define("_TABLE_USER_WBW_BLOCK_", _SQLITE_TABLE_USER_WBW_BLOCK_);
+define("_FILE_DB_USER_WBW_", _PG_DB_USER_WBW_);
+define("_TABLE_USER_WBW_", _PG_TABLE_USER_WBW_);
+define("_TABLE_USER_WBW_BLOCK_", _PG_TABLE_USER_WBW_BLOCK_);
 
 
 # 译文
 #sqlite
-define("_FILE_DB_SENTENCE_", _SQLITE_DB_SENTENCE_);
-define("_TABLE_SENTENCE_", _SQLITE_TABLE_SENTENCE_);
-define("_TABLE_SENTENCE_BLOCK_", _SQLITE_TABLE_SENTENCE_BLOCK_);
-define("_TABLE_SENTENCE_PR_", _SQLITE_TABLE_SENTENCE_PR_);
+define("_FILE_DB_SENTENCE_", _PG_DB_SENTENCE_);
+define("_TABLE_SENTENCE_", _PG_TABLE_SENTENCE_);
+define("_TABLE_SENTENCE_BLOCK_", _PG_TABLE_SENTENCE_BLOCK_);
+define("_TABLE_SENTENCE_PR_", _PG_TABLE_SENTENCE_PR_);
 
 
 # 译文编辑历史
 #sqlite
-define("_FILE_DB_USER_SENTENCE_HISTORAY_", _SQLITE_DB_USER_SENTENCE_HISTORAY_);
-define("_TABLE_SENTENCE_HISTORAY_", _SQLITE_TABLE_SENTENCE_HISTORAY_);
+define("_FILE_DB_USER_SENTENCE_HISTORAY_", _PG_DB_USER_SENTENCE_HISTORAY_);
+define("_TABLE_SENTENCE_HISTORAY_", _PG_TABLE_SENTENCE_HISTORAY_);
 
 
 # 逐词解析字典
 # sqlite
-define("_FILE_DB_WBW_", _SQLITE_DB_WBW_);
-define("_TABLE_DICT_WBW_", _SQLITE_TABLE_DICT_WBW_);
-define("_TABLE_DICT_WBW_INDEX_", _SQLITE_TABLE_DICT_WBW_INDEX_);
+define("_FILE_DB_WBW_", _PG_DB_WBW_);
+define("_TABLE_DICT_WBW_", _PG_TABLE_DICT_WBW_);
+define("_TABLE_DICT_WBW_INDEX_", _PG_TABLE_DICT_WBW_INDEX_);
 
 
 //写入频繁 读取不频繁
 # 用户行为记录
 #sqlite
-define("_FILE_DB_USER_ACTIVE_", _SQLITE_DB_USER_ACTIVE_);
-define("_TABLE_USER_OPERATION_DAILY_", _SQLITE_TABLE_USER_OPERATION_DAILY_);
-define("_TABLE_USER_OPERATION_FRAME_", _SQLITE_TABLE_USER_OPERATION_FRAME_);
+define("_FILE_DB_USER_ACTIVE_", _PG_DB_USER_ACTIVE_);
+define("_TABLE_USER_OPERATION_DAILY_", _PG_TABLE_USER_OPERATION_DAILY_);
+define("_TABLE_USER_OPERATION_FRAME_", _PG_TABLE_USER_OPERATION_FRAME_);
 
 
 #sqlite
-define("_FILE_DB_USER_ACTIVE_LOG_", _SQLITE_DB_USER_ACTIVE_LOG_);
-define("_TABLE_USER_OPERATION_LOG_", _SQLITE_TABLE_USER_OPERATION_LOG_);
+define("_FILE_DB_USER_ACTIVE_LOG_", _PG_DB_USER_ACTIVE_LOG_);
+define("_TABLE_USER_OPERATION_LOG_", _PG_TABLE_USER_OPERATION_LOG_);
 
 
 //读取频繁 写入不频繁 
@@ -633,16 +635,16 @@ define("_TABLE_USER_INFO_", _SQLITE_TABLE_USER_INFO_);
 
 # 版本风格 
 #sqlite
-define("_FILE_DB_CHANNAL_", _SQLITE_DB_CHANNAL_);
-define("_TABLE_CHANNEL_", _SQLITE_TABLE_CHANNEL_);
+define("_FILE_DB_CHANNAL_", _PG_DB_CHANNAL_);
+define("_TABLE_CHANNEL_", _PG_TABLE_CHANNEL_);
 
 
 # 文章 文集
 
-define("_FILE_DB_USER_ARTICLE_", _SQLITE_DB_USER_ARTICLE_);
-define("_TABLE_ARTICLE_", _SQLITE_TABLE_ARTICLE_);
-define("_TABLE_COLLECTION_", _SQLITE_TABLE_COLLECTION_);
-define("_TABLE_ARTICLE_COLLECTION_", _SQLITE_TABLE_ARTICLE_COLLECTION_);
+define("_FILE_DB_USER_ARTICLE_", _PG_DB_USER_ARTICLE_);
+define("_TABLE_ARTICLE_", _PG_TABLE_ARTICLE_);
+define("_TABLE_COLLECTION_", _PG_TABLE_COLLECTION_);
+define("_TABLE_ARTICLE_COLLECTION_", _PG_TABLE_ARTICLE_COLLECTION_);
 
 
 

+ 5 - 11
public/app/db/channel.php

@@ -1,21 +1,15 @@
 <?php
+/*
+废弃
+*/
 require_once "../config.php";
 require_once "../db/table.php";
 require_once "../public/function.php";
-/*
-CREATE TABLE likes (
-    id            INTEGER      PRIMARY KEY AUTOINCREMENT,
-    like_type     VARCHAR (16) NOT NULL,
-    resource_type VARCHAR (32) NOT NULL,
-    resource_id   CHAR (36)    NOT NULL,
-    user_id       INTEGER      NOT NULL,
-    created_at    TIMESTAMP DEFAULT CURRENT_TIMESTAMP     NOT NULL //只做初始化,更新时不自动更新
-);
-*/
+
 class Channel extends Table
 {
     function __construct($redis=false) {
-		parent::__construct(_FILE_DB_CHANNAL_, "channal", "", "",$redis);
+		parent::__construct(_FILE_DB_CHANNAL_, _TABLE_CHANNEL_, _DB_USERNAME_,_DB_PASSWORD_,$redis);
     }
 
 	public function  index(){

+ 2 - 1
public/app/db/database.php

@@ -6,7 +6,7 @@
 class Database
 {
     // specify your own database credentials
-    private $host = '127.0.0.1';
+    private $host = 'localhost';
     private $db_name = 'mint';
     private $username = 'postgras';
     private $password = '123456';
@@ -22,6 +22,7 @@ class Database
             'driver' => 'pgsql',
             'host' => $this->host,
             'database' => $this->db_name,
+            'port' => 5432,
             'username' => $this->username,
             'password' => $this->password,
             'charset' => 'utf8',

+ 3 - 0
public/app/db/table.php

@@ -1,6 +1,7 @@
 <?php
 require_once __DIR__."/../config.php";
 require_once __DIR__."/../redis/function.php";
+require_once __DIR__."/../public/snowflakeid.php";
 
 // Require Composer's autoloader.
 require '../../vendor/autoload.php';
@@ -19,6 +20,7 @@ class Table
 	protected $result;
 	public $medoo;
 	protected $redisProfix;
+    protected $SnowFlake;
     function __construct($db,$table,$user="",$password="",$redis=false) {
         $this->dbh = new PDO($db, _DB_USERNAME_, _DB_PASSWORD_,array(PDO::ATTR_PERSISTENT=>true));
         $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
@@ -36,6 +38,7 @@ class Table
 		$this->table = $table;
 		$this->result = ["ok"=>true,"message"=>"","data"=>array()];
 		$this->redisProfix = $table . "/:id";
+        $this->SnowFlake = new SnowFlakeId();
     }
 	
 	public function _index($columns,$where){

+ 5 - 3
public/app/db/test.php

@@ -1,6 +1,6 @@
 <?php
-require "../vendor/autoload.php";
-require "../config/database.php";
+require_once '../../vendor/autoload.php';
+require "./database.php";
 use Illuminate\Database\Capsule\Manager as Capsule;
 
 $dbclass = new Database();
@@ -13,4 +13,6 @@ $capsule->setAsGlobal();
 $capsule->bootEloquent();
 
 
-$users = Capsule::table('user')->where('id', '=', 1)->get();
+$users = Capsule::table('wbw_blocks')->where('id', '=', 129195)->get();
+
+var_dump($users);

+ 5 - 5
public/app/db/wbw_block.php

@@ -6,22 +6,22 @@ require_once "../channal/function.php";
 class WbwBlock extends Table
 {
     function __construct($redis=false) {
-		parent::__construct(_FILE_DB_USER_WBW_, _TABLE_USER_WBW_BLOCK_, "", "",$redis);
+		parent::__construct(_FILE_DB_USER_WBW_, _TABLE_USER_WBW_BLOCK_, _DB_USERNAME_, _DB_PASSWORD_,$redis);
     }
 
 	public function getPower($blockId){
 		$channelInfo = new Channal($this->redis);
 		$power = 0;
-		$query = "SELECT channal,owner from "._TABLE_USER_WBW_BLOCK_."   where id= ?  ";
+		$query = "SELECT channel_uid , creator_uid  from "._TABLE_USER_WBW_BLOCK_."   where uid= ?  ";
 		$row = $this->fetch($query,array($blockId));
 		if($row ){
-			if(empty($row["channal"])){
-				if($row["owner"]==$_COOKIE["userid"]){
+			if(empty($row["channel_uid"])){
+				if($row["creator_uid"]==$_COOKIE["userid"]){
 					$power = 30;
 				}
 			}
 			else{
-				$power = $channelInfo->getPower($row["channal"]);
+				$power = $channelInfo->getPower($row["channel_uid"]);
 			}
 		}
 		return $power;

+ 17 - 14
public/app/dict/dict_lookup.php

@@ -107,9 +107,8 @@ $right_word_list = "";
 				}
 
 				
-                //$query = "SELECT dict.dict_id,dict.mean,dn.shortname from " . _TABLE_DICT_REF_ . " LEFT JOIN "._TABLE_DICT_REF_NAME_." as dn ON dict.dict_id = dn.id where word = ? limit 30";
-
-				$Fetch = PDO_FetchAll($query, array($x));
+                $query = "SELECT dict.id,dict.dict_id,dict.mean,info.shortname from " . _TABLE_DICT_REF_ . " LEFT JOIN info ON dict.dict_id = info.id where word = ? limit 30";
+                $Fetch = PDO_FetchAll($query, array($x));
                 $iFetch = count($Fetch);
                 $count_return += $iFetch;
                 if ($iFetch > 0) {
@@ -339,6 +338,7 @@ function lookup_user($word){
 
 	$output ="";
 	$Fetch=array();
+	
 	if($redis){
 		$wordData = $redis->hGet("dict://user",$word);
 			if($wordData){
@@ -349,7 +349,7 @@ function lookup_user($word){
 						$Fetch[] = array("id"=>$one[0],
 										"pali"=>$one[1],
 										"type"=>$one[2],
-										"gramma"=>$one[3],
+										"grammar"=>$one[3],
 										"parent"=>$one[4],
 										"mean"=>$one[5],
 										"note"=>$one[6],
@@ -357,8 +357,8 @@ function lookup_user($word){
 										"factormean"=>$one[8],
 										"status"=>$one[9],
 										"confidence"=>$one[10],
-										"creator"=>$one[11],
-										"dict_name"=>$one[12],
+										"creator_id"=>$one[11],
+										"source"=>$one[12],
 										"lang"=>$one[13],
 										);
 					}						
@@ -368,9 +368,10 @@ function lookup_user($word){
 				#  没找到就不找了
 			}
 	}
-	else{
-		PDO_Connect("" . _FILE_DB_WBW_);
-		$query = "SELECT *  from " . _TABLE_DICT_REF_ . " where pali = ? limit 0,100";
+	else
+	{
+		PDO_Connect(_FILE_DB_WBW_,_DB_USERNAME_,_DB_PASSWORD_);
+		$query = "SELECT *  from " . _TABLE_DICT_WBW_ . " where word = ? and source='_SYS_USER_WBW_' limit 100";
 		$Fetch = PDO_FetchAll($query, array($word));
 	}
 	
@@ -380,12 +381,12 @@ function lookup_user($word){
 		$count_return++;
 		$userlist = array();
 		foreach ($Fetch as $value) {
-			if (isset($userlist[$value["creator"]])) {
-				$userlist[$value["creator"]] += 1;
+			if (isset($userlist[$value["creator_id"]])) {
+				$userlist[$value["creator_id"]] += 1;
 			} else {
-				$userlist[$value["creator"]] = 1;
+				$userlist[$value["creator_id"]] = 1;
 			}
-			$userwordcase = $value["type"] . "#" . $value["gramma"];
+			$userwordcase = $value["type"] . "#" . $value["grammar"];
 			$parent = $value["parent"];
 			if(empty($parent)){
 				$parent = "_null_";
@@ -510,7 +511,9 @@ function lookup_term($word){
 			}
 	}
 	else{
-		PDO_Connect("" . _FILE_DB_WBW_);
+		exit;
+		#TODO 查询term 表
+		PDO_Connect(_FILE_DB_WBW_,_DB_USERNAME_,_DB_PASSWORD_);
 		$query = "SELECT *  from " . _TABLE_DICT_REF_ . " where pali = ? limit 0,100";
 		$Fetch = PDO_FetchAll($query, array($word));
 	}

+ 11 - 10
public/app/dict/redis_import_user.php

@@ -6,37 +6,38 @@ $rediskey = "dict://user";
 if (PHP_SAPI == "cli") {
 	$redis = redis_connect();
 	if ($redis != false) {
-		$dbh = new PDO(_FILE_DB_WBW_, "", "", array(PDO::ATTR_PERSISTENT => true));
+		$dbh = new PDO(_FILE_DB_WBW_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
 		$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
-		$query = "SELECT pali from dict where pali !='' group by pali";
+		$query = "SELECT word from "._TABLE_DICT_WBW_." group by word";
 		$stmtPli = $dbh->query($query);
 		while ($word = $stmtPli->fetch(PDO::FETCH_ASSOC)) {
 			# code...
-			$query = "SELECT * from dict where pali = ? ";
+			$query = "SELECT * from "._TABLE_DICT_WBW_." where word = ? and source = '_USER_DATA_' ";
 			$stmt = $dbh->prepare($query);
-			$stmt->execute(array($word["pali"]));
+			$stmt->execute(array($word["word"]));
 			if ($stmt) {
 				$Fetch = $stmt->fetchAll(PDO::FETCH_ASSOC);
 				$redisWord=array();
 				foreach ($Fetch as  $one) {
 					# code...
-					$redisWord[] = array($one["id"],
-										$one["pali"],
+					$redisWord[] = array(
+									$one["id"],
+									$one["word"],
 									$one["type"],
 									$one["gramma"],
-									$one["parent"],
+									$one["base"],
 									$one["mean"],
 									$one["note"],
 									$one["factors"],
 									$one["factormean"],
 									$one["status"],
 									$one["confidence"],
-									$one["creator"],
-									$one["dict_name"],
+									$one["creator_id"],
+									$one["source"],
 									$one["language"]
 									);
 				}
-				$redis->hSet($rediskey,$word["pali"],json_encode($redisWord,JSON_UNESCAPED_UNICODE));
+				$redis->hSet($rediskey,$word["word"],json_encode($redisWord,JSON_UNESCAPED_UNICODE));
 			}
 		}
 	}

+ 4 - 4
public/app/dict/redis_pali_word_statistic.php

@@ -103,20 +103,20 @@ if (PHP_SAPI == "cli") {
 
 				break;
 			case 'update':
-				$dbh = new PDO(_FILE_DB_WBW_, "", "", array(PDO::ATTR_PERSISTENT => true,PDO::SQLITE_ATTR_OPEN_FLAGS => PDO::SQLITE_OPEN_READONLY));
+				$dbh = new PDO(_FILE_DB_WBW_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true,PDO::SQLITE_ATTR_OPEN_FLAGS => PDO::SQLITE_OPEN_READONLY));
 				$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 				
-				$query = "SELECT pali from dict where 1  group by pali";
+				$query = "SELECT word from "._TABLE_DICT_WBW_."  group by word";
 				$stmt = $dbh->prepare($query);
 				$stmt->execute();
 				$count = 0;
 				while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
 					# code...
-					$word = $redis->hGet($strKey, $row["pali"]);
+					$word = $redis->hGet($strKey, $row["word"]);
 					if($word){
 						$eWord = json_decode($word,true);
 						$eWord["user"]=1;
-						$redis->hSet($strKey, $row["pali"],json_encode($eWord,JSON_UNESCAPED_UNICODE));
+						$redis->hSet($strKey, $row["word"],json_encode($eWord,JSON_UNESCAPED_UNICODE));
 						$count++;
 					}
 				}		

+ 13 - 10
public/app/doc/edit_wbw.php

@@ -40,15 +40,15 @@ echo "</fieldset>";
 echo "<fieldset>";
 echo "<legend>{$_local->gui->channel} ({$_local->gui->required})</legend>";
 echo "<div>";
-PDO_Connect(""._FILE_DB_CHANNAL_);
-$query = "SELECT * from channal where owner = ?   limit 0,100";
-$Fetch = PDO_FetchAll($query,array($_COOKIE["userid"]));
+PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+$query = "SELECT * from "._TABLE_CHANNEL_." where owner_uid = ?   limit 100";
+$Fetch = PDO_FetchAll($query,array($_COOKIE["user_uid"]));
 $i=0;
 foreach($Fetch as $row){
     echo '<div class="file_list_row" style="padding:5px;">';
 
     echo '<div class="pd-10"  style="max-width:2em;flex:1;">';
-    echo '<input name="channal" value="'.$row["id"].'" ';
+    echo '<input name="channal" value="'.$row["uid"].'" ';
     if($i==0){
         echo "checked";
     }
@@ -59,8 +59,9 @@ foreach($Fetch as $row){
     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
     // 查询逐词解析库
     PDO_Connect(_FILE_DB_USER_WBW_);
-    $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channal = '{$row["id"]}' and book='{$book}' and paragraph in {$strQueryParaList}  limit 0,100";
-    $FetchWBW = PDO_FetchOne($query);
+	#TODO $strQueryParaList 改为预处理
+    $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channel_uid = ? and book_id=? and paragraph in {$strQueryParaList}  limit 100";
+    $FetchWBW = PDO_FetchOne($query,array($row["uid"],$book));
     echo '</div>';
     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
     if($FetchWBW==0){
@@ -69,14 +70,16 @@ foreach($Fetch as $row){
     }
     else{
         echo $FetchWBW.$_local->gui->para;
-        echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["id"]}'>open</a>";
+        echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["uid"]}'>open</a>";
     }
     echo '</div>';
 
     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-    PDO_Connect(""._FILE_DB_SENTENCE_);
-    $query = "select count(*) from sentence where channal = '{$row["id"]}' and book='{$book}' and paragraph in {$strQueryParaList}  limit 0,100";
-    $FetchWBW = PDO_FetchOne($query);
+    PDO_Connect(_FILE_DB_SENTENCE_,_DB_USERNAME_, _DB_PASSWORD_);
+	#TODO $strQueryParaList 改为预处理
+
+    $query = "SELECT count(*) from "._TABLE_SENTENCE_." where channel_uid = ? and book_id= ? and paragraph in {$strQueryParaList}  limit 100";
+    $FetchWBW = PDO_FetchOne($query,array($row["uid"],$book));
     echo '</div>';
     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
     if($FetchWBW==0){

+ 63 - 129
public/app/doc/fork.php

@@ -3,15 +3,18 @@
  *
  *
  */
-require_once '../studio/index_head.php';
+require_once __DIR__."/../public/_pdo.php";
+require_once __DIR__."/../public/function.php";
+require_once __DIR__."/../config.php";
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
+require_once __DIR__.'/../studio/index_head.php';
+
 ?>
 <body id="file_list_body" >
 <?php
-require_once "../public/_pdo.php";
-require_once "../public/function.php";
-require_once "../config.php";
 
-require_once '../studio/index_tool_bar.php';
+require_once __DIR__."/../studio/index_tool_bar.php";
 
 echo '<div class="index_inner" style="    margin-left: 18em;margin-top: 5em;">';
 
@@ -42,15 +45,15 @@ if (isset($_GET["channel"]) == false) {
     echo "<h2>选择一个空白的版风存储新的文档</h2>";
     echo "<form action='fork.php' method='get'>";
     echo "<input type='hidden' name='doc_id' value='{$_GET["doc_id"]}' />";
-    PDO_Connect("" . _FILE_DB_CHANNAL_);
-    $query = "select * from channal where owner = '{$_COOKIE["userid"]}'   limit 0,100";
-    $Fetch = PDO_FetchAll($query);
+    PDO_Connect( _FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid,name,lang,status,create_time from "._TABLE_CHANNEL_." where owner_uid = ?   limit 100";
+    $Fetch = PDO_FetchAll($query,$_COOKIE["user_uid"]);
     $i = 0;
     foreach ($Fetch as $row) {
         echo '<div class="file_list_row" style="padding:5px;display:flex;">';
 
         echo '<div class="pd-10"  style="max-width:2em;flex:1;">';
-        echo '<input name="channel" value="' . $row["id"] . '" ';
+        echo '<input name="channel" value="' . $row["uid"] . '" ';
         if ($i == 0) {
             echo "checked";
         }
@@ -60,7 +63,7 @@ if (isset($_GET["channel"]) == false) {
         echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["lang"] . '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
         PDO_Connect(_FILE_DB_USER_WBW_);
-        $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channal = '{$row["id"]}' and book='{$mbook}' and paragraph in ({$paragraph})  limit 0,100";
+        $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channel_uid = '{$row["uid"]}' and book_id='{$mbook}' and paragraph in ({$paragraph})  limit 100";
         $FetchWBW = PDO_FetchOne($query);
         echo '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
@@ -68,14 +71,14 @@ if (isset($_GET["channel"]) == false) {
             echo $_local->gui->blank;
         } else {
             echo $FetchWBW . $_local->gui->para;
-            echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["id"]}'>open</a>";
+            echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["uid"]}'>open</a>";
         }
         echo '</div>';
 
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-        PDO_Connect(_FILE_DB_SENTENCE_);
-        $query = "SELECT count(*) from sentence where channal = '{$row["id"]}' and book='{$mbook}' and paragraph in ({$paragraph})  limit 0,100";
-        $FetchWBW = PDO_FetchOne($query);
+        PDO_Connect(_FILE_DB_SENTENCE_,_DB_USERNAME_,_DB_PASSWORD_);
+        $query = "SELECT count(*) from "._TABLE_SENTENCE_." where channel_uid = ? and book_id=? and paragraph in ({$paragraph})  limit 1000";
+        $FetchWBW = PDO_FetchOne($query,array($row["uid"],$mbook));
         echo '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
         if ($FetchWBW == 0) {
@@ -99,7 +102,7 @@ if (isset($_GET["channel"]) == false) {
 
 //if(isset($_GET["doc_id"]))
 {
-    PDO_Connect("" . _FILE_DB_FILEINDEX_);
+    PDO_Connect( _FILE_DB_FILEINDEX_,_DB_USERNAME_,_DB_PASSWORD_);
     $doc_id = $_GET["doc_id"];
     $query = "SELECT * from fileindex where id= ? ";
     $Fetch = PDO_FetchAll($query, array($doc_id));
@@ -144,13 +147,13 @@ if (isset($_GET["channel"]) == false) {
                     //$dest=$dir_user_base.$userid.$dir_mydocument.$filename;
                     //复制数据
                     //打开逐词解析数据库
-                    $dns = "" . _FILE_DB_USER_WBW_;
-                    $dbhWBW = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
+                    $dns = _FILE_DB_USER_WBW_;
+                    $dbhWBW = new PDO($dns, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
                     $dbhWBW->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
                     //打开译文数据库
-                    $dns = "" . _FILE_DB_SENTENCE_;
-                    $dbhSent = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
+                    $dns = _FILE_DB_SENTENCE_;
+                    $dbhSent = new PDO($dns, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
                     $dbhSent->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
                     //逐词解析新数据数组
@@ -158,11 +161,6 @@ if (isset($_GET["channel"]) == false) {
                     $arrNewBlockData = array();
                     $arrBlockTransform = array();
 
-                    //译文新数据数组
-                    $arrSentNewBlock = array();
-                    $arrSentNewBlockData = array();
-                    $arrSentBlockTransform = array();
-
                     $newDocBlockList = array();
 
                     $blocks = json_decode($Fetch[0]["doc_block"]);
@@ -171,59 +169,7 @@ if (isset($_GET["channel"]) == false) {
                             case 1:
                                 break;
                             case 2:
-                                //译文
-                                $blockid = $blocks[$i]->block_id;
-                                $query = "select * from sent_block where id= ? ";
-                                $stmt = $dbhSent->prepare($query);
-                                $stmt->execute(array($blockid));
-                                $fBlock = $stmt->fetchAll(PDO::FETCH_ASSOC);
-                                $newBlockId = UUID::V4();
                                 //不复刻译文
-                                //$newDocBlockList[]=array('type' => 2,'block_id' => $newBlockId);
-                                $arrSentBlockTransform[$fBlock[0]["id"]] = $newBlockId;
-                                if (count($fBlock) > 0) {
-                                    array_push($arrSentNewBlock,
-                                        array($newBlockId,
-                                            $fBlock[0]["id"],
-                                            $fBlock[0]["book"],
-                                            $fBlock[0]["paragraph"],
-                                            $_COOKIE["userid"],
-                                            $fBlock[0]["lang"],
-                                            $fBlock[0]["author"],
-                                            $fBlock[0]["editor"],
-                                            $fBlock[0]["tag"],
-                                            $fBlock[0]["status"],
-                                            mTime(),
-                                            mTime(),
-                                        ));
-                                }
-
-                                $query = "select * from sentence where block_id= ? ";
-                                $stmtSent = $dbhSent->prepare($query);
-                                $stmtSent->execute(array($fBlock[0]["id"]));
-                                $fBlockData = $stmtSent->fetchAll(PDO::FETCH_ASSOC);
-                                foreach ($fBlockData as $value) {
-                                    array_push($arrSentNewBlockData,
-                                        array(UUID::V4(),
-                                            $arrSentBlockTransform[$value["block_id"]],
-                                            $value["book"],
-                                            $value["paragraph"],
-                                            $value["begin"],
-                                            $value["end"],
-                                            $value["channal"],
-                                            $value["tag"],
-                                            $value["author"],
-                                            $_COOKIE["userid"],
-                                            $value["text"],
-                                            $value["language"],
-                                            $value["ver"],
-                                            $value["status"],
-                                            mTime(),
-                                            mTime(),
-                                        ));
-
-                                }
-
                                 break;
                             case 3:
                                 break;
@@ -234,7 +180,7 @@ if (isset($_GET["channel"]) == false) {
                             case 6:
                                 #逐词解析
                                 $blockid = $blocks[$i]->block_id;
-                                $query = "select * from "._TABLE_USER_WBW_BLOCK_." where id= ? ";
+                                $query = "SELECT uid,book_id,paragraph,style,lang,status from "._TABLE_USER_WBW_BLOCK_." where uid= ? ";
                                 $stmt = $dbhWBW->prepare($query);
                                 $stmt->execute(array($blockid));
                                 $fBlock = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -243,17 +189,18 @@ if (isset($_GET["channel"]) == false) {
                                 $arrBlockTransform[$fBlock[0]["id"]] = $newBlockId;
                                 if (count($fBlock) > 0) {
                                     array_push($arrNewBlock,
-                                        array($newBlockId,
-                                            $fBlock[0]["id"],
+                                        array(
+                                            $snowflake->id(),
+                                            $newBlockId,
+                                            $fBlock[0]["uid"],
                                             $_GET["channel"],
                                             $_COOKIE["userid"],
-                                            $fBlock[0]["book"],
+                                            $fBlock[0]["book_id"],
                                             $fBlock[0]["paragraph"],
                                             $fBlock[0]["style"],
                                             $fBlock[0]["lang"],
                                             $fBlock[0]["status"],
-                                            mTime(),
-                                            mTime(),
+                                            mTime()
                                         ));
                                 }
 
@@ -263,7 +210,9 @@ if (isset($_GET["channel"]) == false) {
                                 $fBlockData = $stmtWBW->fetchAll(PDO::FETCH_ASSOC);
                                 foreach ($fBlockData as $value) {
                                     array_push($arrNewBlockData,
-                                        array(UUID::V4(),
+                                        array(
+                                            $snowflake->id(),
+                                            UUID::V4(),
                                             $arrBlockTransform[$value["block_id"]],
                                             $value["book"],
                                             $value["paragraph"],
@@ -288,7 +237,22 @@ if (isset($_GET["channel"]) == false) {
 
                     if (count($arrNewBlock) > 0) {
                         $dbhWBW->beginTransaction();
-                        $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." ('id','parent_id','channal','owner','book','paragraph','style','lang','status','modify_time','receive_time') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+                        $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." 
+                                            ( 
+                                                id,
+                                                uid ,
+                                                parent_id ,
+                                                channel_uid ,
+                                                creator_uid ,
+                                                book_id ,
+                                                paragraph ,
+                                                style ,
+                                                lang ,
+                                                status ,
+                                                modify_time ,
+                                                updated_at
+                                            )
+                                            VALUES (?,?,?,?,?,?,?,?,?,?,?,now())";
                         $stmtNewBlock = $dbhWBW->prepare($query);
                         foreach ($arrNewBlock as $oneParam) {
                             $stmtNewBlock->execute($oneParam);
@@ -308,7 +272,21 @@ if (isset($_GET["channel"]) == false) {
                     if (count($arrNewBlockData) > 0) {
                         // 开始一个事务,逐词解析数据 关闭自动提交
                         $dbhWBW->beginTransaction();
-                        $query = "INSERT INTO "._TABLE_USER_WBW_." ('id','block_id','book','paragraph','wid','word','data','modify_time','receive_time','status','owner') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+                        $query = "INSERT INTO "._TABLE_USER_WBW_." 
+                                    (
+                                        'id',
+                                        'uid',
+                                        'block_id',
+                                        'book',
+                                        'paragraph',
+                                        'wid',
+                                        'word',
+                                        'data',
+                                        'create_time',
+                                        'update_time',
+                                        'status',
+                                        'owner'
+                                        ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
                         $stmtWbwData = $dbhWBW->prepare($query);
                         foreach ($arrNewBlockData as $oneParam) {
                             $stmtWbwData->execute($oneParam);
@@ -327,50 +305,6 @@ if (isset($_GET["channel"]) == false) {
 
                     //不复刻译文
 
-                    //译文 block数据块
-                    /*
-                    if(count($arrSentNewBlock)>0){
-                    $dbhSent->beginTransaction();
-                    $query="INSERT INTO sent_block ('id','parent_id','book','paragraph','owner','lang','author','editor','tag','status','modify_time','receive_time') VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
-                    $stmtSentNewBlock = $dbhSent->prepare($query);
-                    foreach($arrSentNewBlock as $oneParam){
-                    //print_r($oneParam);
-                    $stmtSentNewBlock->execute($oneParam);
-                    }
-                    // 提交更改
-                    $dbhSent->commit();
-                    if (!$stmtSentNewBlock || ($stmtSentNewBlock && $stmtSentNewBlock->errorCode() != 0)) {
-                    $error = $dbhSent->errorInfo();
-                    echo "error - $error[2] <br>";
-                    }
-                    else{
-                    //译文 block块复刻成功
-                    $count=count($arrNewBlock);
-                    echo "wbw block $count recorders.<br/>";
-                    }
-                    }
-
-                    if(count($arrSentNewBlockData)>0){
-                    // 开始一个事务,逐词解析数据 关闭自动提交
-                    $dbhSent->beginTransaction();
-                    $query="INSERT INTO sentence ('id','block_id','book','paragraph','begin','end','channal','tag','author','editor','text','language','ver','status','modify_time','receive_time') VALUES (? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?, ?)";
-                    $stmtSentData = $dbhSent->prepare($query);
-                    foreach($arrSentNewBlockData as $oneParam){
-                    $stmtSentData->execute($oneParam);
-                    }
-                    // 提交更改
-                    $dbhSent->commit();
-                    if (!$stmtSentData || ($stmtSentData && $stmtSentData->errorCode() != 0)) {
-                    $error = $dbhSent->errorInfo();
-                    echo "error - $error[2] <br>";
-                    }
-                    else{
-                    //译文 数据 复刻成功
-                    $count=count($arrSentNewBlockData);
-                    echo "new translation $count recorders.";
-                    }
-                    }
-                     */
 
                     //插入记录到文件索引
                     $filesize = 0;

+ 203 - 170
public/app/doc/fork_channel.php

@@ -1,18 +1,24 @@
 <?php
 
-/*拷贝其他人的文件
- *
- *
- */
+/*
+*拷贝其他人的逐词解析数据
+ *输入参数
+ *src_channel
+ *dest_channel
+ *bookid
+ *paragraph
+*/
 require_once '../studio/index_head.php';
 ?>
 <body id="file_list_body" >
 <?php
-require_once "../config.php";
-require_once "../public/_pdo.php";
-require_once "../public/function.php";
-require_once "../channal/function.php";
-require_once "../redis/function.php";
+require_once __DIR__."/../config.php";
+require_once __DIR__."/../public/_pdo.php";
+require_once __DIR__."/../public/function.php";
+require_once __DIR__."/../channal/function.php";
+require_once __DIR__."/../redis/function.php";
+require_once __DIR__."/../public/snowflakeid.php";
+$snowflake = new SnowFlakeId();
 
 $redis = redis_connect();
 
@@ -52,16 +58,16 @@ if (isset($_GET["dest_channel"]) == false) {
     echo "<input type='hidden' name='book' value='{$_GET["book"]}' />";
     echo "<input type='hidden' name='para' value='{$_GET["para"]}' />";
     echo "<input type='hidden' name='src_channel' value='{$_GET["src_channel"]}' />";
-    PDO_Connect(_FILE_DB_CHANNAL_);
-    $query = "select * from channal where owner = '{$_COOKIE["userid"]}'   limit 0,100";
+    PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid,name,lang,status,create_time from "._TABLE_CHANNEL_." where owner_uid = '{$_COOKIE["user_uid"]}'   limit 100";
     $Fetch = PDO_FetchAll($query);
     $i = 0;
-    PDO_Connect( _FILE_DB_USER_WBW_);	
+    PDO_Connect( _FILE_DB_USER_WBW_,_DB_USERNAME_,_DB_PASSWORD_);	
     foreach ($Fetch as $row) {
         echo '<div class="file_list_row" style="padding:5px;display:flex;">';
 
         echo '<div class="pd-10"  style="max-width:2em;flex:1;">';
-        echo '<input name="dest_channel" value="' . $row["id"] . '" ';
+        echo '<input name="dest_channel" value="' . $row["uid"] . '" ';
         if ($i == 0) {
             echo "checked";
         }
@@ -70,7 +76,7 @@ if (isset($_GET["dest_channel"]) == false) {
         echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["name"] . '</div>';
         echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["lang"] . '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-        $query = "select count(*) from "._TABLE_USER_WBW_BLOCK_." where channal = '{$row["id"]}' and book='{$mbook}' and paragraph in ({$paragraph})  limit 0,100";
+        $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channel_uid = '{$row["uid"]}' and book_id = '{$mbook}' and paragraph in ({$paragraph})  limit 100";
         $FetchWBW = PDO_FetchOne($query);
         echo '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
@@ -78,7 +84,7 @@ if (isset($_GET["dest_channel"]) == false) {
             echo $_local->gui->blank;
         } else {
             echo $FetchWBW . $_local->gui->para;
-            echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["id"]}'>open</a>";
+            echo "<a href='../studio/editor.php?op=openchannal&book={$mbook}&para={$paragraph}&channal={$row["uid"]}'>open</a>";
         }
         echo '</div>';
 
@@ -94,184 +100,211 @@ if (isset($_GET["dest_channel"]) == false) {
     exit;
 }
 
-PDO_Connect( _FILE_DB_USER_WBW_);	
+PDO_Connect( _FILE_DB_USER_WBW_,_DB_USERNAME_,_DB_PASSWORD_);	
 
 $channelInfo= new Channal($redis);
 
 $srcPower = (int)$channelInfo->getPower($_GET["src_channel"]);
-
 {
 
-	{
-
         if ($srcPower == 30) {
             //自己的文档
             echo "这是自己的文档,不能复刻。";
         } else {
             //别人的文档
-            //查询以前自己是否曾经复刻
-            $query = "SELECT * from "._TABLE_USER_WBW_BLOCK_." where parent_channel=? and owner=? ";
-            $FetchSelf = PDO_FetchAll($query,array($_GET["src_channel"],$_COOKIE["userid"]));
-            $iFetchSelf = count($FetchSelf);
-            if ($iFetchSelf > 0) {
-                //以前打开过
-                echo "文档已经复刻";
-                echo "正在<a href='../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$FetchSelf[0]["channal"]}'>打开</a>文档";
-                echo "<script>";
-                echo "window.location.assign(\"../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$FetchSelf[0]["channal"]}\");";
-                echo "</script>";
-            } else {
+			{
                 //以前没打开过
-                echo "<h3>共享的文档,正在fork...</h3>";
-                echo "<div style='display:none;'>";
-
-				{
-                    //复制数据
-                    //打开逐词解析数据库
-                    $dns = _FILE_DB_USER_WBW_;
-                    $dbhWBW = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
-                    $dbhWBW->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
+			echo "<h3>共享的文档,正在fork...</h3>";
+			echo "<div style='display:none;'>";
 
-                    //逐词解析新数据数组
-                    $arrNewBlock = array();
-                    $arrNewBlockData = array();
-                    $arrBlockTransform = array();
+		
+			//复制数据
+			//打开逐词解析数据库
+			$dns = _FILE_DB_USER_WBW_;
+			$dbhWBW = new PDO($dns,_DB_USERNAME_,_DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
+			$dbhWBW->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
-                    $blocks = $_para;
-                    for ($i = 0; $i < count($blocks); $i++) {
-						$query = "SELECT id from "._TABLE_USER_WBW_BLOCK_." where book= ? and paragraph = ? and channal = ? ";
-						$stmt = $dbhWBW->prepare($query);
-						$stmt->execute(array($_GET["book"],$iPara,$_GET["dest_channel"]));
-						$fDest = $stmt->fetch(PDO::FETCH_ASSOC);
-						if($fDest){
-							#旧的逐词解析数据块wbw_block id 
-							$destId = $fDest["id"];
-						}
-						#逐词解析
-						$iPara = $blocks[$i];
-						$query = "SELECT * from "._TABLE_USER_WBW_BLOCK_." where book= ? and paragraph = ? and channal = ? ";
-						$stmt = $dbhWBW->prepare($query);
-						$stmt->execute(array($_GET["book"],$iPara,$_GET["src_channel"]));
-						$fBlock = $stmt->fetchAll(PDO::FETCH_ASSOC);
-						if(isset($destId)){
-							$newBlockId = $destId;
-						}
-						else{
-							$newBlockId = UUID::V4();
-						}
-						$arrBlockTransform[$fBlock[0]["id"]] = $newBlockId;
-						if (count($fBlock) > 0) {
-							array_push($arrNewBlock,
-								array($newBlockId,
-									"",
-									$_GET["dest_channel"],
-									$_GET["src_channel"],
-									$_COOKIE["userid"],
-									$fBlock[0]["book"],
-									$fBlock[0]["paragraph"],
-									$fBlock[0]["style"],
-									$fBlock[0]["lang"],
-									$fBlock[0]["status"],
-									mTime(),
-									mTime(),
-									mTime()
-								));
-						}
+			//逐词解析新数据数组
+			$arrNewBlock = array();
+			$arrNewBlockData = array();
+			$arrBlockTransform = array();
 
-						$query = "SELECT * from "._TABLE_USER_WBW_." where block_id= ? ";
-						$stmtWBW = $dbhWBW->prepare($query);
-						$stmtWBW->execute(array($fBlock[0]["id"]));
-						$fBlockData = $stmtWBW->fetchAll(PDO::FETCH_ASSOC);
-						foreach ($fBlockData as $value) {
-							array_push($arrNewBlockData,
-								array(UUID::V4(),
-									$arrBlockTransform[$value["block_id"]],
-									$value["book"],
-									$value["paragraph"],
-									$value["wid"],
-									$value["word"],
-									$value["data"],
-									mTime(),
-									mTime(),
-									$value["status"],
-									$_COOKIE["userid"],
-								));
+			$blocks = $_para;
+			for ($i = 0; $i < count($blocks); $i++) {
+				#查找是否有旧的wbw_block数据
+				$query = "SELECT id,uid from "._TABLE_USER_WBW_BLOCK_." where book_id= ? and paragraph = ? and channel_uid = ? ";
+				$stmt = $dbhWBW->prepare($query);
+				$stmt->execute(array($_GET["book"],$blocks[$i],$_GET["dest_channel"]));
+				$fDest = $stmt->fetch(PDO::FETCH_ASSOC);
+				if($fDest){
+					#旧的逐词解析数据块wbw_block id 
+					$destUid = $fDest["uid"];
+					$destId = $fDest["id"];
+				}
+				#复制源wbw_block
+				$iPara = $blocks[$i];
+				$query = "SELECT uid,book_id,paragraph,style,lang,status from "._TABLE_USER_WBW_BLOCK_." where book_id= ? and paragraph = ? and channel_uid = ? ";
+				$stmt = $dbhWBW->prepare($query);
+				$stmt->execute(array($_GET["book"],$iPara,$_GET["src_channel"]));
+				$fSrcBlock = $stmt->fetch(PDO::FETCH_ASSOC);
+				if(isset($destId)){
+					#有旧的wbw_block uuid 使用旧的uuid
+					$newBlockId = $destId;
+					$newBlockUid = $destUid;
+				}
+				else{
+					$newBlockId = $snowflake->id();
+					$newBlockUid = UUID::V4();
+				}
+				
+				if ($fSrcBlock) {
+					$arrBlockTransform[$fSrcBlock["uid"]] = $newBlockId;
+					array_push($arrNewBlock,
+						array(
+                            $newBlockId,
+                            $newBlockUid,
+							"",
+							$_GET["dest_channel"],
+							$_GET["src_channel"],
+							$_COOKIE["user_uid"],
+							$_COOKIE["user_id"],
+							$fSrcBlock["book_id"],
+							$fSrcBlock["paragraph"],
+							$fSrcBlock["style"],
+							$fSrcBlock["lang"],
+							$fSrcBlock["status"],
+							mTime(),
+							mTime()
+						));
+				}
+				#复制源数据
+				$query = "SELECT block_uid, book_id,paragraph,wid,word,data,status from "._TABLE_USER_WBW_." where block_uid= ? ";
+				$stmtWBW = $dbhWBW->prepare($query);
+				$stmtWBW->execute(array($fSrcBlock["uid"]));
+				$fBlockData = $stmtWBW->fetchAll(PDO::FETCH_ASSOC);
+				foreach ($fBlockData as $value) {
+					array_push($arrNewBlockData,
+						array(
+                            $snowflake->id(),
+                            UUID::V4(),
+							$newBlockUid,
+							$newBlockId,
+							$value["book_id"],
+							$value["paragraph"],
+							$value["wid"],
+							$value["word"],
+							$value["data"],
+							mTime(),
+							mTime(),
+							$value["status"],
+							$_COOKIE["user_uid"],
+                            $_COOKIE["user_id"],
+						));
 
-						}
+				}
 
-                    }
+			}
 
-					# 查找目标block是否存在
+			# 查找目标block是否存在
 
-					//删除旧的逐词解析block数据块
-					$query = "DELETE from "._TABLE_USER_WBW_BLOCK_." where  paragraph = ? AND book = ? AND channal = ? ";
-					$stmt = $dbhWBW->prepare($query);
-					$stmt->execute(array($iPara,$_GET["book"],$_GET["dest_channel"]));
-					
-                    //新增逐词解析block数据块
-                    if (count($arrNewBlock) > 0) {
-                        $dbhWBW->beginTransaction();
-                        $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." ('id','parent_id','channal','parent_channel','owner','book','paragraph','style','lang','status','modify_time','receive_time','create_time') VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
-                        $stmtNewBlock = $dbhWBW->prepare($query);
-                        foreach ($arrNewBlock as $oneParam) {
-                            $stmtNewBlock->execute($oneParam);
-                        }
-                        // 提交更改
-                        $dbhWBW->commit();
-                        if (!$stmtNewBlock || ($stmtNewBlock && $stmtNewBlock->errorCode() != 0)) {
-                            $error = $dbhWBW->errorInfo();
-                            echo "error - $error[2] <br>";
-							exit;
-                        } else {
-                            //逐词解析block块复刻成功
-                            $count = count($arrNewBlock);
-                            echo "wbw block $count recorders.<br/>";
-                        }
-                    }
+			//删除旧的逐词解析block数据块
+			$query = "DELETE from "._TABLE_USER_WBW_BLOCK_." where  paragraph = ? AND book_id = ? AND channel_uid = ? ";
+			$stmt = $dbhWBW->prepare($query);
+			$stmt->execute(array($iPara,$_GET["book"],$_GET["dest_channel"]));
+			
+			//新增逐词解析block数据块
+			if (count($arrNewBlock) > 0) {
+				$dbhWBW->beginTransaction();
+				$query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." 
+                (
+                    id,
+                    uid , 
+                    parent_id , 
+                    channel_uid , 
+                    parent_channel_uid , 
+                    creator_uid , 
+                    editor_id , 
+                    book_id , 
+                    paragraph , 
+                    style , 
+                    lang , 
+                    status , 
+                    modify_time , 
+                    create_time 
+                ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+				$stmtNewBlock = $dbhWBW->prepare($query);
+				foreach ($arrNewBlock as $oneParam) {
+					$stmtNewBlock->execute($oneParam);
+				}
+				// 提交更改
+				$dbhWBW->commit();
+				if (!$stmtNewBlock || ($stmtNewBlock && $stmtNewBlock->errorCode() != 0)) {
+					$error = $dbhWBW->errorInfo();
+					echo "error - $error[2] <br>";
+					exit;
+				} else {
+					//逐词解析block块复刻成功
+					$count = count($arrNewBlock);
+					echo "wbw block $count recorders.<br/>";
+				}
+			}
 
-					//删除逐词解析数据块
-					if(isset($destId)){
-						$query = "DELETE from "._TABLE_USER_WBW_." where  block_id = ? ";
-						$stmt = $dbhWBW->prepare($query);
-						$stmt->execute($destId);
-					}
-					
-                    if (count($arrNewBlockData) > 0) {
-                        // 开始一个事务,逐词解析数据 关闭自动提交
-                        $dbhWBW->beginTransaction();
-                        $query = "INSERT INTO "._TABLE_USER_WBW_." ('id','block_id','book','paragraph','wid','word','data','modify_time','receive_time','status','owner') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
-                        $stmtWbwData = $dbhWBW->prepare($query);
-                        foreach ($arrNewBlockData as $oneParam) {
-                            $stmtWbwData->execute($oneParam);
-                        }
-                        // 提交更改
-                        $dbhWBW->commit();
-                        if (!$stmtWbwData || ($stmtWbwData && $stmtWbwData->errorCode() != 0)) {
-                            $error = $dbhWBW->errorInfo();
-                            echo "error - $error[2] <br>";
-							exit;
-                        } else {
-                            //逐词解析 数据 复刻成功
-                            $count = count($arrNewBlockData);
-                            echo "new wbw $count recorders.";
-                        }
-                    }
-
-                   {
-                        //成功
-                        echo "doc list updata 1 recorders.";
-                        echo "</div>";
-                        echo "<h3>复刻成功</h3>";
-                        echo "正在<a href='../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$_GET["dest_channel"]}'>打开</a>文档";
-                        echo "<script>";
-                        echo "window.location.assign(\"../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$_GET["dest_channel"]}\");";
-                        echo "</script>";
-                    }
-                }
+			//删除旧的wbw逐词解析数据块
+			if(isset($destId)){
+				$query = "DELETE from "._TABLE_USER_WBW_." where  block_uid = ? ";
+				$stmt = $dbhWBW->prepare($query);
+				$stmt->execute(array($destId));
+			}
+			
+			if (count($arrNewBlockData) > 0) {
+				// 开始一个事务,逐词解析数据 关闭自动提交
+				$dbhWBW->beginTransaction();
+				$query = "INSERT INTO "._TABLE_USER_WBW_." 
+                ( 
+                    id,
+                    uid , 
+                    block_uid , 
+                    block_id , 
+                    book_id , 
+                    paragraph , 
+                    wid , 
+                    word , 
+                    data , 
+                    modify_time , 
+                    create_time , 
+                    status , 
+                    creator_uid,
+                    editor_id
+                    ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+				$stmtWbwData = $dbhWBW->prepare($query);
+				foreach ($arrNewBlockData as $oneParam) {
+					$stmtWbwData->execute($oneParam);
+				}
+				// 提交更改
+				$dbhWBW->commit();
+				if (!$stmtWbwData || ($stmtWbwData && $stmtWbwData->errorCode() != 0)) {
+					$error = $dbhWBW->errorInfo();
+					echo "error - $error[2] <br>";
+					exit;
+				} else {
+					//逐词解析 数据 复刻成功
+					$count = count($arrNewBlockData);
+					echo "new wbw $count recorders.";
+				}
+			}
 
+			
+			//成功
+			echo "doc list updata 1 recorders.";
+			echo "</div>";
+			echo "<h3>复刻成功</h3>";
+			echo "正在<a href='../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$_GET["dest_channel"]}'>打开</a>文档";
+			echo "<script>";
+			echo "window.location.assign(\"../studio/editor.php?op=openchannal&book={$_GET["book"]}&para={$_para[0]}&channal={$_GET["dest_channel"]}\");";
+			echo "</script>";
+			
             }
         }
-    }
 }
 
 echo "</div>";

+ 6 - 6
public/app/doc/load_channal_para.php

@@ -39,13 +39,13 @@ echo "\n<dict></dict>\n";
 echo "<message></message>\n";
 echo "<body>\n";
 
-$dh_wbw = new PDO("" . _FILE_DB_USER_WBW_, "", "", array(PDO::ATTR_PERSISTENT => true));
+$dh_wbw = new PDO(_FILE_DB_USER_WBW_, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
 $dh_wbw->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
 foreach ($paralist as $para) {
 
     $albumId = UUID::v4();
-    $query = "SELECT * FROM "._TABLE_USER_WBW_BLOCK_." WHERE channal=? AND book = ? AND paragraph = ?  ";
+    $query = "SELECT uid,creator_uid,lang FROM "._TABLE_USER_WBW_BLOCK_." WHERE channel_uid=? AND book_id = ? AND paragraph = ?  ";
     $stmt = $dh_wbw->prepare($query);
     $stmt->execute(array($channal, $book, $para));
     $FetchBlock = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -60,16 +60,16 @@ foreach ($paralist as $para) {
         echo "<title></title>";
         echo "<album_id></album_id>";
         echo "<album_guid></album_guid>";
-        echo "<author>{$FetchBlock["owner"]}</author>";
+        echo "<author>{$FetchBlock["creator_uid"]}</author>";
         echo "<language>{$FetchBlock["lang"]}</language>";
         echo "<version>1</version>";
         echo "<edition>1</edition>";
-        echo "<id>{$FetchBlock["id"]}</id>";
+        echo "<id>{$FetchBlock["uid"]}</id>";
         echo "</info>\n";
 
         echo "<data>\n";
-        $block_id = $FetchBlock["id"];
-        $query = "SELECT * from "._TABLE_USER_WBW_." where block_id= ? order by wid ASC";
+        $block_id = $FetchBlock["uid"];
+        $query = "SELECT data from "._TABLE_USER_WBW_." where block_uid= ? order by wid ASC";
         $stmt = $dh_wbw->prepare($query);
         $stmt->execute(array($block_id));
         $wbw_data = $stmt->fetchAll(PDO::FETCH_ASSOC);

+ 29 - 33
public/app/doc/pcs2db.php

@@ -40,15 +40,15 @@ if (isset($_GET["channel"]) == false) {
     echo "<h2>选择一个空白的版风存储新的文档</h2>";
     echo "<form action='pcs2db.php' method='get'>";
     echo "<input type='hidden' name='doc_id' value='{$_GET["doc_id"]}' />";
-    PDO_Connect("" . _FILE_DB_CHANNAL_);
-    $query = "SELECT * from channal where owner = '{$_COOKIE["userid"]}'   limit 0,100";
-    $Fetch = PDO_FetchAll($query);
+    PDO_Connect( _FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+    $query = "SELECT uid,name,lang,status,create_time from "._TABLE_CHANNEL_." where owner_uid = ?   limit 100";
+    $Fetch = PDO_FetchAll($query,$_COOKIE["user_uid"]);
     $i = 0;
     foreach ($Fetch as $row) {
         echo '<div class="file_list_row" style="padding:5px;display:flex;">';
 
         echo '<div class="pd-10"  style="max-width:2em;flex:1;">';
-        echo '<input name="channel" value="' . $row["id"] . '" ';
+        echo '<input name="channel" value="' . $row["uid"] . '" ';
         if ($i == 0) {
             echo "checked";
         }
@@ -58,7 +58,7 @@ if (isset($_GET["channel"]) == false) {
         echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["lang"] . '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
         PDO_Connect("" . _FILE_DB_USER_WBW_);
-        $query = "select count(*) from "._TABLE_USER_WBW_BLOCK_." where channal = '{$row["id"]}' and book='{$mbook}' and paragraph in ({$paragraph})  limit 0,100";
+        $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channel_uid = '{$row["uid"]}' and book_id='{$mbook}' and paragraph in ({$paragraph})  limit 100";
         $FetchWBW = PDO_FetchOne($query);
         echo '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
@@ -66,14 +66,14 @@ if (isset($_GET["channel"]) == false) {
             echo $_local->gui->blank;
         } else {
             echo $FetchWBW . $_local->gui->para;
-            echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["id"]}'>open</a>";
+            echo "<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["uid"]}'>open</a>";
         }
         echo '</div>';
 
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-        PDO_Connect("" . _FILE_DB_SENTENCE_);
-        $query = "select count(*) from sentence where channal = '{$row["id"]}' and book='{$mbook}' and paragraph in ({$paragraph})  limit 0,100";
-        $FetchWBW = PDO_FetchOne($query);
+        PDO_Connect(_FILE_DB_SENTENCE_,_DB_USERNAME_, _DB_PASSWORD_);
+        $query = "SELECT count(*) from "._TABLE_SENTENCE_." where channel_uid = ? and book_id= ?  and paragraph in ({$paragraph})  limit 100";
+        $FetchWBW = PDO_FetchOne($query,array($row["uid"],$mbook));
         echo '</div>';
         echo '<div class="title" style="flex:2;padding-bottom:5px;">';
         if ($FetchWBW == 0) {
@@ -141,13 +141,13 @@ $dataBlock = $xml->xpath('//block');
 
     //复制数据
     //打开逐词解析数据库
-    $dns = "" . _FILE_DB_USER_WBW_;
-    $dbhWBW = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
+    $dns = _FILE_DB_USER_WBW_;
+    $dbhWBW = new PDO($dns, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
     $dbhWBW->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
     //打开译文数据库
-    $dns = "" . _FILE_DB_SENTENCE_;
-    $dbhSent = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
+    $dns = _FILE_DB_SENTENCE_;
+    $dbhSent = new PDO($dns, _DB_USERNAME_, _DB_PASSWORD_, array(PDO::ATTR_PERSISTENT => true));
     $dbhSent->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
 
     //逐词解析新数据数组
@@ -221,7 +221,6 @@ $dataBlock = $xml->xpath('//block');
                                 $block->info->paragraph,
                                 $sent_begin,
                                 $sent_end,
-                                "",
                                 $block->info->author,
                                 $_COOKIE["userid"],
                                 $paraText,
@@ -231,7 +230,6 @@ $dataBlock = $xml->xpath('//block');
                                 "7",
                                 $file_modify_time,
                                 mTime(),
-                                mTime(),
                                 $_GET["channel"],
                             ));
                     }
@@ -252,8 +250,7 @@ $dataBlock = $xml->xpath('//block');
                             "",
                             $block->info->language,
                             "",
-                            $file_modify_time,
-                            mTime(),
+                            $file_modify_time
                         ));
                 }
 
@@ -326,7 +323,6 @@ $dataBlock = $xml->xpath('//block');
                         $word->real,
                         $sWordData,
                         $file_modify_time,
-                        mTime(),
                         $word->status,
                         $_COOKIE["userid"],
                     ));
@@ -344,19 +340,19 @@ $dataBlock = $xml->xpath('//block');
     if (count($arrNewBlock) > 0) {
         $dbhWBW->beginTransaction();
         $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." (
-										'id',
-										'parent_id',
-										'channal',
-										'owner',
-										'book',
-										'paragraph',
-										'style',
-										'lang',
-										'status',
-										'modify_time',
-										'receive_time'
+										 uid ,
+										 parent_id ,
+										 channel_uid ,
+										 creator_uid ,
+										 book_id ,
+										 paragraph ,
+										 style ,
+										 lang ,
+										 status ,
+										 modify_time ,
+										updated_at
 										)
-										VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+										VALUES (?,?,?,?,?,?,?,?,?,?,now())";
         $stmtNewBlock = $dbhWBW->prepare($query);
         foreach ($arrNewBlock as $oneParam) {
             $stmtNewBlock->execute($oneParam);
@@ -376,7 +372,7 @@ $dataBlock = $xml->xpath('//block');
     if (count($arrNewBlockData) > 0) {
         // 开始一个事务,逐词解析数据 关闭自动提交
         $dbhWBW->beginTransaction();
-        $query = "INSERT INTO "._TABLE_USER_WBW_." ('id','block_id','book','paragraph','wid','word','data','modify_time','receive_time','status','owner') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+        $query = "INSERT INTO "._TABLE_USER_WBW_." ( uid , block_uid , book_id , paragraph , wid , word , data , modify_time , status , creator_uid ,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,now())";
         $stmtWbwData = $dbhWBW->prepare($query);
         foreach ($arrNewBlockData as $oneParam) {
             $stmtWbwData->execute($oneParam);
@@ -397,7 +393,7 @@ $dataBlock = $xml->xpath('//block');
 
     if (count($arrSentNewBlock) > 0) {
         $dbhSent->beginTransaction();
-        $query = "INSERT INTO sent_block ('id','parent_id','book','paragraph','owner','lang','author','editor','tag','status','modify_time','receive_time') VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
+        $query = "INSERT INTO "._TABLE_SENTENCE_BLOCK_." (uid , parent_uid , book_id , paragraph , owner_uid , lang , author , editor_uid  , status , modify_time , create_time') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
         $stmtSentNewBlock = $dbhSent->prepare($query);
         foreach ($arrSentNewBlock as $oneParam) {
             //print_r($oneParam);
@@ -418,7 +414,7 @@ $dataBlock = $xml->xpath('//block');
     if (count($arrSentNewBlockData) > 0) {
         // 开始一个事务,逐词解析数据 关闭自动提交
         $dbhSent->beginTransaction();
-        $query = "INSERT INTO sentence ('id','block_id','book','paragraph','begin','end','tag','author','editor','text','strlen','language','ver','status','modify_time','receive_time','create_time','channal') VALUES (? , ? , ? , ? , ? ,?, ? , ? , ? , ? , ? , ? , ? , ? , ?, ? , ? ,?)";
+        $query = "INSERT INTO "._TABLE_SENTENCE_." ( uid , block_uid , book_id , paragraph , word_start , word_end , author , editor_uid , content , strlen , language , version , status , modify_time , create_time , channel_uid') VALUES (?  , ? , ? , ? ,?, ? , ? , ? , ? , ? , ? , ? , ? , ?, ? , ? ,?)";
         $stmtSentData = $dbhSent->prepare($query);
         foreach ($arrSentNewBlockData as $oneParam) {
             $stmtSentData->execute($oneParam);

+ 1 - 1
public/app/group/group.js

@@ -31,7 +31,7 @@ function channal_list() {
 
 function channal_getById(id) {
 	for (const iterator of _my_channal) {
-		if (iterator.id == id) {
+		if (iterator.uid == id) {
 			return iterator;
 		}
 	}

+ 2 - 2
public/app/pali_sent/get_sim.php

@@ -1,12 +1,12 @@
 <?php
 /*
-get user sentence from db
+获取相似句子列表
  */
 require_once "../config.php";
 require_once "../public/_pdo.php";
 require_once "../public/function.php";
 
-//获取相似句子列表
+//
 
 if (isset($_POST["sent_id"])) {
     $dns = _FILE_DB_PALI_SENTENCE_SIM_;

+ 3 - 1
public/app/pali_sent/pali_sent_list.php

@@ -1,6 +1,8 @@
 <?php
 /*
-get user sentence from db
+获取巴利句子列表
+输入参数
+para: json
  */
 require_once "../config.php";
 require_once "../public/_pdo.php";

+ 2 - 2
public/app/pcdl/reader1.php

@@ -743,8 +743,8 @@ if ($currParaLevel == 1 || $currParaParentLevel == 1) {
     //查询编辑者数量
 
     //查询句子译文内容
-    PDO_Connect(_FILE_DB_SENTENCE_);
-    $dbh = new PDO(_FILE_DB_PALI_SENTENCE_, "", "");
+    PDO_Connect(_FILE_DB_SENTENCE_,_DB_USERNAME_, _DB_PASSWORD_);
+    $dbh = new PDO(_FILE_DB_PALI_SENTENCE_, _DB_USERNAME_, _DB_PASSWORD_);
     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
     //查询channal数量
     switch ($_view) {

+ 15 - 0
public/app/public/snowflakeid.php

@@ -0,0 +1,15 @@
+<?php
+require_once __DIR__.'/../../vendor/autoload.php';
+require_once __DIR__."/../config.php";
+require_once __DIR__."/../setting.php";
+
+class SnowFlakeId{
+	protected $snowflake;
+	function __construct() {
+		$this->snowflake = new \Godruoyi\Snowflake\Snowflake(SnowFlake["DatacenterId"], SnowFlake["WorkerId"]);
+		$this->snowflake->setStartTimeStamp(strtotime(_SnowFlakeDate_)*1000);
+	}
+	public function id(){
+		return $this->snowflake->id();
+	}
+}

+ 4 - 0
public/app/setting.php

@@ -0,0 +1,4 @@
+<?php
+#此配置文件中的内容为各个服务器通用内容。服务器的维护者无需修改。
+
+

+ 1 - 1
public/app/share/function.php

@@ -80,7 +80,7 @@ function share_res_list_get($userid,$res_type=-1){
 				$channelInfo = $channel->getChannal($res["res_id"]);
 				if($channelInfo){
 					$resList[$key]["res_title"]=$channelInfo["name"];
-					$resList[$key]["res_owner_id"]=$channelInfo["owner"];
+					$resList[$key]["res_owner_id"]=$channelInfo["owner_uid"];
 					$resList[$key]["status"]=$channelInfo["status"];
 					$resList[$key]["lang"]=$channelInfo["lang"];
 				}

+ 65 - 83
public/app/studio/dict_updata_wbw.php

@@ -3,27 +3,21 @@ require_once 'checklogin.inc';
 require_once "../public/_pdo.php";
 require_once "../config.php";
 require_once "../redis/function.php";
-
-$redis = redis_connect();
-$input = file_get_contents("php://input");
+require_once "../public/function.php";
 
 $return = "";
 $serverMsg = "";
 
+$redis = redis_connect();
+$input = file_get_contents("php://input");
 $xml = simplexml_load_string($input);
-
-PDO_Connect(_FILE_DB_WBW_);
-PDO_Execute("PRAGMA synchronous = OFF");
-PDO_Execute("PRAGMA journal_mode = WAL");
-PDO_Execute("PRAGMA foreign_keys = ON");
-PDO_Execute("PRAGMA busy_timeout = 5000");
-
 $wordsList = $xml->xpath('//word');
-//$serverMsg+= "word count:".count($wordsList)."<br>";
+
+PDO_Connect(_FILE_DB_WBW_,_DB_USERNAME_,_DB_PASSWORD_);
 
 //remove the same word
 foreach ($wordsList as $ws) {
-    $combine = $ws->pali . $ws->guid . $ws->type . $ws->gramma . $ws->parent . $ws->parent_id . $ws->mean . $ws->factors . $ws->fm . $ws->part_id;
+    $combine = $ws->pali  . $ws->type . $ws->gramma . $ws->parent .  $ws->mean . $ws->factors . $ws->fm;
     $word[$combine] = $ws;
 }
 
@@ -34,80 +28,97 @@ $updateWord = array();
 
 foreach ($word as $x => $ws) {
 	
-    $query = "SELECT id,ref_counter  FROM dict WHERE
-				\"guid\"= ? AND
-				\"pali\"= ? AND
-				\"type\"= ? AND
-				\"gramma\"= ? AND
-				\"mean\"= ? AND
-				\"parent\"= ? AND
-				\"parent_id\"= ? AND
-				\"factors\"= ? AND
-				\"factormean\"= ? AND
-				\"part_id\"= ?" ;
-    $Fetch = PDO_FetchAll($query,array($ws->guid,$ws->pali,$ws->type,$ws->gramma,$ws->mean,$ws->parent,$ws->parent_id,$ws->factors,$ws->fm,$ws->part_id));
+    $query = "SELECT id,ref_counter  FROM "._TABLE_DICT_USER_." WHERE
+				 word = ? AND
+				 type = ? AND
+				 gramma = ? AND
+				 mean = ? AND
+				 base = ? AND
+				 factors = ? AND
+				 factormean = ? AND source = '_USER_DATA_'" ;
+    $Fetch = PDO_FetchAll($query,array($ws->pali,$ws->type,$ws->gramma,$ws->mean,$ws->parent,$ws->factors,$ws->fm));
     $FetchNum = count($Fetch);
 
     if ($FetchNum == 0) {
 		$updateWord["{$ws->pali}"] = 1;
 		//没有找到,新建数据
         //new recorder
-        $params = array($ws->guid,
+        $params = array(
             $ws->pali,
             $ws->type,
             $ws->gramma,
             $ws->parent,
-            $ws->parent_id,
             $ws->mean,
             $ws->note,
             $ws->factors,
             $ws->fm,
-            $ws->part_id,
             $ws->status,
             $ws->language,
-            $UID,
-            time());
+			'_USER_DATA_',
+            mTime());
         array_push($arrInserString, $params);
 
     } else {
+		#查询本人是否有此记录
+		$query = "SELECT id,ref_counter  FROM "._TABLE_DICT_USER_." WHERE
+		word = ? AND
+		type = ? AND
+		gramma = ? AND
+		mean = ? AND
+		base = ? AND
+		factors = ? AND
+		factormean = ? AND user_id = ? " ;
+		$FetchMy = PDO_FetchAll($query,array($ws->pali,$ws->type,$ws->gramma,$ws->mean,$ws->parent,$ws->factors,$ws->fm,$UID));
+		$FetchNumMy = count($FetchMy);
+		if($FetchNumMy==0){
+			$wordId = $Fetch[0]["id"];
+			$ref = $Fetch[0]["ref_counter"] + 1;
+			//更新引用计数
+			$query = "UPDATE dict SET ref_counter= ?  where id = ? ";
+			$stmt = PDO_Execute($query,array($ref,$wordId));
+			if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
+				$error = PDO_ErrorInfo();
+				echo "error" . $error[2] . "<br>";
+			}
+
+			#增加我的记录
+			$params = array(
+				$ws->pali,
+				$ws->type,
+				$ws->gramma,
+				$ws->parent,
+				$ws->mean,
+				$ws->note,
+				$ws->factors,
+				$ws->fm,
+				$ws->status,
+				$ws->language,
+				'_WBW_',
+				mTime());
+			array_push($arrInserString, $params);
+		}
         // "have a same recorder";
-        $wordId = $Fetch[0]["id"];
-        $ref = $Fetch[0]["ref_counter"] + 1;
-        //更新引用计数
-        $query = "UPDATE dict SET ref_counter='$ref' where id=" . $PDO->quote($wordId);
-        $stmt = @PDO_Execute($query);
-        if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
-            $error = PDO_ErrorInfo();
-            echo "error" . $error[2] . "<br>";
-        }
-        //去掉已经有的索引
-        $query = "select count(*)  from user_index where word_index={$wordId} and user_id={$UID}";
-        $num = PDO_FetchOne($query);
-        if ($num == 0) {
-            array_push($arrExistWords, $Fetch[0]["id"]);
-        }
+
+
     }
 }
 /* 开始一个事务,关闭自动提交 */
 $PDO->beginTransaction();
-$query = "INSERT INTO dict ('id',
-						  'guid',
-						  'pali',
+$query = "INSERT INTO "._TABLE_DICT_USER_." (
+						  'word',
 						  'type',
 						  'gramma',
 						  'parent',
-						  'parent_id',
 						  'mean',
 						  'note',
 						  'factors',
 						  'factormean',
-						  'part_id',
 						  'status',
-						  'dict_name',
+						  'source',
 						  'language',
-						  'creator',
-						  'time')
-				   VALUES (null,?,?,?,?,?,?,?,?,?,?,?,?,'user',?,?,?)";
+						  'creator_id',
+						  'create_time')
+				   VALUES (?,?,?,?,?,?,?,?,?,'user',?,?,?)";
 $stmt = $PDO->prepare($query);
 foreach ($arrInserString as $oneParam) {
     $stmt->execute($oneParam);
@@ -121,40 +132,11 @@ if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
     echo "error - $error[2] <br>";
 } else {
 	//成功
-    $count = count($arrInserString);
-    echo "updata $count recorders.";
-    //更新索引表
-
-    $iFirst = $lastid - $count + 1;
-    for ($i = 0; $i < $count; $i++) {
-        array_push($arrExistWords, $iFirst + $i);
-    }
-    if (count($arrExistWords) > 0) {
-        /* 开始一个事务,关闭自动提交 */
-        $PDO->beginTransaction();
-        $query = "INSERT INTO user_index ('id','word_index','user_id','create_time')
-								VALUES (null,?,{$UID},?)";
-        $stmt = $PDO->prepare($query);
-        foreach ($arrExistWords as $oneId) {
-            $stmt->execute(array($oneId, time()));
-        }
-        /* 提交更改 */
-        $PDO->commit();
-        if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
-            $error = PDO_ErrorInfo();
-            echo "error - $error[2] <br>";
-        } else {
-            echo "updata index " . count($arrExistWords) . " recorders.";
-        }
-    } else {
-        echo "updata index 0";
-	}
-	
 	#更新 redis
 	if ($redis != false) {
 		foreach ($updateWord as $key => $value) {
 			# code...
-			$query = "SELECT * from dict where pali = ? ";
+			$query = "SELECT * from "._TABLE_DICT_USER_." where word = ? ";
 			$stmt = $PDO->prepare($query);
 			$stmt->execute(array($key));
 			if ($stmt) {

+ 1 - 1
public/app/studio/index_head.php

@@ -5,7 +5,7 @@ require_once '../public/config.php';
 require_once '../public/load_lang.php';
 ?>
 
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE html>
 <html>
 <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

+ 70 - 3
public/app/studio/js/editor.js

@@ -2148,6 +2148,8 @@ function editor_updataInlineDict(iword, newWord) {
 上传到我的字典
 */
 function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
+	let words = new Array();
+
 	let queryString = "<wordlist>";
 	let x = gXmlBookDataBody.getElementsByTagName("word");
 	let iCount = 0;
@@ -2293,6 +2295,18 @@ function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
 			queryString += "<enable>" + d_enable + "</enable>";
 			queryString += "<language>" + d_language + "</language>";
 			queryString += "</word>";
+			words.push(
+				{
+					word:d_pali,
+					type:d_type,
+					grammar:d_gramma,
+					parent:d_parent,
+					mean:d_mean,
+					factors:d_factors,
+					factormean:d_fm,
+					language:d_language,
+				}
+			)
 			iCount++;
 
 			//formula
@@ -2315,6 +2329,18 @@ function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
 				queryString += "<language>" + d_language + "</language>";
 				queryString += "</word>";
 				iCount++;
+				words.push(
+					{
+						word:"_formula_",
+						type:d_type,
+						grammar:d_gramma,
+						parent:"",
+						mean:formula,
+						factors:"",
+						factormean:"",
+						language:d_language,
+					}
+				);
 			}
 
 			//parent recorder
@@ -2343,6 +2369,18 @@ function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
 				queryString += "<language>" + d_language + "</language>";
 				queryString += "</word>";
 				iCount++;
+				words.push(
+					{
+						word:d_parent,
+						type:d_parentType,
+						grammar:d_parentGramma,
+						parent:"",
+						mean:d_parentmean,
+						factors:fc.join("+"),
+						factormean:fm.join("+"),
+						language:d_language,
+					}
+				);
 			}
 
 			//part recorder
@@ -2372,6 +2410,18 @@ function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
 						queryString += "<language>" + d_language + "</language>";
 						queryString += "</word>";
 						iCount++;
+						words.push(
+							{
+								word:arrPart[iPart],
+								type:".part.",
+								grammar:"",
+								parent:"",
+								mean:arrPartMean[iPart],
+								factors:"",
+								factormean:"",
+								language:d_language,
+							}
+						);
 					}
 				}
 			}
@@ -2382,9 +2432,26 @@ function upload_to_my_dict(wordIdFrom = -1, wordIdTo = -1) {
 	if (iCount == 0) {
 		ntf_show("no word update");
 	} else {
-		$.post("./dict_updata_wbw.php", queryString, function (data, status) {
-			ntf_show("Data: " + data + "\nStatus: " + status);
-		});
+		/*
+		$.post(
+			"./dict_updata_wbw.php", 
+			queryString, 
+			function (data, status) {
+				ntf_show("Data: " + data + "\nStatus: " + status);
+			}
+		);
+		*/
+		$.post(
+			"../api/user_dicts.php", 
+			{
+				op:'create',
+				view:'wbw',
+				data: JSON.stringify(words),
+			}, 
+			function (data, status) {
+				ntf_show("Data: " + data + "\nStatus: " + status);
+			}
+		);
 	}
 }
 

+ 27 - 17
public/app/studio/js/render.js

@@ -1449,7 +1449,7 @@ function renderWordParBlockInner(elementBlock) {
 								paragraph,
 								sent_begin,
 								word_id,
-								iterator.id,
+								iterator.uid,
 								readonly
 							);
 						}
@@ -1607,7 +1607,7 @@ function renderWordParBlockInner(elementBlock) {
 				} else {
 					readonly = false;
 				}
-				output += render_tran_sent_block(book, paragraph, sent_begin, word_id, iterator.id, readonly);
+				output += render_tran_sent_block(book, paragraph, sent_begin, word_id, iterator.uid, readonly);
 			}
 		}
 	}
@@ -1817,7 +1817,13 @@ function render_tran_sent_block(book, para, begin, end, channal = 0, readonly =
 	let sChannalName = "";
 	let sent_text = "";
 	let sent_lang = "en";
-	let objSent;
+	let objSent = {
+                text:"",
+                language:"en",
+                id:"",
+                tag:"[]",
+                author:"{}"
+            };
 	let thischannal;
 	let shell_class = "";
 	if (channal == 0) {
@@ -1837,12 +1843,13 @@ function render_tran_sent_block(book, para, begin, end, channal = 0, readonly =
 		objSent = _user_sent_buffer.getSentText(book, para, begin, end, channal);
 		thischannal = channal_getById(channal);
 		if (objSent == false) {
-			objSent = new Object();
-			objSent.text = "";
-			objSent.language = thischannal.lang;
-			objSent.id = "";
-			objSent.tag = "[]";
-			objSent.author = "{}";
+			objSent = {
+                text:"",
+                language:thischannal.lang,
+                id:"",
+                tag:"[]",
+                author:"{}"
+            };
 			sent_text = "";
 		} else {
 			sent_text = objSent.text;
@@ -1908,14 +1915,17 @@ function render_tran_sent_block(book, para, begin, end, channal = 0, readonly =
 		output += "<span id='" + id + "' ";
 		output += "onclick=\"sent_edit_click('";
 		output += book + "','" + para + "','" + begin + "','" + end + "','" + channal + "',)\">";
-		if (objSent.text == null || objSent.text == "") {
-			output += "<span style='color:gray;'>";
-			output += "<svg class='icon' style='fill: var(--detail-color);'>";
-			output += "<use xlink='http://www.w3.org/1999/xlink' href='svg/icon.svg#ic_mode_edit'>";
-			output += "</span>";
-		} else {
-			output += note_init(term_std_str_to_tran(objSent.text, channal, getCookie("userid"), sent_lang));
-		}
+        if(typeof objSent !== 'undefined'){
+            if (objSent.text == null || objSent.text == "") {
+                output += "<span style='color:gray;'>";
+                output += "<svg class='icon' style='fill: var(--detail-color);'>";
+                output += "<use xlink='http://www.w3.org/1999/xlink' href='svg/icon.svg#ic_mode_edit'>";
+                output += "</span>";
+            } else {
+                output += note_init(term_std_str_to_tran(objSent.text, channal, getCookie("userid"), sent_lang));
+            }            
+        }
+
 
 		output += "</span>";
 	}

+ 3 - 3
public/app/studio/js/wizard.js

@@ -435,9 +435,9 @@ function loadUserWBWList(){
 		let html ="";
 		for (const it of data) {
 			html += "<div class='file_list_row'>";
-			link = "<a href='./editor.php?op=openchannel&book="+it.book+"&par="+it.paragraph+"&channel="+it.channal+"' target='_blank'>";
-			html += "<div style='flex:5;'>"+link+it.book+"-"+it.paragraph+"</a></div>";
-			html += "<div style='flex:2;'>"+getDataTime(it.modify_time)+"</div>";
+			link = "<a href='./editor.php?op=openchannel&book="+it.book+"&par="+it.paragraph+"&channel="+it.channel_uid+"' target='_blank'>";
+			html += "<div style='flex:5;'>"+link+it.book_id+"-"+it.paragraph+"</a></div>";
+			html += "<div style='flex:2;'>"+it.updated_at+"</div>";
 			html += "</div>"
 		}
 		$("#file_list").html(html);

+ 9 - 10
public/app/studio/pc_get_word_num.php

@@ -13,18 +13,17 @@ PDO_Connect(_FILE_DB_PALICANON_TEMPLET_);
 if ($get_par_end == -1 || ($get_par_end - $get_par_begin) > 50000) {
     echo "0,0,0,0";
     exit;
-} else 
-{
-    $query1 = "SELECT count(*) FROM "._TABLE_PALICANON_TEMPLET_." WHERE book = $get_book and  paragraph BETWEEN $get_par_begin AND $get_par_end";
-    $query2 = "SELECT count(*) FROM (SELECT count(*),real FROM "._TABLE_PALICANON_TEMPLET_." WHERE book = $get_book and (paragraph BETWEEN $get_par_begin AND $get_par_end ) group by real ) T";
+} else {
+    $query1 = "SELECT count(*) FROM "._TABLE_PALICANON_TEMPLET_." WHERE book = ? and (paragraph BETWEEN $get_par_begin AND $get_par_end)";
+    $query2 = "SELECT count(*) FROM (SELECT count(*) FROM "._TABLE_PALICANON_TEMPLET_." WHERE book=? and (paragraph BETWEEN $get_par_begin AND $get_par_end ) group by real ) T";
 
-    $query3 = "SELECT sum(length(real)) FROM "._TABLE_PALICANON_TEMPLET_." WHERE book = $get_book and paragraph BETWEEN $get_par_begin AND $get_par_end";
-    $query4 = "SELECT sum(length(real)) FROM (SELECT count(*),real FROM "._TABLE_PALICANON_TEMPLET_." WHERE book = $get_book and (paragraph BETWEEN $get_par_begin AND $get_par_end ) group by real ) T";
+    $query3 = "SELECT sum(length(real)) FROM "._TABLE_PALICANON_TEMPLET_." WHERE book=? and  (paragraph BETWEEN $get_par_begin AND $get_par_end)";
+    $query4 = "SELECT sum(length(real)) FROM (SELECT count(*),real FROM "._TABLE_PALICANON_TEMPLET_." WHERE book=? and (paragraph BETWEEN $get_par_begin AND $get_par_end ) group by real ) T";
 
-    $allword = PDO_FetchOne($query1);
-    $allword_token = PDO_FetchOne($query2);
-    $allwordLen = PDO_FetchOne($query3);
-    $allword_tokenLen = PDO_FetchOne($query4);
+    $allword = PDO_FetchOne($query1,array($get_book));
+    $allword_token = PDO_FetchOne($query2,array($get_book));
+    $allwordLen = PDO_FetchOne($query3,array($get_book));
+    $allword_tokenLen = PDO_FetchOne($query4,array($get_book));
 
     echo $allword . "," . $allword_token . "," . $allwordLen . "," . $allword_tokenLen;
 }

+ 99 - 25
public/app/studio/project.php

@@ -12,14 +12,20 @@
 <?php
 //工程文件操作
 //建立,
-require_once '../config.php';
-require_once "../public/_pdo.php";
-require_once "../public/function.php";
-require_once "../public/load_lang.php";
-require_once "./book_list_en.inc";
-require_once "../ucenter/function.php";
-require_once "../ucenter/setting_function.php";
-require_once "../lang/function.php";
+require_once __DIR__.'/../config.php';
+require_once __DIR__."/../public/_pdo.php";
+require_once __DIR__."/../public/function.php";
+require_once __DIR__."/../public/load_lang.php";
+require_once __DIR__."/./book_list_en.inc";
+require_once __DIR__."/../ucenter/function.php";
+require_once __DIR__."/../ucenter/setting_function.php";
+require_once __DIR__."/../lang/function.php";
+require_once __DIR__."/../redis/function.php";
+require_once __DIR__."/../channal/function.php";
+require_once __DIR__."/../public/snowflakeid.php";
+
+# 雪花id
+$snowflake = new SnowFlakeId();
 
 $user_setting = get_setting();
 
@@ -47,6 +53,10 @@ if ($_COOKIE["uid"]) {
     echo '<a href="../ucenter/index.php" target="_blank">' . $_local->gui->not_login . '</a>';
     exit;
 }
+
+$channelClass = new Channal(redis_connect());
+$channelInfo = $channelClass->getChannal($_POST['channal']);
+
 switch ($op) {
     case "create":
         //判断单词数量 太大的不能加载
@@ -149,7 +159,22 @@ switch ($op) {
                                     }
                                     $block_id = UUID::v4();
                                     $trans_block_id = UUID::v4();
-                                    $block_data[] = array($block_id, "", $_POST["channal"], $USER_ID, $book, $iPar, "_none_", $_POST["lang"], 1);
+                                    $block_data[] = array
+									(
+										$snowflake->id(),
+										$block_id, 
+										"", 
+										$_POST["channal"], 
+										$_COOKIE['userid'], 
+										$_COOKIE['uid'], 
+										$book, 
+										$iPar, 
+										"_none_", 
+										$channelInfo["lang"],
+										$channelInfo["status"],
+										mTime(),
+										mTime()
+									);
                                     $block_list[] = array("channal" => $_POST["channal"],
                                         "type" => 6, //word by word
                                         "book" => $res_book,
@@ -185,7 +210,22 @@ switch ($op) {
                                         $strXml .= "<style>{$result["style"]}</style>";
                                         $strXml .= "<status>0</status>";
                                         $strXml .= "</word>";
-                                        $wbw_data[] = array(UUID::v4(), $block_id, $book, $iPar, $result["wid"], $result["real"], $strXml, mTime(), mTime(), 1, $USER_NAME);
+                                        $wbw_data[] = array
+										(
+											$snowflake->id(),
+											UUID::v4(), 
+											$block_id, 
+											$book, 
+											$iPar, 
+											$result["wid"], 
+											$result["real"], 
+											$strXml, 
+											mTime(), 
+											mTime(), 
+											$channelInfo["status"], 
+											$_COOKIE['userid'],
+											$_COOKIE['uid']
+										);
                                     }
                                 }
                             }
@@ -193,9 +233,26 @@ switch ($op) {
                             //写入数据库
                             // 开始一个事务,关闭自动提交
 
-                            PDO_Connect(_FILE_DB_USER_WBW_);
+                            PDO_Connect(_FILE_DB_USER_WBW_,_DB_USERNAME_,_DB_PASSWORD_);
                             $PDO->beginTransaction();
-                            $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." ('id','parent_id','channal','owner','book','paragraph','style','lang','status','modify_time','receive_time') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+
+                            $query = "INSERT INTO "._TABLE_USER_WBW_BLOCK_." 
+									( 
+										id,
+										uid , 
+										parent_id , 
+										channel_uid , 
+									 	creator_uid , 
+										editor_id,
+										book_id , 
+										paragraph , 
+									  	style , 
+									  	lang , 
+									  	status , 
+									  	create_time ,
+									  	modify_time 
+									) 
+									  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
                             $stmt = $PDO->prepare($query);
                             foreach ($block_data as $oneParam) {
                                 $stmt->execute($oneParam);
@@ -213,7 +270,23 @@ switch ($op) {
                             // 开始一个事务,关闭自动提交
 
                             $PDO->beginTransaction();
-                            $query = "INSERT INTO "._TABLE_USER_WBW_." ('id','block_id','book','paragraph','wid','word','data','modify_time','receive_time','status','owner') VALUES (?,?,?,?,?,?,?,?,?,?,?)";
+                            $query = "INSERT INTO "._TABLE_USER_WBW_." 
+										( 
+										  id,
+										  uid , 
+										  block_uid , 
+										  book_id , 
+										  paragraph , 
+										  wid , 
+										  word , 
+										  data , 
+										  create_time , 
+										  modify_time , 
+										  status , 
+										  creator_uid ,
+										  editor_id
+										)
+										  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
                             $stmt = $PDO->prepare($query);
                             foreach ($wbw_data as $oneParam) {
                                 $stmt->execute($oneParam);
@@ -330,15 +403,15 @@ switch ($op) {
                 echo "<fieldset>";
                 echo "<legend>{$_local->gui->channel} ({$_local->gui->required})</legend>";
                 echo "<div>";
-                PDO_Connect(_FILE_DB_CHANNAL_);
-                $query = "select * from channal where owner = '{$_COOKIE["userid"]}'   limit 0,100";
-                $Fetch = PDO_FetchAll($query);
+                PDO_Connect(_FILE_DB_CHANNAL_,_DB_USERNAME_,_DB_PASSWORD_);
+                $query = "SELECT uid,name,lang,status,create_time from "._TABLE_CHANNEL_." where owner_uid = ?  limit 100";
+                $Fetch = PDO_FetchAll($query,array($_COOKIE["userid"]));
                 $i = 0;
                 foreach ($Fetch as $row) {
                     echo '<div class="file_list_row" style="padding:5px;">';
 
                     echo '<div class="pd-10"  style="max-width:2em;flex:1;">';
-                    echo '<input name="channal" value="' . $row["id"] . '" ';
+                    echo '<input name="channal" value="' . $row["uid"] . '" ';
                     if ($i == 0) {
                         echo "checked";
                     }
@@ -347,24 +420,25 @@ switch ($op) {
                     echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["name"] . '</div>';
                     echo '<div class="title" style="flex:3;padding-bottom:5px;">' . $row["lang"] . '</div>';
                     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-                    PDO_Connect( _FILE_DB_USER_WBW_);
-                    $query = "select count(*) from "._TABLE_USER_WBW_BLOCK_." where channal = '{$row["id"]}' and book='{$book}' and paragraph in {$strQueryParaList}  limit 0,100";
-                    $FetchWBW = PDO_FetchOne($query);
+                    PDO_Connect( _FILE_DB_USER_WBW_,_DB_USERNAME_,_DB_PASSWORD_);
+                    $query = "SELECT count(*) from "._TABLE_USER_WBW_BLOCK_." where channel_uid = ? and book_id= ? and paragraph in {$strQueryParaList}  limit 100";
+                    $FetchWBW = PDO_FetchOne($query,array($row["uid"],$book));
                     echo '</div>';
                     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
                     if ($FetchWBW == 0) {
                         echo $_local->gui->blank;
-                        echo "&nbsp;<a></a>";//快捷编辑?
+                        echo "&nbsp;<a></a>";//??
                     } else {
+						#打开编辑窗口
                         echo $FetchWBW . $_local->gui->para;
-                        echo "&nbsp;<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["id"]}'>{$_local->gui->open}</a>";
+                        echo "&nbsp;<a href='../studio/editor.php?op=openchannal&book=$book&para={$paraList}&channal={$row["uid"]}'>{$_local->gui->open}</a>";
                     }
                     echo '</div>';
 
                     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
-                    PDO_Connect( _FILE_DB_SENTENCE_);
-                    $query = "select count(*) from sentence where channal = '{$row["id"]}' and book='{$book}' and paragraph in {$strQueryParaList}  limit 0,100";
-                    $FetchWBW = PDO_FetchOne($query);
+                    PDO_Connect( _FILE_DB_SENTENCE_,_DB_USERNAME_,_DB_PASSWORD_);
+                    $query = "SELECT count(*) from "._TABLE_SENTENCE_." where channel_uid = ? and book_id = ? and paragraph in {$strQueryParaList}  limit 100";
+                    $FetchWBW = PDO_FetchOne($query,array($row["uid"],$book));
                     echo '</div>';
                     echo '<div class="title" style="flex:2;padding-bottom:5px;">';
                     if ($FetchWBW == 0) {

Некоторые файлы не были показаны из-за большого количества измененных файлов