+
    Oj                     :   ^ RI HtHtHtHtHt ^ RIHt ^ RIH	t	 ^ RI
Ht ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHt ]! ]4      t]! ]RR	R
R.R. ROR. RORR//R7       ]	! ]]R.RR7      t]P<                  P?                  ]P<                  PA                  ]!4      R4      t"]P<                  P?                  ]P<                  PA                  ]!4      R4      t#]P<                  P?                  ]P<                  PA                  ]!4      R4      t$0 Rmt%Rt&]$]PN                  R&   ]&]PN                  R&   / t(])! R]" 24       ])! R]# 24       ]PT                  R 4       t+]PX                  R  4       t-]P]                  ]/4      R! 4       t0R" t1R# t2R$ t3R% t4R& t5R' t6RR) lt7R* t8RR+ lt9RR, lt:R- t;R. t<R/ t=R0 t>R1 t?R2 t@]P                  R3R.R47      R5 4       tB]P                  R6R.R47      R7 4       tC]P                  R8R.R47      R9 4       tDR: tE]P                  R3R.R47      R; 4       tF]P                  R8R.R47      R< 4       tG]P                  R8R.R47      R= 4       tH]P                  R>R.R47      R? 4       tI]P                  R>R.R47      R@ 4       tJ]P                  RAR.R47      RB 4       tK]P                  RAR.R47      RC 4       tL]P                  RDR.R47      RE 4       tM]P                  RFR.R47      RG 4       tN]P                  RHR.R47      RI 4       tO]P                  RDR.R47      RJ 4       tP]P                  RFR.R47      RK 4       tQ]P                  RFR.R47      RL 4       tR]P                  RMR.R47      RN 4       tS]P                  ROR.R47      RP 4       tT]P                  RQR.R47      RR 4       tU]P                  RSR.R47      RT 4       tV]P                  RSR.R47      RU 4       tW]P                  RVR.R47      ]P                  RW4      RX 4       4       tY]P                  RYR.R47      RZ 4       tZ]P                  R[R.R47      R\ 4       t[]P                  R]R.R47      R^ 4       t\]P                  R_R.R47      R` 4       t]]P                  RaR.R47      Rb 4       t^]P                  RcR.R47      Rd 4       t_]P                  RcR.R47      Re 4       t`Rf taRRg ltb]P                  RhR.R47      ]P                  Ri4      Rj 4       4       tc]P                  Rk4      Rl 4       tdRm teRn tfRo tgRp th]P                  RqR.R47      Rr 4       ti]P                  RsR.R47      ]P                  Ri4      Rt 4       4       tjRu tk]P                  RvR.R47      Rw 4       tl]P                  RxR.R47      Ry 4       tm]P                  RzR.R47      R{ 4       tn]P                  R|R.R47      R} 4       to]P                  R~R.R47      R 4       tp]P                  R~R.R47      R 4       tq]P                  RR.R47      R 4       tr]P                  RR.R47      R 4       ts]P                  RR.R47      R 4       tt]P                  RR.R47      R 4       tu]P                  RR.R47      R 4       tv]P                  RR.R47      R 4       tw]P                  RR.R47      R 4       tx]R8X  dB   ])! R4       ]2! 4        ]y! ];! RR4      4      tz])! R]z R24       ]P                  R]zRR(R7       R# R# )    )Flaskrequestjsonifysend_from_directorymake_response)CORS)Limiter)get_remote_addressN)secure_filename)Imagez/*originshttp://localhost:8080http://127.0.0.1:8080methodsGETPOSTPUTDELETEallow_headerssupports_credentialsT)	resourcesz100 per minutez	memory://)appdefault_limitsstorage_uriz../database/app.dbz../database/schema.sqlz
../uploadsUPLOAD_FOLDERMAX_CONTENT_LENGTHzDatabase path: zSchema path: c                      \         P                  R 8X  d]   \        P                  4       p V P                  p\         P                  P                  R4      pV'       d   W!R&   RVR&   RVR&   RVR&   V # R	# )
OPTIONSOriginAccess-Control-Allow-OriginGET, POST, PUT, DELETE, OPTIONSAccess-Control-Allow-Methods;Content-Type, Authorization, Cache-Control, Pragma, ExpiresAccess-Control-Allow-Headers3600zAccess-Control-Max-AgeN)r   methodr   make_default_options_responseheadersget)responser(   origins      app.pyhandle_optionsr-   2   sr    ~~"446""$$X.5;122S./2o./,2() #    c                     \         P                  P                  R 4      pV'       dC   VR9   d<   WP                  R&   RV P                  R&   RV P                  R&   RV P                  R&   V # )	r   r    r!   r"   r#   r$   true Access-Control-Allow-Credentialsr   r   )r   r(   r)   )r*   r+   s   & r,   add_cors_headersr3   ?   sh    __  *F&NN:@67;\78;x78?E;<Or.   c                    \        R \        V 4      /4      pRVn        \        P                  P                  R4      pV'       dC   VR
9   d<   W!P                  R&   RVP                  R&   RVP                  R&   RVP                  R	&   V# )error  r   r    r!   r"   r#   r$   r0   r1   r2   )r   strstatus_coder   r(   r)   )er*   r+   s   &  r,   handle_exceptionr:   I   s    Q()HH__  *F&NN:@67;\78;x78?E;<Or.   c                  d    \         P                  ! \        4      p \         P                  V n        V # N)sqlite3connectDATABASE_PATHRowrow_factory)conns    r,   get_dbrC   U   s!    ??=)D{{DKr.   c                     \        R 4       \        P                  P                  \        4      p \        P                  P                  V 4      '       g%   \        P                  ! V 4       \        RV  24       \        P                  P                  \        4      '       g   \        R4       \        4       p\        \        RRR7      ;_uu_ 4       pVP                  4       pRRR4       VP                  X4       VP                  4        VP                  4        \        R4       R# \        R4       R#   + '       g   i     L[; i)	Initializing database...zCreated directory: u'   数据库不存在，创建新数据库rutf-8)encodingNu   数据库初始化成功u$   数据库已存在，跳过初始化)printospathdirnamer?   existsmakedirsrC   openSCHEMA_PATHreadexecutescriptcommitclose)db_dirrB   fschemas       r,   init_dbrX   Z   s    	
$%WW__]+F77>>&!!
F#F8,-77>>-((78x+sW55VVXF 66"

()45 65s   D44E	c                  .    \         P                  ! ^ 4      # )    )secretstoken_urlsafe r.   r,   generate_tokenr^   m   s      $$r.   c                     V '       g   R # \        4       pVP                  4       pVP                  RV 34       VP                  4       pVP	                  4        V'       g   R # \        V4      p\        V4      VR&   V# )Nz
        SELECT u.* FROM users u
        JOIN sessions s ON u.id = s.user_id
        WHERE s.token = ? AND s.expires_at > datetime('now')
    location)rC   cursorexecutefetchonerT   dictbuild_location)tokenrB   ra   rowusers   &    r,   get_user_from_tokenri   p   sl    8D[[]F
NN  	
 //
CJJL9D%d+DKr.   c                     V '       g   R # \        4       pVP                  4       pVP                  RV 34       VP                  4       pVP	                  4        V'       d
   VR,          # R # )Nz
        SELECT u.id FROM users u
        JOIN sessions s ON u.id = s.user_id
        WHERE s.token = ? AND s.expires_at > datetime('now')
    idrC   ra   rb   rc   rT   rf   rB   ra   rg   s   &   r,   get_user_id_from_tokenrn      sZ    8D[[]F
NN  	
 //
CJJL3t9%%r.   c                 v    V '       g   R # ^ RI pVP                  RR V 4      p V P                  4       p V R,          # ) Nz[%_\\]:Nd   N)resubstrip)termrr   s   & r,   sanitize_search_termrv      s2    66)R&D::<D:r.   Fc                 "   . pV P                  R 4      '       d   VP                  V R ,          4       V P                  R4      '       dw   VP                  V R,          4       V P                  R4      '       dH   VP                  V R,          4       V P                  R4      '       d   VP                  V R,          4       V'       d0   V P                  R4      '       d   VP                  V R,          4       V'       d   RP                  V4      # R# )provincecitydistrictstreetdetail_location/N)r)   appendjoin)datainclude_detaillocation_partss   && r,   re   re      s    Nxx
d:./88F!!$v,/xx
##%%d:&6788H%%"))$x.9$((#455d#456'5388N#?4?r.   c                     \        V4      pV'       g   R . 3# RRP                  R V  4       4      ,           R,           pRV R2.\        V 4      ,          pW43# )rp   z AND (z OR c              3   *   "   T F	  q R 2x  K  	  R# 5i)z LIKE ?Nr]   ).0rV   s   & r,   	<genexpr>*build_search_conditions.<locals>.<genexpr>   s     'Fv!#Wvs   )%)rv   r   len)fieldssearch_term	sanitized
conditionsvaluess   &&   r,   build_search_conditionsr      sY    $[1I2vFKK'Fv'FFFLJ)A#f+-Fr.   c                 $    \        R RRV /4      V3# )successFr5   r   )messager8   s   &&r,   error_responser      s    Iugw78+EEr.   c                 4    R RRV /pVe   WR&   \        V4      # )r   Tr   r   r   )r   r   r*   s   && r,   success_responser      s)    4G4H8r.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       d
   VR,          # V# )z;SELECT config_value FROM system_config WHERE config_key = ?config_valuerl   )
config_keydefault_valuerB   ra   rg   s   &&   r,   get_config_valuer      sP    8D[[]F
NNPS]R_`
//
CJJL
>""r.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       ^ ,          pVP	                  4        V# )z
        SELECT COUNT(*) FROM tasks 
        WHERE publisher_id = ? AND status IN ('pending', 'in_progress') AND deleted_at IS NULL
    rl   user_idrB   ra   counts   &   r,   get_user_pending_tasks_countr      M    8D[[]F
NN   OOa EJJLLr.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       ^ ,          pVP	                  4        V# )zy
        SELECT COUNT(*) FROM tasks 
        WHERE acceptor_id = ? AND status = 'in_progress' AND deleted_at IS NULL
    rl   r   s   &   r,   get_user_accepted_tasks_countr      r   r.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       ^ ,          pVP	                  4        V# )zISELECT COUNT(*) FROM skills WHERE publisher_id = ? AND deleted_at IS NULLrl   r   s   &   r,   get_user_skills_countr      sF    8D[[]F
NN^ah`jkOOa EJJLLr.   c                 $   \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       d;   VR,          ^ 8  d-   \        VR,          VR,          ,          ^d,          4      pV R2# R# )z
        SELECT
            COUNT(*) as total,
            SUM(CASE WHEN rating = 'good' THEN 1 ELSE 0 END) as positive_count
        FROM task_ratings
        WHERE acceptor_id = ?
    totalpositive_countr   -)rC   ra   rb   rc   rT   round)r   rB   ra   rg   rates   &    r,   get_user_rating_rater      s~    8D[[]F
NN   //
CJJL
s7|ac*+c'l:cABqzr.   c                    V '       g   / # \        4       pVP                  4       pR P                  R.\        V 4      ,          4      pVP	                  RV R2V 4       VP                  4       pVP                  4        / pV FS  pVR,          ^ 8  d8   \        VR,          VR,          ,          ^d,          4      pV R2WVR,          &   KH  RWVR,          &   KU  	  V  F  pW9  g   K  RWX&   K  	  V# )	,?z
        SELECT
            acceptor_id,
            COUNT(*) as total,
            SUM(CASE WHEN rating = 'good' THEN 1 ELSE 0 END) as positive_count
        FROM task_ratings
        WHERE acceptor_id IN (z#)
        GROUP BY acceptor_id
    r   r   r   acceptor_idr   )rC   ra   r   r   rb   fetchallrT   r   )	user_idsrB   ra   placeholdersrows
rating_maprg   r   r   s	   &        r,   get_bulk_user_rating_ratesr      s    	8D[[]F88SECM12L
NN   ,n - 
 ??DJJLJw<!#./#g,>#EFD04vQZJ=)*-0J=)*  $"%J  r.   z
/api/tasks)r   c            
      6   \         P                  P                  R 4      p \         P                  P                  R4      p\         P                  P                  R4      p\        \         P                  P                  R^4      4      p\        \         P                  P                  R^
4      4      pV^,
          V,          p\	        4       pVP                  4       pRpRp	. p
. pV '       d<   V R8w  d5   VR,          pV	R,          p	V
P                  V 4       VP                  V 4       \         P                  P                  R	4      pV'       d   V'       d   VP                  R
4      '       d   VP                  R4      ^,          p\        V4      pV'       d   VR8X  d6   VR,          pV	R,          p	V
P                  V4       VP                  V4       MsVR8X  dm   VR,          pV	R,          p	V
P                  V4       VP                  V4       VR,          pV	R,          p	V
P                  RR.4       VP                  RR.4       V'       dO   . ROp\        W4      w  ppV'       d5   VV,          pV	V,          p	V
P                  V4       VP                  V4       VP                  W4       VP                  4       ^ ,          pVR,          pV
P                  WE.4       VP                  W4       VP                  4       p\!        \#        R V 4       4      4      p\%        V4      p. pV FK  p\'        V4      pVP                  VR,          R4      VR&   \)        VRR7      VR&   VP                  V4       KM  	  VP+                  4        \-        RVRVRVRV/4      # )statustypesearchpagelimitz
        SELECT t.*, u.phone as publisher_phone
        FROM tasks t LEFT JOIN users u ON t.publisher_id = u.id 
        WHERE t.deleted_at IS NULL
    z3SELECT COUNT(*) FROM tasks WHERE deleted_at IS NULLallz AND status = ?AuthorizationBearer  	publishedz AND publisher_id = ?acceptedz AND acceptor_id = ?z AND status IN (?, ?)in_progress	completed* ORDER BY created_at DESC LIMIT ? OFFSET ?c              3   T   "   T F  qR ,          '       g   K  VR ,          x  K   	  R# 5ipublisher_idNr]   r   rg   s   & r,   r   get_tasks.<locals>.<genexpr>T  #     XDSDWDW0S00D   ((r   r   publisher_rating_rateTr   r`   itemsr   titledescriptionrx   ry   rz   r{   )r   argsr)   intrC   ra   r~   r(   
startswithsplitrn   extendr   rb   rc   r   listsetr   rd   re   rT   r   )r   
type_paramr   r   r   offsetrB   ra   querycount_queryparamscount_paramsauth_headerrf   current_user_idsearch_fieldssearch_condsearch_paramsr   r   publisher_idsr   r   rg   tasks                            r,   	get_tasksr     s   \\h'F!!&)J\\h'Fw||*+D  "-.EQh%F8D[[]FE
 HKFL&E/""((fF#//%%o6Kkk&<&<Y&G&G!!#&q)07[(0066o.##O4z)//55o.##O40066}k:;##]K$@AZ%<]%S"][ E;&KMM-(. NN;-OOa E	99E
MM5/"
NN5!??DXDXXYM+M:JECy(2s>7JC(P$%)$tDZT	  	JJL	  r.   z/api/tasks/countc                  b   \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR4      # V P                  R4      ^,          p\        V4      pV'       g   \	        RR4      # \        \        RR4      4      p\        V4      p\        RVR	V/4      # )
r   r   	   未登录  r      登录已过期max_publish_tasks3r   max)r   r(   r)   r   r   r   rn   r   r   r   r   )r   rf   r   max_publishcurrent_counts        r,   get_task_countr   g  s    //%%o6Kk44Y??k3//c"1%E$U+G/55&':C@AK09MG]E;?@@r.   z/api/tasks/<int:task_id>c                    \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        R4      # \        V4      p\        VRR7      VR&   \        V4      # )a  
        SELECT t.*, u.nickname as acceptor_name, u.phone as acceptor_phone, u.avatar as acceptor_avatar,
               r.rating as task_rating, r.comment as task_rating_comment, r.created_at as rating_created_at
        FROM tasks t 
        LEFT JOIN users u ON t.acceptor_id = u.id 
        LEFT JOIN task_ratings r ON t.id = r.task_id
        WHERE t.id = ? AND t.deleted_at IS NULL
       任务不存在Tr   r`   	rC   ra   rb   rc   rT   r   rd   re   r   )task_idrB   ra   rg   results   &    r,   get_taskr   x  sv    8D[[]F
NN   //
CJJL/00#YF'tDF:6?r.   c                      \         P                   P                  V R 4      p\         P                   P                  4       pW8  #   \         d   p\	        RT 24        Rp?R# Rp?ii ; i)z%Y-%m-%d %H:%Mu   时间验证失败: NF)datetimestrptimenow	ExceptionrI   )task_time_str	task_timecurrent_timer9   s   &   r,   validate_task_timer    s`    %%..}>NO	((,,.'' $QC()s   AA A(A##A(c                  f   \         P                  p \        4       pVP                  4       pV P	                  R 4      pV'       d-   \        V4      '       g   VP                  4        \        R4      # \         P                  P	                  R4      pRpV'       d   VP                  R4      '       d   VP                  R4      ^,          pVP                  RV34       VP                  4       pV'       dy   VR,          ^8w  d   VP                  4        \        RR	4      # VR
,          p\        \        RR4      4      p\        V4      p	W8  d    VP                  4        \        RV R24      # VP                  RV P	                  R4      V P	                  R4      V P	                  R4      V P	                  R4      V P	                  R4      V P	                  R4      V P	                  R4      V P	                  R 4      V P	                  R4      VV P	                  R4      V P	                  R4      V P	                  RR4      V P	                  RR4      34       VP                   p
VP#                  4        VP                  RV
34       VP                  4       pVP                  4        \%        \'        V4      4      # )time$   任务时间必须晚于当前时间r   Nr   r   z
            SELECT u.id, u.enabled FROM users u
            JOIN sessions s ON u.id = s.user_id
            WHERE s.token = ? AND s.expires_at > datetime('now')
        enabledu'   账户已被禁用，无法发布任务  rk   r   r   u(   待处理+进行中的任务数最多为   个，暂时无法发布z
        INSERT INTO tasks (title, description, province, city, district, street, detail_location, time, reward, publisher_id, publisher_name, contact, status, type)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    r   r   rx   ry   rz   r{   r|   rewardpublisher_namecontactr   pendingr   r   z SELECT * FROM tasks WHERE id = ?)r   jsonrC   ra   r)   r  rT   r   r(   r   r   rb   rc   r   r   r   	lastrowidrS   r   rd   )r   rB   ra   r   r   r   rf   rh   r   r   r   created_tasks               r,   create_taskr    s4   <<D8D[[]F I!),,JJL!"HII//%%o6KL{--i88!!#&q)  X		
  I!#

%&OQTUU:L./BCHIK8FM+

%(PQ\P]]u&vww
NN  	"#!"9%%
( GKKM NN5zB??$LJJL4%&&r.   c                    \         P                  p\        4       pVP                  4       pVP	                  R V 34       VP                  4       pV'       g   VP                  4        \        R4      # RV9   d4   \        VR,          4      '       g   VP                  4        \        R4      # . p. pRV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R	4       VP                  VR,          4       R
V9   d*   VP                  R4       VP                  VR
,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   d*   VP                  R4       VP                  VR,          4       RV9   Ed   VP                  R4       VP                  VR,          4       VR,          R>9   d#   VP                  R4       VP                  R4       VR,          R8X  d   RV9   d{   VR,          pV'       g5   VP	                  R V 34       VP                  4       pV'       d
   VR,          pVP	                  R!V VR",          VVR,          VP                  R#R$4      34       VR,          R%8X  Ed   \         P                  P                  R&4      p	V	'       Ed   V	P                  R'4      '       Edj   V	P                  R(4      ^,          p
VP	                  R)V
34       VP                  4       pV'       Ed&   VR*,          ^8w  d   VP                  4        \        R+R,4      # VR-,          pVR.,          pVR/,          pVR0,          p\        \        R1R24      4      p\!        V4      pVV8  d    VP                  4        \        R3V R424      # VP                  R4       VP                  V4       VP                  R54       VP                  V4       VP                  R64       VP                  \"        P"                  P%                  4       P'                  R74      4       R8V9   d*   VP                  R94       VP                  VR8,          4       V'       dI   VP                  V 4       R:R;P)                  V4       R<2pVP	                  VV4       VP+                  4        VP	                  R V 34       VP                  4       pVP                  4        V'       g   \        R=4      # \-        \/        V4      4      # )?z7SELECT * FROM tasks WHERE id = ? AND deleted_at IS NULLr   r  r  r   title=?r   description=?rx   
province=?ry   city=?rz   
district=?r{   street=?r|   zdetail_location=?ztime=?r  zreward=?r	  publisher_name=?r
  	contact=?r   zstatus=?zacceptor_id=?Nr   ratingr   z6SELECT acceptor_id FROM task_ratings WHERE task_id = ?z
                    INSERT OR REPLACE INTO task_ratings 
                    (task_id, publisher_id, acceptor_id, rating, comment)
                    VALUES (?, ?, ?, ?, ?)
                r   rating_commentrp   r   r   r   r   z
                    SELECT u.id, u.enabled, u.nickname, u.phone, u.avatar FROM users u
                    JOIN sessions s ON u.id = s.user_id
                    WHERE s.token = ? AND s.expires_at > datetime('now')
                r  u'   账户已被禁用，无法承接任务r  rk   nicknamephoneavatarmax_accept_tasksr   u   已承接的任务数最多为u   个，暂时无法承接zacceptor_name=?zaccept_time=?%Y-%m-%d %H:%M:%Sr   ztype=?zUPDATE tasks SET ,  WHERE id=?   任务不存在或已删除)r  	cancelled)r   r  rC   ra   rb   rc   rT   r   r  r~   r)   r(   r   r   r   r   r   r   r   strftimer   rS   r   rd   )r   r   rB   ra   existing_taskupdate_fieldsupdate_valuesr   existing_ratingr   rf   rh   acceptor_nameacceptor_phoneacceptor_avatar
max_acceptr   r   updated_tasks   &                  r,   update_taskr.    s?   <<D8D[[]F
NNLwjYOO%M

/00~!$v,//JJL!"HIIMM$Y'T']+_-T-01T\*T*-.~X&T&\*T\*T*-.4Z(T(^,D 01T"345~X&T&\*4Z(T(^,4/0T"234D[)T)_-4Z(T(^,>55  1  &>[(4+M:"NN#[^e]gh&,oo&7O&&5m&D  
 !.1NHH-r2	
 >]*!//--o>K{{55i@@#))#.q1   X	
 (4I!+

-.WY\]]"&t*K$($4M%)']N&*8nO!$%56H#%N!OJ$A+$NM$
2

-0NzlZr.stt!((9!((5!(():;!((7!((9!(():):)>)>)@)I)IJ])^_~X&T&\*W%#DIIm$<#=[Ium,
NNLwjY??$LJJL;<<4%&&r.   c                 
   \        4       pVP                  4       pVP                  R V 34       VP                  4        VP                  ^ 8X  d   VP                  4        \        R4      # VP                  4        \        R4      # )zQUPDATE tasks SET deleted_at = datetime("now") WHERE id = ? AND deleted_at IS NULLr"     删除成功rC   ra   rb   rS   rowcountrT   r   r   )r   rB   ra   s   &  r,   delete_taskr3  c  se    8D[[]F
NNfiphrsKKM!

;<<JJLN++r.   z/api/carouselsc                      \        4       p V P                  4       pVP                  R 4       VP                  4       pV P	                  4        \        V Uu. uF  p\        V4      NK  	  up4      # u upi )z+SELECT * FROM carousels ORDER BY sort_orderrC   ra   rb   r   rT   r   rd   rB   ra   r   rg   s       r,   get_carouselsr7  q  sW    8D[[]F
NN@A??DJJL.#DI.//.   A0c                     \         P                  p \        4       pVP                  4       pVP	                  R V P                  RR4      V P                  R4      V P                  R4      V P                  R4      V P                  R^ 4      34       VP                  pVP                  4        VP                  4        \        RV/V C4      # )z|
        INSERT INTO carousels (page_type, image_url, image_color, link_url, sort_order)
        VALUES (?, ?, ?, ?, ?)
    	page_type	task_list	image_urlimage_colorlink_url
sort_orderrk   
r   r  rC   ra   rb   r)   r  rS   rT   r   )r   rB   ra   carousel_ids       r,   create_carouselrB  {  s    <<D8D[[]F
NN  	k*q!
	 ""KKKMJJLD+..//r.   z /api/carousels/<int:carousel_id>c                    \         P                  p\        4       pVP                  4       pVP	                  R VP                  RR4      VP                  R4      VP                  R4      VP                  R4      VP                  R^ 4      V 34       VP                  4        VP                  4        VP                  ^ 8X  d   \        R4      # \        RV /VC4      # )	z
        UPDATE carousels 
        SET page_type=?, image_url=?, image_color=?, link_url=?, sort_order=?
        WHERE id=?
    r:  r;  r<  r=  r>  r?     轮播图不存在rk   )r   r  rC   ra   rb   r)   rS   rT   r2  r   r   )rA  r   rB   ra   s   &   r,   update_carouselrE    s    <<D8D[[]F
NN 
 	k*q!
	 	KKMJJL!233D+..//r.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4        VP	                  4        VP
                  ^ 8X  d   \        R4      # \        RR/4      # )z"DELETE FROM carousels WHERE id = ?rD  r   r0  )rC   ra   rb   rS   rT   r2  r   r   )rA  rB   ra   s   &  r,   delete_carouselrG    s_    8D[[]F
NN7+HKKMJJL!233I~.//r.   z/api/skillsc            
         \         P                  P                  R R4      p \        \         P                  P                  R^4      4      p\        \         P                  P                  R^
4      4      pV^,
          V,          p\	        4       pVP                  4       p. ROp\        W`4      w  rxV'       dJ   VP                  RV 2V4       VP                  4       ^ ,          p	VP                  RV R2. VOVNVN4       M;VP                  R4       VP                  4       ^ ,          p	VP                  RW#34       VP                  4       p
\        \        R V
 4       4      4      p\        V4      p. pV
 FI  p\        V4      pVP                  VR	,          R
4      VR&   \        V4      VR&   VP                  V4       KK  	  VP!                  4        \#        RVRV	RVRV/4      # )r   rp   r   r   z4SELECT COUNT(*) FROM skills WHERE deleted_at IS NULLz
            SELECT s.*, u.phone as publisher_phone
            FROM skills s
            LEFT JOIN users u ON s.publisher_id = u.id
            WHERE s.deleted_at IS NULLzA
            ORDER BY s.created_at DESC LIMIT ? OFFSET ?
        z
            SELECT s.*, u.phone as publisher_phone
            FROM skills s
            LEFT JOIN users u ON s.publisher_id = u.id
            WHERE s.deleted_at IS NULL ORDER BY s.created_at DESC LIMIT ? OFFSET ?
        c              3   T   "   T F  qR ,          '       g   K  VR ,          x  K   	  R# 5ir   r]   r   s   & r,   r   get_skills.<locals>.<genexpr>  r   r   r   r   r   r`   r   r   r   )r   r   r)   r   rC   ra   r   rb   rc   r   r   r   r   rd   re   r~   rT   r   )r   r   r   r   rB   ra   r   r   r   r   r   r   r   r   rg   skills                   r,   
get_skillsrL    s   \\h+Fw||*+D  "-.EQh%F8D[[]FVM!8!OKMk][]jk!!$ ' (3m 4		 -},e,V,	. 	MN!!$ 
 _	 ??DXDXXYM+M:JES	)3N8KS)Q%&*51jU	  	JJL	  r.   z/api/skills/<int:skill_id>c                 
   \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        R4      # \        V4      p\        V4      VR&   \        V4      # )8SELECT * FROM skills WHERE id = ? AND deleted_at IS NULLu   技能不存在r`   r   )skill_idrB   ra   rg   r   s   &    r,   	get_skillrP    sl    8D[[]F
NNMPX{[
//
CJJL/00#YF'/F:6?r.   z/api/skills/countc                  b   \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR4      # V P                  R4      ^,          p\        V4      pV'       g   \	        RR4      # \        \        RR4      4      p\        V4      p\        RVR	V/4      # )
r   r   r   r   r   r   max_publish_skills1r   r   )r   r(   r)   r   r   r   rn   r   r   r   r   )r   rf   r   
max_skillsr   s        r,   get_skill_countrU    s    //%%o6Kk44Y??k3//c"1%E$U+G/55%&:C@AJ)'2MG]E:>??r.   c                     \         P                  p \        4       pVP                  4       pR p\         P                  P                  RR4      P                  RR4      pV'       d   VP                  RV34       VP                  4       pV'       d   VP                  RVR,          34       VP                  4       pV'       dy   VR,          ^8w  d   VP                  4        \        RR	4      # VR
,          p\        \        RR4      4      p\        V4      pW8  d    VP                  4        \        RV R24      # VP                  RV P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  R4      VV P                  R4      V P                  R4      3	4       VP                  p	VP                  4        VP                  4        \!        R
V	/V C4      # )Nr   rp   r   z,SELECT user_id FROM sessions WHERE token = ? SELECT * FROM users WHERE id = ?r   r  u'   账户已被禁用，无法发布技能r  rk   rR  rS  u   已发布的技能数最多为r  z
        INSERT INTO skills (title, description, province, city, district, street, publisher_id, publisher_name, contact)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    r   r   rx   ry   rz   r{   r	  r
  )r   r  rC   ra   r(   r)   replacerb   rc   rT   r   r   r   r   r  rS   r   )
r   rB   ra   r   
auth_tokensessionrh   rT  r   rO  s
             r,   create_skillr[    s   <<D8D[[]FL$$_b9AA)RPJE
}U//#NN=	@R?TU??$D	?a'JJL)*SUXYY#Dz !12F!LM
 5l C .JJL),J:,Vn*opp
NN  	!"

 HKKMJJLD(+d+,,r.   c                    \         P                  p\        4       pVP                  4       p. p. pR V9   d*   VP	                  R4       VP	                  VR ,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R	4       VP	                  VR,          4       R
V9   d*   VP	                  R4       VP	                  VR
,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       V'       dH   VP	                  V 4       RRP                  V4       R2pVP                  We4       VP                  4        VP                  RV 34       VP                  4       pVP                  4        V'       g   \        R4      # \        \        V4      4      # )r   r  r   r  rx   r  ry   r  rz   r  r{   r  r	  r  r
  r  zUPDATE skills SET r   r!  rN     技能不存在或已删除)r   r  rC   ra   r~   r   rb   rS   rc   rT   r   r   rd   )rO  r   rB   ra   r&  r'  r   updated_skills   &       r,   update_skillr_  D  s   <<D8D[[]FMM$Y'T']+_-T-01T\*T*-.~X&T&\*T\*T*-.4Z(T(^,4/0T"234D[)T)_-X&$TYY}%=$>kJu,
NNMPX{[OO%MJJL;<<4&''r.   c                 
   \        4       pVP                  4       pVP                  R V 34       VP                  4        VP                  ^ 8X  d   VP                  4        \        R4      # VP                  4        \        R4      # )zRUPDATE skills SET deleted_at = datetime("now") WHERE id = ? AND deleted_at IS NULLr]  r0  r1  )rO  rB   ra   s   &  r,   delete_skillra  u  se    8D[[]F
NNgjrituKKM!

;<<JJLN++r.   z/api/skills/myc                     \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR4      # V P                  R4      ^,          p\        V4      pV'       g   \	        RR4      # \        4       pVP                  4       pVP                  RV34       VP                  4       pVP                  4        \        V Uu. uF  p\        V4      NK  	  up4      # u upi )r   r   r   r   r   r   z[SELECT * FROM skills WHERE publisher_id = ? AND deleted_at IS NULL ORDER BY created_at DESC)r   r(   r)   r   r   r   rn   rC   ra   rb   r   rT   r   rd   )r   rf   r   rB   ra   r   rg   s          r,   get_my_skillsrc    s    //%%o6Kk44Y??k3//c"1%E$U+G/558D[[]F
NNpszr|}??DJJL.#DI.//.s   C3z
/api/usersc            
      L   \         P                  P                  R R4      p \        \         P                  P                  R^4      4      p\        \         P                  P                  R^
4      4      pV^,
          V,          p\	        4       pVP                  4       pV '       dv   VP                  RR\        V 4       R2R\        V 4       R234       VP                  4       ^ ,          pVP                  RR\        V 4       R2R\        V 4       R2W#34       M;VP                  R4       VP                  4       ^ ,          pVP                  RW#34       VP                  4       pVP                  4        \        R	V Uu. uF  p\        V4      NK  	  upR
VRVRV/4      # u upi )r   rp   r   r   zc
            SELECT COUNT(*) FROM users 
            WHERE phone LIKE ? OR nickname LIKE ?
        r   z
            SELECT * FROM users 
            WHERE phone LIKE ? OR nickname LIKE ?
            ORDER BY created_at DESC LIMIT ? OFFSET ?
        zSELECT COUNT(*) FROM usersz=SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?r   r   )r   r   r)   r   rC   ra   rb   rv   rc   r   rT   r   rd   )	r   r   r   r   rB   ra   r   r   rg   s	            r,   	get_usersre    s   \\h+Fw||*+D  "-.EQh%F8D[[]F  &v./q1Q7KF7S6TTU3VW	Y !!$  &v./q1Q7KF7S6TTU3VX]f		h 	34!!$VY^Xgh??DJJLt,t$s)t,	  ,s   ?F!
z/api/users/<int:user_id>/tasksc                   a	a
aa \        4       pVP                  4       o	S	P                  R V 34       S	P                  4       pV'       g    VP	                  4        \        RR/4      R3# \        \        P                  P                  R^4      4      p\        \        P                  P                  R^
4      4      o
\        P                  P                  RR4      oV^,
          S
,          oRV	V
VV3R llpV! R	V .. RO4      w  rVV! R
V .. RO4      w  rxVP	                  4        \        R\        V4      RVRVRVRV/4      # )rW  r5      用户不存在  r   r   r   rp   c                   < V P                  R 4      ^,          P                  R4      ^ ,          P                  4       pS'       d6   V'       d.   \        VS4      w  rEW,           pRV,           V,           p. VOVOpMT pRV,           pTpSP                  Wx4       SP	                  4       ^ ,          p	S'       d   V'       d   . VOXOSNSNp
M. VOSNSNp
SP                  VR,           V
4       SP                  4       p. pV EFh  p\        V4      p. pVP                  R4      '       d   VP                  VR,          4       VP                  R4      '       d   VP                  VR,          4       VP                  R4      '       d   VP                  VR,          4       VP                  R4      '       d   VP                  VR,          4       VP                  R4      ;'       g    R	pV'       d   R
P                  V4      MRpV'       d   V'       d   VR,           V,           VR&   M0V'       d   VVR&   M"V'       d   VVR&   MVP                  R4      VR&   VP                  V4       EKk  	  W3# )WHEREORDERz!SELECT COUNT(*) FROM tasks WHERE r   rx   ry   rz   r{   r|   rp   r}   N
r`   )
r   rt   r   rb   rc   r   rd   r)   r~   r   )
query_baser   r   query_conditionr   r   
full_queryr   r   r   full_paramsr   tasks_with_locationrg   	task_dictr   detail_addressbase_locationra   r   r   r   s   &&&               r,   get_paginated_tasks+get_user_tasks.<locals>.get_paginated_tasks  s   $**73A6<<WEaHNNPm)@PV)W&K#1J=OR]]K4V4m4L#J=OK!L{1!!$mBFB]BEB6BK2F2E262Kz$PPR]^  CS	IN}}Z((%%i
&;<}}V$$%%i&78}}Z((%%i
&;<}}X&&%%i&9:&]]+<=CCN8FCHH^4DM(5(<~(M	*%(5	*%(6	*%(1j(A	*%&&y13 6 #))r.   z*SELECT * FROM tasks WHERE publisher_id = ?z)SELECT * FROM tasks WHERE acceptor_id = ?rh   published_taskspublished_totalaccepted_tasksaccepted_totalr<   r   )rC   ra   rb   rc   rT   r   r   r   r   r)   rd   )r   rB   rh   r   ru  rw  rx  ry  rz  ra   r   r   r   s   &        @@@@r,   get_user_tasksr{    s'   8D[[]F
NN5zB??D

!234c99w||*+D  "-.E\\h+FQh%F4* 4*l (;4		J($O &93		J&"N 	JJLT
??..  r.   z/api/users/<int:user_id>c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        RR/4      R3# \        \        V4      4      # )rW  r5   rg  rh  rC   ra   rb   rc   rT   r   rd   )r   rB   ra   rg   s   &   r,   get_userr~    sb    8D[[]F
NN5zB
//
CJJL!234c9949r.   c                    \         P                  p\        4       pVP                  4       p. p. pR V9   d*   VP	                  R4       VP	                  VR ,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R	4       VP	                  VR,          4       R
V9   d*   VP	                  R4       VP	                  VR
,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       RV9   d*   VP	                  R4       VP	                  VR,          4       V'       g    VP                  4        \        RR/4      R3# RRP                  V4       R2pVP	                  V 4       VP                  We4       VP                  4        VP                  4        VP                  ^ 8X  d   \        RR/4      R3# \        RV /VC4      # )r  z
nickname=?genderzgender=?rx   r  ry   r  rz   r  r{   r  r  zphone=?r  z	enabled=?r5   u   没有需要更新的字段  zUPDATE users SET r   r!  rg  rh  rk   )r   r  rC   ra   r~   rT   r   r   rb   rS   r2  )r   r   rB   ra   r&  r'  r   s   &      r,   update_userr  &  s   <<D8D[[]F MMT\*T*-.4Z(T(^,T\*T*-.~X&T&\*T\*T*-.4Z(T(^,$Y'T']+D[)T)_-

!>?@#EE		- 89EE!
NN5(KKMJJL!!234c99D'*T*++r.   z/api/auth/loginz10 per minutec                  V   R p  \         P                  pVP                  R4      pVP                  R4      pV'       d	   V'       g*   \        RR/4      R3V '       d    V P	                  4        # # VP                  4       '       d   \        V4      ^8w  d*   \        RR/4      R3V '       d    V P	                  4        # # VP                  4       '       d   \        V4      ^8w  d*   \        RR/4      R3V '       d    V P	                  4        # # \        4       p V P                  4       pVP                  RV34       VP                  4       pV'       g5    VP                  R	V^34       VP                  pV P                  4        R
pMVR,          pRpVP                  RV34       VP                  4       R,          pV^8w  d7   V P	                  4        \!        RR4      V '       d    V P	                  4        # # \#        4       p	\$        P$                  P'                  4       \$        P(                  ! ^R7      ,           P+                  R4      p
VP                  RV34       VP                  RWiV
34       V P                  4        VP                  RV34       VP                  4       pV P	                  4        RT	RRVR,          RVR,          RVR,          RVR,          RVR,          RVR,          RVR,          /RTRVR,          ;'       d
    VR,          '       * /p\        V4      V '       d    V P	                  4        # #     # ; i    # ; i    # ; i  \        P                   dC    T P                  4        TP                  RT34       TP                  4       pTR,          pRp ELi ; i    # ; i    # ; i  \,         d;   p\        RR/4      R 3u R p?T '       d    T P	                  4        #     # ; i# R p?ii ; i  T '       d    T P	                  4        i     i ; ii ; i)!Nr  coder5   u!   手机号和验证码不能为空r  u    请输入正确的11位手机号u   请输入4位验证码z#SELECT * FROM users WHERE phone = ?z0INSERT INTO users (phone, enabled) VALUES (?, ?)Trk   Fz&SELECT enabled FROM users WHERE id = ?r  u!   账户已被禁用，无法登录r  )hoursr  z&DELETE FROM sessions WHERE user_id = ?zBINSERT INTO sessions (user_id, token, expires_at) VALUES (?, ?, ?)zXSELECT id, phone, nickname, avatar, gender, location, created_at FROM users WHERE id = ?rf   rh   r  r  r  r`   
created_atis_new_userneed_profileu!   服务器错误，请稍后重试r6   )r   r  r)   r   rT   isdigitr   rC   ra   rb   rc   r  rS   r=   IntegrityErrorrollbackr   r^   r   r   	timedeltar$  r   )rB   r   r  r  ra   rh   r   r  user_enabledrf   
expires_atr   r9   s                r,   loginr  Y  s    DM||!xxDG%HIJCOD 

 A }}#e*"2G%GHI3N~ 

 { ||~~TaG%=>?Dx 

 u x<uhG 
$QTY[\S]^ **" 4jGK?'L(31JJL!"EsK@ 

 =  ''++-0B0B0KKUUVij
?'L[
3	5qt{s}~ 

 Ud4jgD,$x.$x.D,d<0 ;j!1!F!Fd:6FG
 v 

 e )) $DuhO(t*#$b  L!DEFKK

	 L 

	 s   AN= N= M /N= N= ,M>N= N= ;MAN= 2M AN= &N/8DN= N= .N6 MMMAN,(N= +N,,N= /N36N:=PO=PP $O55O9=PP 	P(P P( P$"P(z/api/auth/logoutc                  ^   \         P                  P                  R 4      p V '       d}   V P                  R4      '       df   V P	                  R4      ^,          p\        4       pVP                  4       pVP                  RV34       VP                  4        VP                  4        \        R4      # )r   r   r   z$DELETE FROM sessions WHERE token = ?   登出成功r   r(   r)   r   r   rC   ra   rb   rS   rT   r   r   rf   rB   ra   s       r,   logoutr    s~    //%%o6K{--i88!!#&q)x=xH

N++r.   z/api/auth/mec                      \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR/4      R3# V P                  R4      ^,          p\        V4      pV'       g   \        RR4      # \	        V4      # )r   r   r5   r   r   r   !   登录已过期，请重新登录)r   r(   r)   r   r   r   ri   r   )r   rf   rh   s      r,   get_current_userr    sx    //%%o6Kk44Y??-.33c"1%Eu%DA3GG4=r.   z	/api/userc                     \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR/4      R3# V P                  R4      ^,          p\        V4      pV'       g   \	        RR/4      R3# \         P                  pVP                  R4      '       g   \	        RR/4      R	3# \        4       pVP                  4       pVP                  R
VP                  R4      VP                  R4      VP                  R4      VP                  R4      VP                  R4      VP                  R4      VP                  R4      VR,          34       VP                  4        VP                  RVR,          34       VP                  4       pVP                  4        \	        \        V4      4      # )r   r   r5   r   r   r   r  r  u   昵称不能为空r  z
        UPDATE users
        SET nickname=?, avatar=?, gender=?, province=?, city=?, district=?, street=?
        WHERE id=?
    r  r  rx   ry   rz   r{   rk   rW  )r   r(   r)   r   r   r   ri   r  rC   ra   rb   rS   rc   rT   rd   )r   rf   rh   r   rB   ra   updated_users          r,   update_profiler    sp   //%%o6Kk44Y??-.33c"1%Eu%D!DEFKK<<D 88J!567<<8D[[]F
NN 
 	T
	
	 	KKM
NN5T
}E??$LJJL4%&&r.   z/api/auth/profilec                      \        4       # r<   )r  r]   r.   r,   update_auth_profiler    s    r.   z/api/configc                      \        4       p V P                  4       pVP                  R 4       VP                  4       pV P	                  4        \        V Uu. uF  p\        V4      NK  	  up4      # u upi )z'SELECT * FROM system_config ORDER BY idr5  r6  s       r,   get_configsr    sW    8D[[]F
NN<=??DJJL.#DI.//.r8  z/api/config/<config_key>c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        RR/4      R3# \        \        V4      4      # )0SELECT * FROM system_config WHERE config_key = ?r5      配置不存在rh  r}  )r   rB   ra   rg   s   &   r,   
get_configr    sb    8D[[]F
NNE
}U
//
CJJL!234c9949r.   c                    \         P                  p\        4       pVP                  4       pVP	                  R V 34       VP                  4       pV'       g    VP                  4        \        RR/4      R3# VP	                  RVP                  R4      V 34       VP                  4        VP	                  R V 34       VP                  4       pVP                  4        \        \        V4      4      # )r  r5   r  rh  z{
        UPDATE system_config 
        SET config_value = ?, updated_at = datetime('now')
        WHERE config_key = ?
    r   r   r  rC   ra   rb   rc   rT   r   r)   rS   rd   )r   r   rB   ra   existingupdated_configs   &     r,   update_configr  	  s    <<D8D[[]F
NNE
}U H

!234c99
NN 
 	 
	 	KKM
NNE
}U__&NJJL4'((r.   c                 x    R V 9   ;'       d/    V P                  R ^4      ^,          P                  4       \        9   # ).)rsplitlowerALLOWED_EXTENSIONSfilenames   &r,   allowed_filer  '  s=    (? D D??3"1%++-1CCDr.   c                    \         P                  ! V 4      pVP                  R9   d   VP                  R4      pVP                  w  rV\        WV4      V8  d`   V\        WV4      ,          p\        WW,          4      p\        Wg,          4      p	VP                  W3\         P                  P                  4      p\        P                  ! 4       p
VP                  V
RVR7       V
P                  4       V8  d<   V^8  d5   V^,          p\        P                  ! 4       p
VP                  V
RVR7       KP  V
P                  ^ 4       V
# )RGBARGBJPEG)formatquality)r  LA)r   rO   modeconvertsizer   r   resize
ResamplingLANCZOSioBytesIOsavetellseek)file_streammax_sizer  max_dimensionimgwidthheightratio	new_width
new_heightbuffers   &&&&       r,   compress_imager  +  s    
**[
!C
xx>!kk% HHME
5M)E 22&	(
jj)0%2B2B2J2JKZZ\FHHVFGH4
++-(
"w|18
KKNMr.   z/api/uploadz5 per minutec                     R \         P                  9  d   \        RR/4      R3# \         P                  R ,          p V P                  R8X  d   \        RR/4      R3# \	        V P                  4      '       g   \        RR/4      R3# V P                  4       p\        V4      \        ^,          8  d   \        RR/4      R3# \        P                  ! V4      p \        P                  ! V4      pVP                  4        VP                  ^ 4       TP                  ^ 4        \        T4      p\!        T P                  4      pTP#                  R^4      p\        T4      ^8  d.   \$        P&                  ! 4       P(                   RT^ ,           R2pM%\$        P&                  ! 4       P(                   RT R2p\*        P,                  P/                  \0        P2                  R,          T4      p	\        T	R4      ;_uu_ 4       p
T
P5                  TP7                  4       4       R	R	R	4       \        T4      pTP9                  4       p^Y,          ,
          ^d,          pRT 2p\        RTRTRTRTRTR R2/4      #   \         d   p\        RR/4      R3u R	p?# R	p?ii ; i  \         d   p\        RR
/4      R3u R	p?# R	p?ii ; i  + '       g   i     L; i)filer5   u   没有上传文件r  rp   u   没有选择文件u   不支持的文件格式u   文件大小不能超过5MBu   无效的图片文件Nu   图片处理失败r6   r  _z.jpgr   wbz	/uploads/urlr  original_sizecompressed_sizecompression_ratioz.1fr   )r   filesr   r  r  rQ   r   MAX_FILE_SIZEr  r  r   rO   verifyr  r   r  r   r  uuiduuid4hexrJ   rK   r   r   configwritegetvaluer  )r  file_contentr  r  r9   compressed_bufferr  
name_partsunique_filename	save_pathrV   r  r  r  file_urls                  r,   upload_filer  C  s    W]]"!567<<== D}}!567<<&&!;<=sBB99;L
<=1,,!>?@#EE**\*K@jj%

 Q=*;7 t}}-Ha(J
:!ZZ\--.a
1dC!ZZ\--.az>SZZ8/JI	i		!	!**,- 
 %M',,.O_<<C?+,HxO? 1#6a8  5  @!89:C??@  =!567<<= 
	sH   7I4  J = K4J?JJJJ?&J:4J?:J?K	z/uploads/<filename>c                 D    \        \        P                  R ,          V 4      # )r   )r   r   r  r  s   &r,   uploaded_filer  }  s    szz/:HEEr.   c                     \         P                  ! 4       p\         P                  ! V P                  R 4      V4      P	                  R 4      # rG   )bcryptgensalthashpwencodedecode)passwordsalts   & r,   hash_passwordr    s3    >>D==148??HHr.   c                 l    \         P                  ! V P                  R 4      VP                  R 4      4      # r  )r  checkpwr  )r  hashed_passwords   &&r,   verify_passwordr    s'    >>(//'2O4J4J74STTr.   c                  h   \        \        P                  ! 4       4      p \        P                  ! ^^4      p\        P                  ! ^^4      p. R
Op\        P
                  ! V4      pVR8X  d   W,           pV RV R2pMdVR8X  d    W8  d   W3MW!3w  rW,
          pV RV R2pM>\        P                  ! ^^
4      p\        P                  ! ^^
4      pW,          pV RV R2pR\        V4      R\        P                  P                  4       \        P                  ! ^R	7      ,           /\        V &   W3# )   +r   z + z = ?z - u    × textr  minutes)r  r      ×)
r7   r  r  randomrandintchoicer   r   r  captcha_store)
captcha_idnum1num2	operatorsopr   displays          r,   generate_captchar    s   TZZ\"J>>!R D>>!R D I	y	!B	SyF#dV4(	s%)\d\|
F#dV4(~~a$~~a$F$tfD) 	Fh''++-0B0B10MM!M* r.   c                 L   ^^2r!. pVP                  RV RV R24       VP                  R4       \        ^24       F  p\        P                  ! ^ V4      p\        P                  ! ^ V4      p\        P                  ! ^^4      pR\        P                  ! ^^4       R\        P                  ! ^^4       R\        P                  ! ^^4       R2pVP                  RV R	V R
V RV R2	4       K  	  VP                  RV  R24       VP                  R4       RP	                  V4      # )   z/<svg xmlns="http://www.w3.org/2000/svg" width="z
" height="z">z1<rect width="100%" height="100%" fill="#f5f5f5"/>zrgb(r   r   z<circle cx="z" cy="z" r="z" fill="z"/>zw<text x="70" y="35" font-family="Arial, sans-serif" font-size="24" fill="#333" text-anchor="middle" font-weight="bold">z</text>z</svg>rp   )r~   ranger  r  r   )	display_textr  r  	svg_partsr  xyrF   colors	   &        r,   create_svg_captchar    s5   6IFugZX^W__abcHJ2YNN1e$NN1f%NN1a v~~c3/06>>#s3K2LBv~~^acfOgNhhij<s&58E7#NO    O  P\  O]  ]d  e  fX779r.   z/api/admin/captchac                  Z    \        4       w  r\        R V RV/4      pRVP                  R&   V# )r   questionz.no-store, no-cache, must-revalidate, max-age=0Cache-Control)r  r   r(   )r   r
  r*   s      r,   get_captchar    s>    /1JjL H )YH_%Or.   z/api/admin/loginc            
      B   \         P                  p V P                  R 4      pV P                  R4      pV P                  R4      pV P                  R4      pV'       d	   V'       g   \        RR/4      R3# V'       d	   V'       g   \        RR/4      R3# \        P                  V4      pV'       g   \        RR/4      R3# \
        P
                  P                  4       VR	,          8  d   \        V \        RR/4      R3# VP                  4       VR
,          8w  d   \        RR/4      R3# \        V \        4       pVP                  4       pVP                  RV34       VP                  4       pV'       g    VP                  4        \        RR/4      R3# \        W(R,          4      '       g    VP                  4        \        RR/4      R3# \        P                  ! ^ 4      p	\
        P
                  P                  4       \
        P                   ! ^R7      ,           P#                  R4      p
VP                  RVR,          34       VP                  RVR,          W34       VP%                  4        VP                  4        \        RV	RRVR,          R VR ,          //4      # )usernamer  r   captchar5   u   用户名和密码不能为空r  u   验证码不能为空u   验证码已过期r  r  u   验证码错误z,SELECT * FROM admin_users WHERE username = ?u   用户名或密码错误r   r  r  z-DELETE FROM admin_sessions WHERE admin_id = ?rk   zIINSERT INTO admin_sessions (admin_id, token, expires_at) VALUES (?, ?, ?)rf   admin)r   r  r)   r   r  r   r   upperrC   ra   rb   rc   rT   r  r[   r\   r  r$  rS   )r   r  r  r   captcha_inputcaptcha_datarB   ra   
admin_userrf   r  s              r,   admin_loginr    sK    <<Dxx
#Hxx
#H,'JHHY'M8!ABCSHH]!89:C?? $$Z0L!567<<l!;;*%!567<<V 44!234c99j!8D[[]F
NNAH;O"J

!;<=sBB8
%;<<

!;<=sBB!!"%E##'')H,>,>r,JJTTUhiJ
NNBZPTEUDWX
NN^t$e8:KKMJJL*T"
:.
  r.   c                     V '       g   R # \        4       pVP                  4       pVP                  RV 34       VP                  4       pVP	                  4        V'       d   \        V4      # R # )Nz
        SELECT u.* FROM admin_users u
        JOIN admin_sessions s ON u.id = s.admin_id
        WHERE s.token = ? AND s.expires_at > datetime('now')
    )rC   ra   rb   rc   rT   rd   rm   s   &   r,   get_admin_from_tokenr    sZ    8D[[]F
NN  	
 //
CJJL49%%r.   z/api/admin/mec                  >   \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR4      # V P                  R4      ^,          p\        V4      pV'       g   \	        RR4      # \        RVR,          RVR,          /4      # )r   r   r   r   r   r  rk   r  )r   r(   r)   r   r   r   r  r   )r   rf   r  s      r,   get_current_adminr     s    //%%o6Kk44Y??k3//c"1%E 'EA3GGD%+z53DEFFr.   z/api/admin/passwordc                  2   \         P                  P                  R 4      p V '       d   V P                  R4      '       g   \	        RR4      # V P                  R4      ^,          p\        V4      pV'       g   \	        RR4      # \         P                  pVP                  R4      pVP                  R4      pV'       d	   V'       g   \	        R4      # \        4       pVP                  4       pVP                  R	VR
,          34       VP                  4       R,          p\        WH4      '       g    VP                  4        \        RR/4      R3# VP                  R\        V4      VR
,          34       VP!                  4        VP                  4        \#        R4      # )r   r   r   r   r   r  old_passwordnew_passwordu!   旧密码和新密码不能为空z-SELECT password FROM admin_users WHERE id = ?rk   r  r5   u   旧密码错误r  zm
        UPDATE admin_users 
        SET password = ?, updated_at = datetime('now')
        WHERE id = ?
    u   密码修改成功)r   r(   r)   r   r   r   r  r  rC   ra   rb   rc   r  rT   r   r  rS   r   )	r   rf   r  r   r"  r#  rB   ra   current_passwords	            r,   change_admin_passwordr%    sC   //%%o6Kk44Y??k3//c"1%E 'EA3GG<<D88N+L88N+L|ABB8D[[]F
NNBU4[NS(4<::

!234c99
NN  
%uT{	3	5
 	KKMJJL011r.   z/api/admin/logoutc                  ^   \         P                  P                  R 4      p V '       d}   V P                  R4      '       df   V P	                  R4      ^,          p\        4       pVP                  4       pVP                  RV34       VP                  4        VP                  4        \        R4      # )r   r   r   z*DELETE FROM admin_sessions WHERE token = ?r  r  r  s       r,   admin_logoutr'  <  s~    //%%o6K{--i88!!#&q)xCeXN

N++r.   z/api/admin/ratingsc            
      P   \         P                  P                  R R4      p \        \         P                  P                  R^4      4      p\        \         P                  P                  R^
4      4      pV^,
          V,          p\	        4       pVP                  4       pRpRp. p. p	V '       dN   \        V 4      p
VR,          pVR,          pRV
 R2.^,          pVP                  V4       V	P                  V4       VP                  Wy4       VP                  4       ^ ,          pVR,          pVP                  W#.4       VP                  Wh4       VP                  4       pVP                  4        . pV F  p\        V4      pVP                  V4       K!  	  \        R	VR
VRVRV/4      # )r   rp   r   r   a_  
        SELECT r.*, t.title as task_title, u.nickname as acceptor_name, u.phone as acceptor_phone,
               p.nickname as publisher_name, p.phone as publisher_phone
        FROM task_ratings r
        LEFT JOIN tasks t ON r.task_id = t.id
        LEFT JOIN users u ON r.acceptor_id = u.id
        LEFT JOIN users p ON r.publisher_id = p.id
    z#SELECT COUNT(*) FROM task_ratings rzy WHERE (t.title LIKE ? OR u.nickname LIKE ? OR u.phone LIKE ? OR p.nickname LIKE ? OR p.phone LIKE ? OR r.comment LIKE ?)r   z, ORDER BY r.created_at DESC LIMIT ? OFFSET ?r   r   )r   r   r)   r   rC   ra   rv   r   rb   rc   r   rT   rd   r~   r   )r   r   r   r   rB   ra   r   r   r   r   r   r   r   r   r   rg   items                    r,   get_admin_ratingsr*  H  s   \\h+Fw||*+D  "-.EQh%F8D[[]FE 8KFL(0	  M  	M  S  	SYKq)*Q.m$M*
NN;-OOa E	;;E
MM5/"
NN5!??DJJLECyT  	  r.   z"/api/admin/ratings/<int:rating_id>c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        R4      # \        \        V4      4      # )a  
        SELECT r.*, t.title as task_title, t.description as task_description,
               u.nickname as acceptor_name, u.phone as acceptor_phone,
               p.nickname as publisher_name, p.phone as publisher_phone
        FROM task_ratings r
        LEFT JOIN tasks t ON r.task_id = t.id
        LEFT JOIN users u ON r.acceptor_id = u.id
        LEFT JOIN users p ON r.publisher_id = p.id
        WHERE r.id = ?
       评价不存在)rC   ra   rb   rc   rT   r   r   rd   )	rating_idrB   ra   rg   s   &   r,   get_admin_ratingr.  }  sa    8D[[]F
NN 	 	 //
CJJL/0049r.   c                 
   \        4       pVP                  4       pVP                  R V 34       VP                  4        VP                  ^ 8X  d   VP                  4        \        R4      # VP                  4        \        R4      # )z%DELETE FROM task_ratings WHERE id = ?r,  r0  r1  )r-  rB   ra   s   &  r,   delete_admin_ratingr0    sc    8D[[]F
NN:YLIKKM!

/00JJLN++r.   z	/api/newsc                      \        4       p V P                  4       pVP                  R 4       VP                  4       pV P	                  4        \        V Uu. uF  p\        V4      NK  	  up4      # u upi )zVSELECT * FROM news WHERE status = "published" ORDER BY sort_order ASC, created_at DESCr5  r6  s       r,   get_newsr2    sW    8D[[]F
NNkl??DJJL.#DI.//.r8  z/api/admin/newsc                      \        4       p V P                  4       pVP                  R 4       VP                  4       pV P	                  4        \        V Uu. uF  p\        V4      NK  	  up4      # u upi )z;SELECT * FROM news ORDER BY sort_order ASC, created_at DESCr5  r6  s       r,   get_all_newsr4    sW    8D[[]F
NNPQ??DJJL.#DI.//.r8  z/api/news/<int:news_id>c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        RR/4      R3# \        \        V4      4      # )z8SELECT * FROM news WHERE id = ? AND status = "published"r5      资讯不存在rh  r}  news_idrB   ra   rg   s   &   r,   get_news_by_idr9    sc    8D[[]F
NNMPWzZ
//
CJJL!234c9949r.   z/api/admin/news/<int:news_id>c                     \        4       pVP                  4       pVP                  R V 34       VP                  4       pVP	                  4        V'       g   \        RR/4      R3# \        \        V4      4      # )SELECT * FROM news WHERE id = ?r5   r6  rh  r}  r7  s   &   r,   get_admin_news_by_idr<    sb    8D[[]F
NN4wjA
//
CJJL!234c9949r.   c                     \         P                  p \        4       pVP                  4       pVP	                  R V P                  R4      V P                  R4      V P                  R4      V P                  R4      V P                  RR4      V P                  R^ 4      34       VP                  pVP                  4        VP                  4        \        RV/V C4      # )	zy
        INSERT INTO news (title, summary, content, image_url, status, sort_order)
        VALUES (?, ?, ?, ?, ?, ?)
    r   summarycontentr<  r   r   r?  rk   r@  )r   rB   ra   r8  s       r,   create_newsr@    s    <<D8D[[]F
NN  	;'q!

 GKKMJJLD'*T*++r.   c                 ~   \         P                  p\        4       pVP                  4       pVP	                  R V 34       VP                  4       pV'       g    VP                  4        \        RR/4      R3# VP	                  RVP                  R4      VP                  R4      VP                  R4      VP                  R4      VP                  R	4      VP                  R
4      V 34       VP                  4        VP	                  R V 34       VP                  4       pVP                  4        \        \        V4      4      # )r;  r5   r6  rh  z
        UPDATE news 
        SET title = ?, summary = ?, content = ?, image_url = ?, status = ?, sort_order = ?, updated_at = datetime('now')
        WHERE id = ?
    r   r>  r?  r<  r   r?  r  )r8  r   rB   ra   r  updated_newss   &     r,   update_newsrC    s    <<D8D[[]F
NN4wjA H

!234c99
NN 
 	
	 	KKM
NN4wjA??$LJJL4%&&r.   c                     \        4       pVP                  4       pVP                  R V 34       VP                  4        VP	                  4        VP
                  ^ 8X  d   \        RR/4      R3# \        RR/4      # )zDELETE FROM news WHERE id = ?r5   r6  rh  r   r0  )rC   ra   rb   rS   rT   r2  r   )r8  rB   ra   s   &  r,   delete_newsrE  
  si    8D[[]F
NN2WJ?KKMJJL!!234c99I~.//r.   __main__rE   backend_port3000zStarting Flask server on port z...z0.0.0.0)debugporthostuse_reloader)r   r   r   r   r   )zContent-Typer   r  PragmaExpires>   gifjpgpngjpegwebpi   )F)r  )u   操作成功N)i  P   i  )|flaskr   r   r   r   r   
flask_corsr   flask_limiterr	   flask_limiter.utilr
   r=   rJ   sysr  r   r[   r  stringhashlibr  r  werkzeug.utilsr   PILr   __name__r   limiterrK   r   rL   __file__r?   rP   r   r  r  r  r  rI   before_requestr-   after_requestr3   errorhandlerr   r:   rC   rX   r^   ri   rn   rv   re   r   r   r   r   r   r   r   r   r   router   r   r   r  r  r.  r3  r7  rB  rE  rG  rL  rP  rU  r[  r_  ra  rc  re  r{  r~  r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r%  r'  r*  r.  r0  r2  r4  r9  r<  r@  rC  rE  r   rJ  runr]   r.   r,   <module>rf     s(	   M M  ! 1  	 
       	  * Ho S	+-DE>`	  $%	 RWW__X68LMggll277??846NORWW__X6E: +

? #0

   ' ( k]# $
 
   )	 	
6&%$&@F		$B <%)R *Rh w/A 0A  %w7 8, <&*A' +A'F %w7D' 8D'L %z:, ;, eW-0 .0 fX.0 /0, -w?0 @04 -zB
0 C
0 =5'*5 +5n '%9 : 0@ 1@  =6(+.- ,.-` '%9.( :.(` '(<, =, eW-0 .0& <%)# *#J +eW=Y >Yv %w7
 8
 %w70, 80,d vh/O   0Ob x0	, 1	, >E7+ , ;((' )('T 0 1 =5'*0 +0 %w7 8 %w7) 8):D0 =6(+~6  ,6p  !F "FIU4$ %1 2 x0~6  16p& ?UG,G -G  5'2$2 3$2L 1	, 2	, %12 22h /%A B. /(D, E, ;(0 )0 ug.0 /0 $ug6
 7
 *UG<
 =
 ;), *,. $ug6 ' 7 'D $xj9
0 :
0 z	
$%I78D	*4&
45GG$T	GF r.   