| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983 |
- 我设计了一个系统,内部有如下实体:
- 1. **文章**:以文本为主体,可能包含少量表格、代码、文头文尾等内容,包含大量需提取的关键信息。一个典型的示例:
- ```
- 2026年6月1日晚8点,好友们决定为王若飞(男)组织一场生日派对。这次小范围聚会共有5人参加,刘阳(女)作为总策划,除寿星和总策划外,还有李四(女)、王五(男)和赵六(男)参加。活动总预算为3000元,且已完成备案,现场安排了掷骰子、扔飞镖和打桌球等破冰游戏,确保大家玩得尽兴。
- ```
- 2. **关键信息定义**:使用Json定义的树状结构,每个节点以`node_label`为key,包含`metadata`字段和`subnodes`字段,`metadata`字段中包含`node_label`(取关键信息名称的拼音首字母、`node_name`(关键信息名称)、`node_type`(取值为`concept`时表示分类节点,`property`时表示属性节点)、`value_type`(仅当`node_type`为`property`时生效,取值为`integer`、`float`、`string`、`boolean`、`date_time`、`class`,其中`class`表示关键信息为复合结构,包含子属性)、`is_list`(仅当`node_type`为`property`时生效,标识关键信息是否为列表类型,即是否可以有多个实例)字段。一个典型的示例:
- ```json
- {
- "metadata": {
- "node_label": "PDJH",
- "node_name": "派对计划",
- "node_type": "concept"
- },
- "subnodes": {
- "JBXX": {
- "metadata": {
- "node_label": "JBXX",
- "node_name": "基本信息",
- "node_type": "concept"
- },
- "subnodes": {
- "PDMC": {
- "metadata": {
- "node_label": "PDMC",
- "node_name": "派对名称",
- "node_type": "property",
- "value_type": "string",
- "is_list": false
- }
- },
- "PDKSSJ": {
- "metadata": {
- "node_label": "PDKSSJ",
- "node_name": "派对开始时间",
- "node_type": "property",
- "value_type": "date_time",
- "is_list": false
- }
- },
- "PDZRS": {
- "metadata": {
- "node_label": "PDZRS",
- "node_name": "派对总人数",
- "node_type": "property",
- "value_type": "integer",
- "is_list": false
- }
- },
- "SFBA": {
- "metadata": {
- "node_label": "SFBA",
- "node_name": "是否备案",
- "node_type": "property",
- "value_type": "boolean",
- "is_list": false
- }
- }
- }
- },
- "RYXX": {
- "metadata": {
- "node_label": "RYXX",
- "node_name": "人员信息",
- "node_type": "concept"
- },
- "subnodes": {
- "ZCH": {
- "metadata": {
- "node_label": "ZCH",
- "node_name": "总策划",
- "node_type": "property",
- "value_type": "class",
- "is_list": false
- },
- "subnodes": {
- "XM": {
- "metadata": {
- "node_label": "XM",
- "node_name": "姓名",
- "node_type": "property",
- "value_type": "string",
- "is_list": false
- }
- },
- "SFZH": {
- "metadata": {
- "node_label": "SFZH",
- "node_name": "身份证号",
- "node_type": "property",
- "value_type": "string",
- "is_list": false
- }
- }
- }
- },
- "RYQD": {
- "metadata": {
- "node_label": "RYQD",
- "node_name": "人员清单",
- "node_type": "property",
- "value_type": "class",
- "is_list": true
- },
- "subnodes": {
- "XM": {
- "metadata": {
- "node_label": "XM",
- "node_name": "姓名",
- "node_type": "property",
- "value_type": "string",
- "is_list": false
- }
- },
- "SFZH": {
- "metadata": {
- "node_label": "SFZH",
- "node_name": "身份证号",
- "node_type": "property",
- "value_type": "string",
- "is_list": false
- }
- }
- }
- }
- }
- },
- "HDXX": {
- "metadata": {
- "node_label": "HDXX",
- "node_name": "活动信息",
- "node_type": "concept"
- },
- "subnodes": {
- "PBYXLB": {
- "metadata": {
- "node_label": "PBYXLB",
- "node_name": "破冰游戏清单",
- "node_type": "property",
- "value_type": "string",
- "is_list": true
- }
- }
- }
- }
- }
- }
- ```
- 3. **关键信息实例**:根据**关键信息定义**,对其中的节点进行赋值而得到的实例,以Json形式表示。其中,有如下注意事项:
- 1. 节点以`node_label`为key;
-
- 2. 在**关键信息定义**中,`node_type`为`concept`的,value为Json对象,包含其子节点或子属性的值;
- 3. 在**关键信息定义**中,`value_type`为`integer`、`float`、`string`、`boolean`、`date_time`时,如果`is_list`为`false`,value为对应类型;如果`is_list`为`true`,value为对应类型列表。特别地,`date_time`类型的值设置为字符串,但格式固定为`XXXX-XX-XXTXX:XX:XX.XXX`;
- 4. 在**关键信息定义**中,`value_type`为`class`的,如果`is_list`为`false`,value为Json对象,包含其子属性的值;如果`is_list`为`true`,value为Json对象列表,每个元素包含其子属性的值。
- 针对**文章**示例,根据上述**关键信息定义**,生成对应的**关键信息实例**为:
- ```json
- {
- "PDJH": {
- "JBXX": {
- "PDMC": "王若飞生日派对",
- "PDKSSJ": "2026-06-01T20:00:00.000",
- "PDZRS": 5,
- "PDZYS": 3000.0,
- "SFBA": true
- },
- "RYXX": {
- "ZCH": {
- "XM": "刘阳",
- "XB": "女"
- },
- "RYQD": [
- {
- "XM": "刘阳",
- "XB": "女"
- },
- {
- "XM": "王若飞",
- "XB": "男"
- },
- {
- "XM": "李四",
- "XB": "女"
- },
- {
- "XM": "王五",
- "XB": "男"
- },
- {
- "XM": "赵六",
- "XB": "男"
- }
- ]
- },
- "HDXX": {
- "PBYXQD": [
- "掷骰子",
- "扔飞镖",
- "打桌球"
- ]
- }
- }
- }
- ```
- 现在,我需要依托大模型,根据输入的**文章**和**关键信息定义**,从文章中将所有关键信息提取出来;请帮我设计一个prompt,使得大模型能够准确、高效、稳定地完成这个task。如果有必要,请使用langchain等框架,分步骤进行,以达到最好的效果。
- --------
- OK,现在,我需要将原始文本中相关的关键信息区域也标识出来。例如,针对“2026年6月1日晚8点,好友们决定为王若飞(男)组织一场生日派对,活动已完成备案。”这个文本,我希望生成类似于“{[PDJH.JBXX.PDKSSJ],2026-06-01T20:00:00.000,2026年6月1日晚8点,2026年1月1日~2026年12月31日,YYYY年M月D日(上午/下午/晚)H点[m分[s秒]]},好友们决定为{[PDJH.RYXX.RYQD[0].XM],王若飞,王若飞,2~4个汉字,不作转换}({[PDJH.RYXX.RYQD[0].XB],男,男,男/女,不作转换})组织一场生日派对,活动{[PDJH.JBXX.SFBA],true,已完成备案,已完成备案/未完成备案,true->已完成备案/false->未完成备案}”。每块关键信息区域包括{节点路径,提取值,原始文本,提取值的约束(以自然语言表示,供大模型理解),提取值到原始文本的转换规则(以自然语言表示,供大模型理解)}。请先帮我思考这个标识相关的符号体系是否合理,是否会与原文符号产生歧义,如果会,则不一定使用这套符号体系,改进该体系。
- --------
- 1. 值约束来源是关键信息定义Json,部分关键信息会带一个constraints属性,里面会带{"raw_constraints":{"min_value":[0],"max_value":[100]}}、{"raw_constraints":{"enum_string":[["男", "女"]]}}这样的约束,确保将其精准地转换为自然语言,也可以在值约束里将原始的Json约束附带上。如果关键信息没有自带该属性,那么对于显而易见的关键信息约束,如“身份证号(18位数字,最后一位可以是X)”、“性别(男/女)”、“年龄(0-110)”等,你要进行推断,给出约束;对于你无法确定的约束,不要随意给出。 转换规则由你自行给出。
- 2. 标注以一个独立字段输出。
- --------
- 有几个提取的原则需要微调一下:
- 1. 如果原文中某处同时对应关键信息定义中的多个关键信息,如“刘阳”即对应“总策划”,又对应“人员清单”中的一员,那么标注时,将多处同时标注,并在中间使用“||”分隔开,如:`{{PDJH.RYXX.ZCH.XM||刘阳||刘阳|| ||不作转换}}||{{PDJH.RYXX.RYQD[1].XM||刘阳||刘阳|| ||不作转换}}`;
- 2. 如果原文中不存在关键信息实例中的某处关键信息原文,例如原文为“为王若飞(男)组织一场生日派对”,而关键信息实例中为“王若飞生日派对”,那么在原文中找到最相关的部分,如“生日派对”进行标注,并将转换规则写为“根据原文进行微调”,结果为`{{PDJH.JBXX.PDMC||王若飞生日派对||生日派对|| ||根据原文进行微调}}`;
- 3. 对于时间、布尔等类型的值,你原来的做法是在代码里写死,我需要你根据原文内容,利用大模型(为确保快速处理,可不使用reasoning推理)给出明确的转换规则,例如`ISO 8601 → YYYY年M月D日(上午/下午/晚)H点[m分[s秒]],根据是否为整点,可视情省略[]中的内容`;
- 4. 你现在预置了一些关键信息的约束,我同样要求你不要写死,根据不同关键信息定义中的内容,利用大模型(为确保快速处理,可不使用reasoning推理)给出相应的约束。
- --------
- 针对某个提取值在原文中拥有多个对应文本的情况(如“王五”这个人在文中出现了多次),我新增了一条提取规则:“10. **同一提取值可多次标注**:如果某个提取值在原文中拥有多个对应文本,对这些文本分别进行标注,各标注的“节点路径”、“提取值”、“值约束”需保持一致,“原始文本”、“转换规则”可以不同,视原文决定”。但是经过测试,该规则未生效,多个对应文本只有一个被标注。请帮我检查并使之生效。
- --------
- 请为我增加调试日志,在每一次与LLM交互前,打印本次交互是整个处理流程中的哪个分步骤,同时打印给LLM发送的prompt,以便我了解发送的内容。同时,在最外层函数调用处增加debug变量,只有当它为True时才打印上述日志。
- --------
- 目前,在转换规则生成过程中,由于直接把整篇文章给了LLM,导致LLM识别提取值对应的原文不清晰(例如提取值“3000.0”对应文中的“3000”,但LLM认为是“3000元”)。所以,我想将“Step 2: LLM辅助生成约束和转换规则”拆分成两步,第一步将提取值对应的原文提取出来,第二步仅根据对应的原文进行约束和转换规则的生成。为了速度快,两步均采用大模型的轻量级调用,不调用reasoning推理。
- --------
- 现在,我希望做一个界面,左侧为菜单栏,目前包含两个菜单:文档解析和信息管理。
- 1. 文档解析:分为两栏,左栏为文档展示区域,如未选择文档,显示“请选择文档”;上传文档后,左侧可浏览文档(支持pdf和word),右侧区域分为上下两栏,比例约为3:1,上方显示从文档中提取的正文内容(不含页眉页脚等,可转为markdown格式),右上方有一个按钮,“开始解析”,点击后,下栏开始输出正文内容关键信息提取的思考过程(即原python文件输出的内容);思考完成后,上方内容区域变为提取后的文本(带{{||}})。
- 2. 信息管理:针对关键信息树状结构的管理维护模块,以折叠树形式展示,每个节点均可编辑其元数据和子节点(参考之前的设计:**关键信息定义**:使用Json定义的树状结构,每个节点以`node_label`为key,包含`metadata`字段和`subnodes`字段,`metadata`字段中包含`node_label`(取关键信息名称的拼音首字母、`node_name`(关键信息名称)、`node_type`(取值为`concept`时表示分类节点,`property`时表示属性节点)、`value_type`(仅当`node_type`为`property`时生效,取值为`integer`、`float`、`string`、`boolean`、`date_time`、`class`,其中`class`表示关键信息为复合结构,包含子属性)、`is_list`(仅当`node_type`为`property`时生效,标识关键信息是否为列表类型,即是否可以有多个实例)字段。)
- 前端请使用vue实现,后端引入flask框架。请实现。
- ---
- 后端配置里有API Key,前端不用输入,请求发给后端,后端使用配置的API key即可。
- ---
- 将后端端口改为8754,前端端口改为8774,然后重启服务。
- ---
- 我要求左侧是文档预览,word打开什么样子就是什么样子,pdf打开什么样子就是什么样子;右侧md文字行距过大,减小一些
- ---
- 1. 上传pdf,报错:上传失败:文档解析失败: PyMuPDF 未安装,无法解析 PDF
- 2. 上传word,不报错,右侧也能解析出来,但左侧为空白页面,无word文档显示。
- ---
- 点击上传,报错:上传失败:Promise.withResolvers is not a function
- ---
- 页面缩放大小为125%时,显示没有问题;100%时,右侧有一大块区域是空白的,鼠标也无法交互。请修复。
- ---
- 信息管理中,我希望不止可以管理这一条关键信息,而是整理一个列表,每一条关键信息有名称、描述等元数据,点开后是这个树状结构,可以进行管理。支持json格式的导入,导入时填入名称和描述,导入格式参考@data/samples/info_definition.json。
- ---
- 我希望在@extractor.py中写一个函数,输入一段文本,从中提取**关键信息定义**Json,格式参考@data/samples/info_definition.json,具体含义:使用Json定义的树状结构,每个节点以`node_label`为key,包含`metadata`字段和`subnodes`字段,`metadata`字段中包含`node_label`(取关键信息名称的拼音首字母、`node_name`(关键信息名称)、`node_type`(取值为`concept`时表示分类节点,`property`时表示属性节点)、`value_type`(仅当`node_type`为`property`时生效,取值为`integer`、`float`、`string`、`boolean`、`date_time`、`class`,其中`class`表示关键信息为复合结构,包含子属性)、`is_list`(仅当`node_type`为`property`时生效,标识关键信息是否为列表类型,即是否可以有多个实例)字段。使用大模型来实现,生成后校验Json结构是否正确,如不正确,给出错误信息让大模型重试。
- ---
- 创建一个 test_definition.py 示例脚本,但复用test.py 中已有的 API 配置调用模型
- ---
- 右下方的文本框里完全没有思考过程输出,之前annotator.py、extractor.py等文件的思考过程输出呢?请将它们返回给前端,并实时流式输出至右下方文本框中。
- ---
- 写个启动脚本吧,里面设置INFO_EXTRACTOR_API_KEY变量,我稍后填入key。
- ---
- 1. 界面右下方,我希望将当前Step也输出出来,当前阶段的思考过程和输出前方统一加4个空格缩进(原有n个空格缩进的话,变为n+4个),阶段之间用“====================================”隔开,例如:
- ```
- 阶段一:XXXXX
- XXXX(思考过程)
- XXXX(思考过程)
- 输出:
- {
- XXXXX
- }
- ====================================
- 阶段2a:XXXX
- ……
- ====================================
- 2. 增加功能:右侧上方区域,不再以markdown形式展示,直接将文字排版显示出来,类似于新闻页面,默认使用仿宋_GB2312字体。解析完成后,对于{{COL1||COL2||COL3||COL4||COL5}}中间的内容进行渲染,文字为原文(COL3),但使用灰色背景将对应文字框选。点击框选区域任意位置,弹出对话框,对话框内表单包含字段:
- ①关键信息名称,值为COL1对应中文字段名,不可编辑;②关键信息值,值为COL2,可编辑;这里你需要根据COL1对应的数据类型和COL4生成组件,如COL1为数字,这里就是数字输入框;COL1为时间,这里就是时间选择框;COL1为字符串,这里就是文本框;COL1为字符串,且COL4约束为枚举型,这里就是下拉选择框;等等。③文中展示值,值为COL3,可编辑,文本框。修改并确认后,后台更新{{}}中的COL2和COL3值,原文中灰色背景框选的部分更新为新的COL3值。
- ---
- 提取报错:提取失败:maximum recursion depth exceeded in comparison
- ---
- 基本实现了,但存在两个问题:
- 1. 灰色选中的区域,不要换行显示,嵌入原文中即可。我以[]表示灰色区域,示例:
- ```
- [小明]是个[医生]。
- ```
- 而非
- ```
- [小明]
- 是个
- [医生]
- 。
- ```
- 2. 文本区域,段落与段落之间空行太多,去掉,一个空行都不要。
- ---
- 另外,右下方思考过程输出时,区域内滚动条自动不断滚到最底部吧
- ---
- 你个垃圾,灰色框选区域不要换行展示,而是嵌入文中,你一点没改;段落与段落之间一个空行都不要,但不是不要换行,还是要一个换行的。你行不行?你不行有的是大模型能干。
- ---
- 有没有一种可能,你用<span>,它灰色区域就一定会换行?我需要它在原文中的原位置,不能换行显示。
- ---
- 基本实现了,但段落之间的换行还要留着啊,怎么没了?从前后端都找找问题。
- 另外,每个段落前要缩进2字符。
- ---
- 当关键信息在段首时,你的处理方式会导致它前面的换行丢失,与上一段接在一起。请解决。
- 另外,为了测试方便,在文本区域增加按钮:导入文本,让我粘贴带{{}}的文本进去,你直接展示,省去标注流程。
- ---
- 段落间的换行又没了,你仔细看看怎么回事,我的要求:段落间的换行要留着,尤其注意段首有关键信息的情况;关键信息两侧的换行不要(除非它在段落首尾)
- ---
- .replace(/(\{\{[^{}]*\}\})/g, (m) => m.replace(/\n+/g, '')),这个语句是干什么用的?逻辑不对吧,执行完以后,文中就没有段落间的换行了
- ---
- function confirmImport() {
- const text = importText.value || ''
- if (!text.trim()) {
- ElMessage.warning('请粘贴要导入的文本')
- return
- }
- annotatedContent.value = normalizeNewsText(text)
- hasResult.value = true
- importDialogVisible.value = false
- ElMessage.success('已导入文本')
- persistAnnotation()
- }
- 这个方法中,normalizeNewsText(text)的结果含\n,为什么最终渲染出来的丢失了换行符?
- ---
- 导入时输入:
- 1
- 2
- 3
- 解析完后,也显示 1 2 3,换行到底怎么回事???
- ---
- 我希望启动前端,但页面上不显示vue调试工具
- ---
- 取消所有TODO。现在,信息管理中,条目无法删除,请实现。写完后,不要启动playwright验证。
- ---
- 把模型的model_name、base_url都做到start_backend的两个脚本里。
- ---
- 现在,我的test.py可以正常使用大模型推理,但使用start_backend.bat调用app.py中的推理,报错: {'error': {'code': '1113', 'message': '余额不足或无可用资源包,请充值。'}},请帮我检查配置。
- ---
- test.py 日志:POST https://open.bigmodel.cn/api/coding/paas/v4/chat/completions "HTTP/1.1 200 OK"
- app.py 日志:POST https://open.bigmodel.cn/api/coding/paas/v4/chat/completions "HTTP/1.1 429 Too Many Requests"
- 你发个请求验证吧
- ---
- 三个问题:
- 1. 最终输出结果,前后容易带上<article>和</article>,过滤掉;
- 2. 对照我的原始需求:“右侧上方区域,不再以markdown形式展示,直接将文字排版显示出来,类似于新闻页面,默认使用仿宋_GB2312字体。解析完成后,对于{{COL1||COL2||COL3||COL4||COL5}}中间的内容进行渲染,文字为原文(COL3),但使用灰色背景将对应文字框选。点击框选区域任意位置,弹出对话框,对话框内表单包含字段:①关键信息名称,值为COL1对应中文字段名,不可编辑;②关键信息值,值为COL2,可编辑;这里你需要根据COL1对应的数据类型和COL4生成组件,如COL1为数字,这里就是数字输入框;COL1为时间,这里就是时间选择框;COL1为字符串,这里就是文本框;COL1为字符串,且COL4约束为枚举型,这里就是下拉选择框;等等。③文中展示值,值为COL3,可编辑,文本框。修改并确认后,后台更新{{}}中的COL2和COL3值,原文中灰色背景框选的部分更新为新的COL3值。” 你现在在灰色背景框选区域中,显示的是COL2的值,而非COL3的值;另外,弹出对话框中,“关键信息值”应为COL2的值,目前为空值;“文中展示值”应为COL3的值,目前为COL2的值。请修改;
- 3. 思考过程容易输出英文思考,请强调输出中文思考过程。
- ---
- 你说“LLM 有时输出 {{path||raw_text||...}}(第 2 段空、第 3 段填了原文),看起来像"COL2 显示成了 COL3"。” 根据我观察,不是的,就算{{}}中内容正确,前端处理也有问题。
- 另外,我不希望完全依赖大模型,请写一个方法,校验LLM输出的结果,{{}}外的内容+{{}}内的原文字段,能否完全匹配原文,若不能,进行相应修改后再输出。
- ---
- 这个新的修复步骤,是否在日志和前端思考过程输出中打印了?如果没有,请补充
- ---
- 重建报错: [修复] text-anchored 重建不可行:text segment 在原文中找不到(从位置 230 起):'指挥员仍然感觉意犹未尽:"每次训练,都是一次全新挑战!"\n\n'
- 就是因为LLM容易出现幻觉,比如,就算让LLM原样输出,它也容易把“”符号输出为""符号,或者出现一些小的问题。所以重建并不是只重建{{}}内的部分,还需要针对{{}}外的部分进行校验和修复,且保持最小的编辑距离。
- ---
- “导入文本”和“提取完成”后,在渲染文本中的组件时,请把每个组件对应的关键信息值、文中展示值打印出来,我查看一下,现在还有问题。
- ---
- @DocumentParse.vue文件中,第341行左右,
- if (ch === '|') {
- fields.push(buf)
- buf = ''
- continue
- }
- 这里有问题,分隔符为“||”而非“|”,修复它。这么明显的问题,为什么会出现???
- ---------------------------------------
- 你是本项目的“会话3:后端设计与实现工程师”。
- 项目名称:方案计划文档管理系统。
- 你的长期职责是负责后端业务设计、MySQL持久化、文件存储、REST接口、权限、安全、审计、测试和前后端联调支持。
- 一、工作边界
- 你主要只允许修改 backend/**。
- 不修改 frontend/**。
- 不自行修改以下统领文档:FUNCTION_AND_API_SPECIFICATION.md
- CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 如果需求、数据库或接口设计存在问题,只提交“变更建议”,等待统领会话批准。
- 现有backend/src中的AI抽取、标注、校验和修复代码不在本阶段范围内,不得无关重构。
- 不接入Milvus,不实现向量化。
- 不实现电子签章和审批流程。
- 不考虑国产数据库和操作系统。
- 结构化数据库使用MySQL 8。
- 文件存储根目录为项目中的backend/dms-storage/。
- 业务接口统一使用/api/v1;现有AI相关/api接口暂时保留。
- 不一次实现全部功能。每次只完成统领会话指定的一个阶段。
- 不自动提交、合并或推送Git,除非我明确要求。
- 保留用户已有修改,不覆盖无关文件。
- 二、必须先阅读
- FUNCTION_AND_API_SPECIFICATION.md
- CODEX_BACKEND_PERSISTENCE_GUIDE.md
- backend/app.py
- backend/src/**
- backend/requirements.txt
- 当前Git状态和后端目录结构
- 三、已确定的数据和业务规则
- 第一阶段最小结构包含:sys_organization
- sys_user
- doc_category
- doc_document
- doc_attachment_binding
- doc_permission
- sys_audit_log
- 所有业务表采用创建时间、更新时间、删除时间、逻辑删除和rowVersion。
- 允许名称、路径、计数和日志快照字段适当冗余。
- 主案与子方案使用parent_document_id表达一对多关系。
- 共享附件的document_type为ATTACHMENT,parent_document_id为空。
- 主案与共享附件通过doc_attachment_binding建立多对多关系。
- 同一主案和附件只能存在一条有效挂载关系。
- 解除挂载只逻辑删除关系,不删除附件。
- 共享附件对所有已登录用户共享,不写doc_permission。
- 删除仍在挂载的附件返回409 ATTACHMENT_IN_USE。
- 文件写入backend/dms-storage/,数据库只保存相对路径。
- 文件上传必须具备数据库事务和文件失败补偿。
- 数据库字段使用snake_case,JSON字段使用lowerCamelCase。
- 接口使用统一响应、分页、错误码和requestId。
- 现有AI代码不得与文档管理业务强耦合。
- 四、长期实施阶段
- B0:后端现状、数据库和接口设计核对
- B1:MySQL、迁移、配置、统一响应和OpenAPI骨架
- B2:登录、用户、组织和审计基础
- B3:方案分类
- B4:主案、子方案和共享附件只读接口
- B5:文件上传、预览、下载、逻辑删除和恢复
- B6:共享附件挂载和解除挂载
- B7:文档权限
- B8:日志与统计
- B9:集成测试、安全检查和清理
- 在当前轮次只执行B0,不修改任何代码。
- 五、本轮任务:B0
- 请只读分析当前后端,并输出:
- 当前Flask后端结构、既有接口和AI模块边界。
- 在不影响现有AI接口的前提下,业务后端建议的模块目录。
- MySQL 7张核心表的最终逻辑核对。
- 必要索引、唯一性约束、外键取舍和事务边界。
- backend/dms-storage/文件目录、上传流程和失败补偿设计。
- FUNCTION_AND_API_SPECIFICATION.md中全部业务接口的实现优先级。
- 拟使用的MySQL驱动、ORM或迁移工具建议及理由,但不要安装。
- OpenAPI文件建议位置和组织方式。
- 现有接口与新/api/v1接口可能发生的冲突。
- 需要统领会话裁决的事项。
- B1阶段建议新增和修改的具体文件,但不要实际修改。
- 输出格式固定为:
- 【阶段】
- 【现有后端分析】
- 【建议模块结构】
- 【数据库核对】
- 【文件存储设计】
- 【接口实施顺序】
- 【技术选型建议】
- 【冲突与待确认】
- 【本轮未执行】
- 【下一阶段建议】
- 完成B0后立即停止,不要继续B1。
- -------------------------------------------------------------------------------------------------
- 【会话身份】
- 你是“会话3:后端设计与实现工程师”。
- 你负责本项目的后端设计、数据库设计、持久化实现、文件存储、接口实现、后端测试及后续与前端联调。
- 本轮执行阶段:
- B1:DMS后端基础设施、七张数据库表、初始迁移、存储目录和OpenAPI公共骨架
- B0现状分析已经通过统领会话审核。本轮允许修改后端代码,但不得提前实现具体业务接口。
- --------------------------------------------------
- 一、强制加载的契约
- --------------------------------------------------
- 执行任何操作前,必须完整读取:
- 1. DMS_FUNCTION_CONTRACT.md
- 2. DMS_API_CONTRACT.md
- 这两份文件是本阶段强制执行契约:
- - DMS_FUNCTION_CONTRACT.md 是业务规则、数据边界、权限和存储规则的最高执行依据。
- - DMS_API_CONTRACT.md 是接口路径、字段、DTO、枚举、响应和错误码的最高执行依据。
- 以下文件只作为背景和数据库字段设计参考:
- 3. FUNCTION_AND_API_SPECIFICATION.md
- 4. CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 约束优先级:
- 1. 用户或统领会话最新明确确认的要求
- 2. DMS_FUNCTION_CONTRACT.md
- 3. DMS_API_CONTRACT.md
- 4. FUNCTION_AND_API_SPECIFICATION.md
- 5. CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 6. 当前代码和历史实现
- 低优先级材料与新契约冲突时,以新契约为准。
- 不得自行修改两份新契约。
- 不得为了兼容旧文档实现废止接口。
- 不得自行增加第八张业务表。
- 发现契约冲突或数据库无法严格表达的规则时,应停止相关部分并提交统领会话裁决,不得自行改变业务语义。
- --------------------------------------------------
- 二、本轮目标
- --------------------------------------------------
- 本轮只建设DMS后端基础设施:
- 1. 独立DMS模块结构。
- 2. MySQL数据库配置。
- 3. SQLAlchemy模型。
- 4. 七张核心表。
- 5. Alembic初始迁移。
- 6. 统一响应、异常、分页和requestId。
- 7. /api/v1 Blueprint。
- 8. /api/v1/health。
- 9. Bearer认证扩展骨架。
- 10. backend/dms-storage/目录骨架。
- 11. OpenAPI公共组件骨架。
- 12. 后端基础自动化测试。
- 本轮不实现登录、分类、文档、附件、挂载、权限、审计查询等具体业务接口。
- --------------------------------------------------
- 三、现有系统保护边界
- --------------------------------------------------
- 必须保护:
- - backend/src/**
- - 现有AI抽取、标注、校验和修复模块
- - 现有/api/*接口
- - 现有AI数据和测试
- 要求:
- 1. 新DMS业务放入backend/dms/。
- 2. 新接口统一注册到/api/v1。
- 3. 现有旧/api/*不能自动套用DMS统一响应。
- 4. 现有旧/api/*不能自动要求DMS登录。
- 5. app.py只允许做最小化DMS初始化和Blueprint注册。
- 6. 不得无关重构现有AI代码。
- 7. 不得改变旧/api/health的响应结构和行为。
- --------------------------------------------------
- 四、本轮允许修改范围
- --------------------------------------------------
- 允许新增或修改:
- backend/dms/**
- backend/migrations/**
- backend/openapi/**
- backend/tests/dms/**
- backend/dms-storage/**
- backend/requirements.txt
- backend/.env.example
- backend/.gitignore
- 项目根.gitignore(仅在确有必要时做最小修改)
- backend/app.py(仅最小化注册)
- 不得修改:
- frontend/**
- DMS_FUNCTION_CONTRACT.md
- DMS_API_CONTRACT.md
- FUNCTION_AND_API_SPECIFICATION.md
- CODEX_BACKEND_PERSISTENCE_GUIDE.md
- backend/src/**
- 不得进行Git提交、推送、合并、重置、清理或覆盖用户改动。
- --------------------------------------------------
- 五、技术栈
- --------------------------------------------------
- 采用:
- - Flask
- - SQLAlchemy 2.x
- - Flask-SQLAlchemy 3.1.x
- - PyMySQL
- - Alembic
- - pytest
- - MySQL 8.x
- - 同步数据库访问
- - READ COMMITTED
- 不得引入:
- - 异步ORM
- - FastAPI替换
- - Milvus
- - Celery或其他任务队列
- - 文档向量化
- - Office转换服务
- - 动态RBAC平台
- - 新AI框架
- --------------------------------------------------
- 六、建议模块结构
- --------------------------------------------------
- 建议:
- backend/dms/
- - __init__.py
- - config.py
- - extensions.py
- backend/dms/common/
- - errors.py
- - response.py
- - request_context.py
- - pagination.py
- - enums.py
- backend/dms/database/
- - base.py
- - transaction.py
- backend/dms/models/
- - organization.py
- - user.py
- - category.py
- - document.py
- - attachment_binding.py
- - permission.py
- - audit_log.py
- backend/dms/security/
- - auth_context.py
- - decorators.py
- backend/dms/storage/
- - paths.py
- backend/dms/api/v1/
- - blueprint.py
- - health.py
- 可以根据现有工程做小幅调整,但必须维持职责分离。
- B1不要创建大量空repository和空service文件。
- --------------------------------------------------
- 七、七张核心表
- --------------------------------------------------
- 只能建立以下七张核心表:
- 1. sys_organization
- 2. sys_user
- 3. doc_category
- 4. doc_document
- 5. doc_attachment_binding
- 6. doc_permission
- 7. sys_audit_log
- 具体基础字段可参考CODEX_BACKEND_PERSISTENCE_GUIDE.md,但冲突规则必须以两份新契约为准。
- 普通业务表统一包含:
- - id
- - created_by
- - updated_by
- - created_at
- - updated_at
- - deleted_at
- - is_deleted
- - row_version
- 要求:
- - id为BIGINT;
- - is_deleted默认0;
- - row_version默认0;
- - created_at和updated_at精确到毫秒;
- - 时间按UTC管理;
- - 正常查询以后默认过滤is_deleted=0;
- - created_by和updated_by不建立外键;
- - row_version用于乐观锁;
- - 逻辑删除时写入deleted_at;
- - 不使用数据库级联删除。
- --------------------------------------------------
- 八、表级强制裁决
- --------------------------------------------------
- 1. sys_organization
- 必须支持:
- - 组织编码
- - 组织名称
- - 父组织
- - 组织路径冗余
- - 排序
- - ENABLED/DISABLED
- - 逻辑删除
- - 乐观锁
- 要求:
- - org_code永久唯一,逻辑删除后也不得复用;
- - parent_id自外键;
- - ON DELETE RESTRICT或NO ACTION;
- - 不允许级联删除。
- 2. sys_user
- 必须支持:
- - username
- - password_hash
- - real_name
- - organization_id
- - organization_name冗余
- - role_code
- - security_level
- - status
- - auth_version
- - 最近登录时间和IP
- - 通用审计字段
- 要求:
- - username永久唯一;
- - organization_id建立外键并RESTRICT;
- - auth_version默认0;
- - B1不实现真实密码校验和JWT签发;
- - 不增加会话表。
- 3. doc_category
- 必须支持:
- - category_code
- - category_name
- - category_type
- - parent_id
- - category_path
- - sort_no
- - document_count
- - status
- - 通用审计字段
- 要求:
- - category_code永久唯一;
- - parent_id自外键并RESTRICT;
- - document_count只统计有效MAIN和SUB_PLAN;
- - 不统计ATTACHMENT。
- 4. doc_document
- 必须同时承载:
- - MAIN
- - SUB_PLAN
- - ATTACHMENT
- 必须包含:
- - document_name
- - summary
- - document_type
- - document_status
- - security_level
- - visibility_type
- - attachment_type
- - category_id
- - category_name冗余
- - category_path冗余
- - parent_document_id
- - root_document_id
- - tags或等价最小存储
- - original_file_name
- - file_relative_path
- - file_extension
- - mime_type
- - file_size
- - file_hash
- - child_count
- - attachment_count
- - view_count
- - download_count
- - search_text
- - 创建人和更新人名称冗余
- - 通用审计字段
- 强制语义:
- MAIN:
- - parent_document_id=NULL
- - root_document_id最终指向自身
- - category_id必填
- - attachment_type=NULL
- SUB_PLAN:
- - parent_document_id指向有效MAIN
- - root_document_id指向同一MAIN
- - category_id必填
- - attachment_type=NULL
- - 不允许继续嵌套
- ATTACHMENT:
- - parent_document_id=NULL
- - root_document_id=NULL
- - category_id=NULL
- - attachment_type必填
- - security_level=PUBLIC
- - visibility_type=ALL_AUTHENTICATED
- 要求:
- - file_format不重复存储,由file_extension派生;
- - file_hash只建立普通索引,不建立全局唯一约束;
- - 类型和父级语义由服务层最终校验;
- - 可使用合理CHECK约束,但不得依赖CHECK替代服务层验证;
- - root_document_id=id需要插入后回写时,应通过事务处理;
- - 不实现文件版本表。
- 5. doc_attachment_binding
- 必须包含:
- - main_document_id
- - attachment_document_id
- - sort_no
- - active_marker生成列
- - 通用审计字段
- 要求:
- active_marker = IF(is_deleted = 0, 1, NULL)
- 建立:
- UNIQUE(
- main_document_id,
- attachment_document_id,
- active_marker
- )
- 两个文档字段均建立外键到doc_document,并使用RESTRICT或NO ACTION。
- 数据库外键只能保证ID存在,文档类型由服务层校验。
- 6. doc_permission
- 必须包含:
- - document_id
- - subject_type
- - subject_id
- - subject_name冗余
- - can_view
- - can_download
- - can_edit
- - can_manage_permission
- - can_delete
- - active_marker生成列
- - 通用审计字段
- 建立:
- UNIQUE(
- document_id,
- subject_type,
- subject_id,
- active_marker
- )
- 规则:
- - 权限只表达允许,不增加DENY;
- - subject_id是ORG或USER多态引用,不建立单一外键;
- - document_id建立外键并RESTRICT;
- - 第一阶段只为MAIN保存权限;
- - SUB_PLAN动态继承MAIN权限;
- - 不复制子方案权限快照;
- - 不使用INHERITED权限记录;
- - ATTACHMENT不写本表。
- 7. sys_audit_log
- 这是追加写例外表。
- 必须包含:
- - id
- - user_id
- - username
- - real_name
- - organization_id
- - organization_name
- - action_type
- - target_type
- - target_id
- - target_name
- - operation_result
- - failure_reason
- - client_ip
- - user_agent
- - request_id
- - operation_detail
- - created_at
- 明确不包含:
- - updated_at
- - deleted_at
- - is_deleted
- - row_version
- 要求:
- - 不建立业务对象外键;
- - 保存名称快照;
- - 普通业务不得更新或删除;
- - 至少建立时间、用户、组织、动作、目标、结果和requestId索引。
- --------------------------------------------------
- 九、固定枚举
- --------------------------------------------------
- 必须严格读取DMS_API_CONTRACT.md中的全部固定枚举。
- 至少包括:
- RoleCode:
- - USER
- - ADMIN
- - AUDITOR
- AllowedModule:
- - DOCUMENT_BROWSER
- - BACKEND_MANAGEMENT
- - AUDIT_LOG
- DocumentType:
- - MAIN
- - SUB_PLAN
- - ATTACHMENT
- DocumentStatus:
- - DRAFT
- - PUBLISHED
- - ARCHIVED
- SecurityLevel:
- - PUBLIC
- - INTERNAL
- - SECRET
- - CONFIDENTIAL
- - TOP_SECRET
- 比较值:
- - PUBLIC=10
- - INTERNAL=20
- - SECRET=30
- - CONFIDENTIAL=40
- - TOP_SECRET=50
- VisibilityType:
- - ALL_AUTHENTICATED
- - ORGANIZATION
- - CUSTOM
- AttachmentType:
- - POLICY
- - WORK_STANDARD
- - TABLE
- - DIAGRAM
- - OTHER
- SubjectType:
- - ORG
- - USER
- CategoryType:
- - SCENE
- - STYLE
- - SITUATION
- - VERSION
- - OTHER
- EnabledStatus:
- - ENABLED
- - DISABLED
- 同时建立契约规定的审计动作、审计结果和审计目标枚举。
- 不得自行增加UNKNOWN等兼容值。
- --------------------------------------------------
- 十、统一HTTP基础设施
- --------------------------------------------------
- 只应用于/api/v1 Blueprint。
- 1. 成功响应:
- {
- "code": "OK",
- "message": "success",
- "data": {},
- "requestId": "uuid"
- }
- 不得自行增加timestamp。
- 2. 错误响应:
- {
- "code": "ERROR_CODE",
- "message": "错误说明",
- "details": null,
- "requestId": "uuid"
- }
- details不得省略,无附加内容时为null。
- 3. 分页:
- {
- "items": [],
- "page": 1,
- "pageSize": 20,
- "total": 0,
- "totalPages": 0
- }
- 4. requestId:
- - 接收X-Request-Id;
- - 未提供时生成UUID;
- - JSON响应体包含requestId;
- - 响应头包含相同X-Request-Id;
- - requestId在请求上下文中可供后续服务和审计使用。
- 5. 业务异常:
- 至少建立:
- - 参数错误
- - 未认证
- - 无权限
- - 未找到
- - 冲突
- - 文件格式错误
- - 请求过大
- - 系统错误
- 错误码语义必须与DMS_API_CONTRACT.md一致。
- 6. ID序列化:
- - 数据库使用BIGINT;
- - 对外JSON和OpenAPI使用字符串;
- - 不把BIGINT直接序列化为JSON number。
- 7. Bearer认证:
- B1只建立可扩展骨架或装饰器,不实现:
- - JWT签发
- - JWT验签业务
- - 用户查询
- - auth_version查询
- - 登录和退出接口
- 未实现的认证装饰器不得被业务路由误用。
- --------------------------------------------------
- 十一、Blueprint和健康检查
- --------------------------------------------------
- 建立:
- GET /api/v1/health
- 要求:
- - 无需认证;
- - 使用统一成功响应;
- - 返回X-Request-Id;
- - 不泄露数据库URL、密码、JWT密钥或磁盘绝对路径。
- 不得在B1创建其他业务占位接口。
- 不得实现契约中废止的路径。
- --------------------------------------------------
- 十二、数据库迁移
- --------------------------------------------------
- 使用Alembic创建初始迁移,例如:
- backend/migrations/versions/0001_initial_schema.py
- 要求:
- 1. 面向MySQL 8.x。
- 2. 包含七张表。
- 3. 包含全部必要索引。
- 4. 包含唯一约束。
- 5. 包含外键。
- 6. 包含active_marker生成列。
- 7. 外键使用RESTRICT或NO ACTION。
- 8. 不使用ON DELETE CASCADE。
- 9. downgrade能够按依赖顺序回滚。
- 10. 不使用零散手写SQL作为唯一迁移机制。
- 11. 生成列如果必须使用MySQL专用DDL,应清楚封装并测试。
- 12. 不得声称未实际连接的MySQL迁移已经成功运行。
- 13. 没有测试MySQL时,集成测试应明确skip,而不是伪造通过。
- --------------------------------------------------
- 十三、事务规则
- --------------------------------------------------
- 配置或明确采用:
- READ COMMITTED
- 为后续业务提供:
- - 事务上下文
- - 回滚机制
- - 乐观锁基础
- - SELECT FOR UPDATE使用入口
- - 有限死锁重试的扩展位置
- B1不提前实现具体业务事务。
- 不得在文件流传输期间长期持有数据库事务。
- --------------------------------------------------
- 十四、文件存储目录
- --------------------------------------------------
- 创建:
- backend/dms-storage/
- - original/
- - preview/
- - extracted/
- - temporary/
- - quarantine/
- - recycle/
- 要求:
- 1. 目录结构保留。
- 2. 运行时业务文件不进入Git。
- 3. 可以使用.gitignore或.gitkeep保留目录。
- 4. 默认存储根目录指向backend/dms-storage/。
- 5. 允许DMS_STORAGE_ROOT环境变量覆盖。
- 6. 数据库未来只保存相对路径。
- 7. 不把目录注册为Flask静态目录。
- 8. 不放入示例业务文档。
- 9. B1只建立路径解析和安全校验基础,不实现上传。
- 10. 解析后的路径必须仍在存储根目录内。
- --------------------------------------------------
- 十五、OpenAPI公共骨架
- --------------------------------------------------
- 创建:
- backend/openapi/openapi.yaml
- backend/openapi/components/
- 建议组件:
- - schemas.yaml
- - responses.yaml
- - parameters.yaml
- - security-schemes.yaml
- B1只定义:
- 1. OpenAPI基本信息。
- 2. /api/v1/health。
- 3. Bearer安全方案。
- 4. X-Request-Id请求头。
- 5. 统一成功响应。
- 6. 统一错误响应。
- 7. 分页结构。
- 8. 固定枚举。
- 9. 字符串ID schema。
- 10. date-time schema。
- 所有ID必须定义为:
- type: string
- pattern: '^[0-9]+$'
- B1不得提前定义尚未实现的业务路径。
- 后续业务阶段才逐步将DMS_API_CONTRACT.md转换为完整OpenAPI。
- --------------------------------------------------
- 十六、配置和依赖
- --------------------------------------------------
- 更新backend/requirements.txt,增加B1必要依赖。
- 提供backend/.env.example,至少说明:
- DMS_DATABASE_URL
- DMS_STORAGE_ROOT
- DMS_MAX_UPLOAD_SIZE
- DMS_BATCH_MAX_FILES
- DMS_JWT_SECRET
- 要求:
- - 不写入真实账号密码;
- - 不写入真实JWT密钥;
- - 数据库默认配置不得含用户真实凭据;
- - 不破坏现有AI配置;
- - 真实.env必须被Git忽略;
- - 不在代码中硬编码机器绝对路径。
- --------------------------------------------------
- 十七、测试要求
- --------------------------------------------------
- 至少增加和执行:
- 1. 配置加载测试。
- 2. DMS Blueprint注册测试。
- 3. 旧/api/health行为保持测试。
- 4. 新/api/v1/health统一响应测试。
- 5. X-Request-Id透传测试。
- 6. X-Request-Id自动生成测试。
- 7. 统一错误响应测试。
- 8. 七张模型导入测试。
- 9. SQLAlchemy metadata表数量和表名测试。
- 10. 普通业务表通用字段测试。
- 11. sys_audit_log例外字段测试。
- 12. auth_version字段测试。
- 13. attachment_type字段测试。
- 14. active_marker生成列测试。
- 15. 两个有效唯一约束测试。
- 16. 外键不存在CASCADE测试。
- 17. 关键索引测试。
- 18. OpenAPI文件解析测试。
- 19. OpenAPI健康接口测试。
- 20. OpenAPI字符串ID组件测试。
- 21. 存储路径不能逃逸根目录测试。
- 22. 未配置MySQL测试库时集成测试明确skip。
- 23. 现有AI模块仍可导入。
- 24. 现有后端测试不得因DMS初始化被破坏。
- --------------------------------------------------
- 十八、验证要求
- --------------------------------------------------
- 必须真实执行并报告:
- 1. Python模块导入检查。
- 2. pytest测试。
- 3. Flask应用创建或导入检查。
- 4. Alembic配置检查。
- 5. OpenAPI YAML解析检查。
- 6. SQLAlchemy metadata检查。
- 7. 如果存在可用MySQL测试库,再执行upgrade和downgrade。
- 8. 如果没有MySQL测试库,明确说明未执行真实迁移。
- 不得因为缺少MySQL而使用SQLite结果冒充MySQL迁移验证。
- --------------------------------------------------
- 十九、验收标准
- --------------------------------------------------
- B1完成必须满足:
- 1. 现有AI代码和接口行为不变。
- 2. /api/v1独立注册。
- 3. 七张表模型完整。
- 4. 初始迁移与模型一致。
- 5. active_marker唯一性真实进入迁移。
- 6. sys_audit_log符合追加写例外。
- 7. 文件存储目录安全保留。
- 8. 统一响应、错误和requestId可验证。
- 9. OpenAPI公共骨架可解析。
- 10. 没有提前实现业务接口。
- 11. 没有恢复接口。
- 12. 没有废止路径。
- 13. 没有第八张业务表。
- 14. 测试结果真实可复查。
- --------------------------------------------------
- 二十、完成报告格式
- --------------------------------------------------
- 完成后必须返回:
- 1. 阶段结论
- - B1完成、部分完成或阻塞
- 2. 契约加载情况
- - 确认完整读取了哪些契约文件
- 3. 修改文件清单
- - 每个文件说明用途
- 4. 模块结构
- - 展示backend/dms目录
- 5. 七张表摘要
- - 主要字段
- - 索引
- - 唯一约束
- - 外键
- - 逻辑删除
- - row_version
- - audit_log例外
- 6. 与旧指导文档相比的调整
- - auth_version
- - attachment_type
- - active_marker
- - 子方案动态继承权限
- - 附件固定PUBLIC和ALL_AUTHENTICATED
- - audit_log字段例外
- - 不提供恢复
- 7. 迁移验证
- - 实际验证了什么
- - 是否连接真实MySQL
- - 未验证什么
- 8. 测试结果
- - 命令
- - 退出码
- - 通过、失败和跳过数量
- - 失败原因
- 9. 契约符合性检查
- - 对应DMS_FUNCTION_CONTRACT.md哪些章节
- - 对应DMS_API_CONTRACT.md哪些章节
- - 是否存在偏差
- - 是否增加未授权表、字段、路径或枚举
- - 是否误用了废止接口
- 10. 未实现内容
- - 明确说明属于B2及以后阶段的内容
- 11. 风险和待统领裁决事项
- 12. 下一阶段建议
- - 只提出B2建议,不得自行执行
- 本轮到B1完成后立即停止,等待统领会话验收。
- ----------------------------------------------------------
- 【阶段】B2:认证、当前用户、组织人员查询和本地初始化数据
- 你是会话3:后端设计与实现工程师。
- B1已经通过统领会话验收。本地MySQL已经由统领会话完成建库和初始迁移。
- 本轮允许修改后端代码,只实现认证闭环、组织树、人员查询、最小开发数据初始化及对应OpenAPI和测试。
- 本轮不得进入分类、方案、附件、挂载、文档权限和文件上传等后续业务。
- 一、强制契约
- 执行前必须完整读取:
- 1. DMS_FUNCTION_CONTRACT.md
- 2. DMS_API_CONTRACT.md
- 补充参考:
- 3. FUNCTION_AND_API_SPECIFICATION.md
- 4. CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 优先级:
- 用户或统领会话最新要求
- → DMS_FUNCTION_CONTRACT.md
- → DMS_API_CONTRACT.md
- → 两份旧参考文档
- → 当前代码
- 不得修改两份DMS契约。
- 发现冲突时停止相关实现并报告,不得自行改变接口。
- 二、数据库现状
- 本地MySQL:
- - 主机:localhost
- - 端口:3306
- - 用户名:root
- - 密码:root
- - 数据库:dms
- - MySQL版本:8.4.8
- - 当前迁移:0001_initial_schema
- - 当前业务表:7张
- - sys_user当前为空
- 本轮运行时使用临时环境变量:
- DMS_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms?charset=utf8mb4
- 禁止把root密码写入:
- - Python代码
- - .env.example
- - Git跟踪文件
- - 测试源码
- - OpenAPI文件
- 三、本轮接口范围
- 只实现:
- POST /api/v1/auth/login
- POST /api/v1/auth/logout
- GET /api/v1/users/me
- GET /api/v1/organizations/tree
- GET /api/v1/users
- 不得实现其他业务接口。
- 四、依赖与密码安全
- 采用:
- - PyJWT:JWT签发和验证
- - argon2-cffi:Argon2id密码哈希
- 要求:
- 1. requirements.txt声明必要依赖。
- 2. 数据库不得保存明文密码。
- 3. 日志不得记录密码、密码哈希或完整Token。
- 4. 用户名或密码错误统一返回401 INVALID_CREDENTIALS。
- 5. 不得泄露用户名是否存在。
- 6. JWT密钥必须从DMS_JWT_SECRET读取。
- 7. DMS_JWT_SECRET为空时,除测试配置外,登录签发应拒绝启动或明确失败。
- 8. 不得在代码中设置可用于正式环境的默认密钥。
- 五、JWT契约
- Token至少包含:
- - sub:字符串用户ID
- - username
- - roleCode
- - authVersion
- - iat
- - exp
- - jti
- - iss=dms
- 有效期:
- - keepSignedIn=false:7200秒
- - keepSignedIn=true:604800秒
- 每次鉴权必须:
- 1. 验证签名。
- 2. 验证exp。
- 3. 验证iss。
- 4. 查询用户。
- 5. 检查用户未逻辑删除。
- 6. 检查status=ENABLED。
- 7. 比较Token authVersion与sys_user.auth_version。
- 8. 将用户放入请求级认证上下文。
- 对应错误:
- - TOKEN_INVALID
- - TOKEN_EXPIRED
- - USER_DISABLED
- - AUTH_VERSION_MISMATCH
- 六、登录接口
- POST /api/v1/auth/login
- 请求严格使用:
- {
- "username": "admin",
- "password": "******",
- "keepSignedIn": true
- }
- 登录成功:
- 1. 校验输入。
- 2. 查询有效用户。
- 3. 使用Argon2id验证密码。
- 4. 更新最近登录时间和IP。
- 5. 签发JWT。
- 6. 写LOGIN成功审计。
- 7. 返回DMS_API_CONTRACT.md定义的响应。
- 8. ID必须返回字符串。
- 登录失败:
- 1. 统一返回INVALID_CREDENTIALS。
- 2. 写LOGIN失败审计。
- 3. 未知用户名时userId可以为空。
- 4. 失败审计使用独立短事务。
- 5. 不更新登录信息。
- allowedModules固定映射:
- USER:
- - DOCUMENT_BROWSER
- ADMIN:
- - DOCUMENT_BROWSER
- - BACKEND_MANAGEMENT
- AUDITOR:
- - AUDIT_LOG
- 不得由前端自行推断或覆盖。
- 七、退出接口
- POST /api/v1/auth/logout
- 要求:
- 1. 必须认证。
- 2. 在事务中锁定当前用户。
- 3. auth_version递增。
- 4. row_version递增。
- 5. 写LOGOUT成功审计。
- 6. 同一事务提交。
- 7. 返回统一成功响应。
- 8. 旧Token在退出响应后立即失效。
- 9. 第一阶段明确为“一个终端退出导致该用户全部Token失效”。
- 八、当前用户接口
- GET /api/v1/users/me
- 要求:
- - 必须认证;
- - 返回UserSummary;
- - 所有ID为字符串;
- - 包含allowedModules;
- - 不返回password_hash;
- - 不返回auth_version;
- - 不返回内部数据库字段;
- - organizationId和organizationName来自有效组织数据或受控冗余。
- 九、组织树
- GET /api/v1/organizations/tree
- 本阶段仅ADMIN可调用。
- 支持:
- - keyword
- - status
- 要求:
- 1. 默认只返回有效、未删除组织。
- 2. 按sortNo及稳定次级顺序排序。
- 3. 返回树形children。
- 4. keyword只匹配组织名称或编码。
- 5. 搜索结果必须保留必要祖先路径,使前端仍可展示树。
- 6. ID为字符串。
- 7. 不返回内部绝对路径或数据库对象。
- 十、人员查询
- GET /api/v1/users
- 本阶段仅ADMIN可调用。
- 支持:
- - organizationId
- - includeDescendants
- - keyword
- - status
- - page
- - pageSize
- 要求:
- 1. 返回契约分页结构。
- 2. keyword搜索username和realName。
- 3. includeDescendants=false时只查指定组织。
- 4. includeDescendants=true时包含有效下级组织。
- 5. 不返回密码哈希和auth_version。
- 6. 所有ID为字符串。
- 7. pageSize最大100。
- 8. 默认过滤逻辑删除数据。
- 十一、Bearer认证基础设施
- 完成B1认证骨架:
- - bearer_required装饰器或等价机制
- - current_user/current_auth_context
- - 统一401和403
- - requestId贯穿
- - 不影响旧/api/*接口
- - 不把认证自动套到/api/v1/health
- - 只保护B2新增接口
- 十二、审计
- 本轮实现:
- - LOGIN成功
- - LOGIN失败
- - LOGOUT成功
- 要求:
- 1. 保存用户名、姓名、组织名称快照。
- 2. 保存clientIp、userAgent、requestId。
- 3. 不保存密码和Token。
- 4. 登录成功和退出审计与对应修改处于同一事务。
- 5. 登录失败审计使用独立短事务。
- 6. sys_audit_log仍为追加写。
- 7. 不实现审计查询接口。
- 十三、开发数据初始化
- 实现显式、可重复执行的开发数据初始化命令。
- 不得在应用启动或Alembic迁移时自动插入默认账号。
- 建议形式:
- python -m dms.seed_dev
- 或等价Flask CLI命令。
- 要求:
- 1. 只有显式执行才写数据。
- 2. 密码通过环境变量传入。
- 3. 缺少密码变量时拒绝执行。
- 4. 使用Argon2id生成哈希。
- 5. 初始化操作幂等。
- 6. 不重复创建组织和用户。
- 7. 默认不得覆盖已有用户密码。
- 8. 提供显式覆盖开关时必须谨慎说明。
- 9. 不把开发密码写入源码或提交文件。
- 初始化以下最小数据:
- 组织:
- - ORG_ROOT / 机关
- - ORG_OPS / 作战部
- - ORG_COMMS / 通信部
- 其中作战部、通信部属于机关。
- 用户:
- - admin / ADMIN / TOP_SECRET / 机关
- - auditor / AUDITOR / TOP_SECRET / 机关
- - user / USER / SECRET / 作战部
- 本地执行初始化时,可以只在命令环境中使用:
- DMS_SEED_ADMIN_PASSWORD=Admin@123456
- DMS_SEED_AUDITOR_PASSWORD=Auditor@123456
- DMS_SEED_USER_PASSWORD=User@123456
- 这些仅为本地开发凭据,不得写入Git跟踪文件,完成报告中必须明确提示后续环境更换。
- 十四、OpenAPI
- 同步补充:
- - POST /api/v1/auth/login
- - POST /api/v1/auth/logout
- - GET /api/v1/users/me
- - GET /api/v1/organizations/tree
- - GET /api/v1/users
- 必须完整声明:
- - operationId
- - 请求DTO
- - 响应DTO
- - Bearer安全要求
- - 查询参数
- - 字符串ID
- - 枚举
- - 400/401/403/500
- - 分页结构
- 登录接口和health不声明Bearer要求。
- 不得定义B3及以后路径。
- 十五、MySQL测试
- 禁止在dms主库中执行破坏性测试或downgrade。
- 如需迁移升级、回滚集成测试:
- 1. 创建独立测试库,例如dms_b2_test。
- 2. 测试库名称必须以_test结尾。
- 3. 使用DMS_TEST_DATABASE_URL。
- 4. 测试完成后可以保留测试库供后续阶段使用。
- 5. 不得对dms执行downgrade。
- 6. 不得删除dms。
- B2完成后,在真实dms库执行:
- - 当前迁移检查
- - 开发数据初始化
- - 登录成功验证
- - /users/me验证
- - 组织树验证
- - 人员分页验证
- - 退出后旧Token失效验证
- 十六、测试要求
- 至少覆盖:
- 1. Argon2id密码哈希和验证。
- 2. 登录成功。
- 3. 用户名错误。
- 4. 密码错误。
- 5. 禁用用户。
- 6. keepSignedIn两种有效期。
- 7. JWT签名错误。
- 8. JWT过期。
- 9. authVersion不一致。
- 10. 缺少Bearer。
- 11. 非Bearer认证头。
- 12. /users/me。
- 13. allowedModules映射。
- 14. 退出auth_version递增。
- 15. 退出后旧Token失效。
- 16. 登录成功审计。
- 17. 登录失败审计。
- 18. 退出审计。
- 19. 审计不包含密码和Token。
- 20. 组织树结构。
- 21. 组织关键词保留祖先。
- 22. 人员分页。
- 23. includeDescendants。
- 24. ADMIN权限。
- 25. USER和AUDITOR不能调用管理查询。
- 26. JSON ID均为字符串。
- 27. OpenAPI解析和路径契约。
- 28. 旧/api/*行为不变。
- 29. 现有AI测试不受影响。
- 十七、禁止事项
- - 不修改前端。
- - 不修改两份DMS契约。
- - 不实现分类接口。
- - 不实现文档、附件、挂载、权限、文件接口。
- - 不实现审计查询。
- - 不增加第八张业务表。
- - 不增加刷新Token。
- - 不增加会话表。
- - 不实现动态角色。
- - 不修改backend/src/**。
- - 不提交或推送Git。
- - 不进入B3。
- 十八、完成报告
- 必须返回:
- 1. 阶段结论。
- 2. 契约加载情况。
- 3. 修改文件清单。
- 4. JWT设计和claims。
- 5. 密码哈希方案。
- 6. auth_version处理。
- 7. allowedModules映射。
- 8. 组织和人员查询行为。
- 9. 初始化数据和执行方式。
- 10. 实际MySQL验证结果。
- 11. OpenAPI变化。
- 12. 测试命令、通过数、失败数、跳过数。
- 13. 契约符合性检查。
- 14. 是否存在偏差。
- 15. 尚未实现内容。
- 16. B3建议,但不得执行。
- 本轮完成B2后停止,等待统领会话验收。
- --------------------------------------------
- 【阶段】B2-R1:修正无测试环境变量时的测试失败
- 你是会话3:后端设计与实现工程师。
- 本轮是B2收尾修正,不得进入B3。
- 一、强制读取
- 完整读取:
- 1. DMS_FUNCTION_CONTRACT.md
- 2. DMS_API_CONTRACT.md
- 不得修改契约。
- 二、问题
- 统领会话独立执行:
- python -m pytest -q tests/dms test_annotation_repair.py
- 在未设置DMS测试环境变量时出现:
- KeyError: DMS_TEST_USER_PASSWORD
- 位置:
- backend/tests/dms/conftest.py
- b2_password fixture
- 预期行为:
- - 未配置真实MySQL测试环境变量时,依赖这些变量的集成测试应该明确skip;
- - 不应产生KeyError或测试错误;
- - 普通B1基础测试和不依赖数据库的单元测试仍应执行。
- 三、本轮工作
- 1. 修正b2_password或相关fixture。
- 2. 缺少DMS_TEST_USER_PASSWORD时使用pytest.skip并给出明确原因。
- 3. 检查DMS_TEST_DATABASE_URL、DMS_TEST_JWT_SECRET等fixture是否存在同类问题。
- 4. 不允许使用dms主库运行破坏性测试。
- 5. 不修改认证业务实现。
- 6. 不修改数据库模型和迁移。
- 7. 不修改前端。
- 8. 不增加业务接口。
- 9. 不进入B3。
- 10. 不提交或推送Git。
- 四、必须验证两种模式
- 模式一:不设置测试环境变量
- 执行:
- python -m pytest -q tests/dms test_annotation_repair.py
- 要求:
- - 退出码0;
- - 允许明确skip;
- - 不允许error;
- - 不允许KeyError。
- 模式二:设置完整测试环境
- 使用:
- DMS_TEST_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms_b2_test?charset=utf8mb4
- DMS_TEST_USER_PASSWORD=TestUser@123456
- DMS_TEST_JWT_SECRET=local-test-jwt-secret-not-for-production
- 执行相同测试。
- 要求:
- - 89项测试全部通过;
- - 不连接或清理dms主库;
- - 不执行主库downgrade。
- 五、完成报告
- 返回:
- 1. 修改文件。
- 2. 根因。
- 3. 修正方式。
- 4. 无环境变量测试结果。
- 5. 完整环境变量测试结果。
- 6. 是否修改业务代码。
- 7. 契约符合性检查。
- 完成B2-R1后停止。
- --------------------------------------
- 【统领裁决】B3-C1:分类操作人名称字段
- 统领会话已经完成裁决。
- 选择方案2:
- 不为doc_category增加created_by_name和updated_by_name字段,不创建新的数据库迁移。
- 一、裁决依据
- 1. DMS_FUNCTION_CONTRACT.md未强制要求分类记录保存操作人名称。
- 2. DMS_API_CONTRACT.md中的CategoryNode不包含createdByName和updatedByName。
- 3. doc_category现有created_by和updated_by足以保存操作人ID。
- 4. 不可变的用户、姓名和组织名称快照由sys_audit_log负责。
- 5. 为非接口字段增加迁移不符合当前七表最小设计原则。
- 6. 原B3提示词中的名称快照要求属于提示词过度约束,不是数据库模型缺陷。
- 二、B3要求调整
- 撤销原B3提示词中的以下要求:
- - 分类新增时在doc_category保存createdByName。
- - 分类新增时在doc_category保存updatedByName。
- - 分类编辑时在doc_category更新updatedByName。
- - 分类删除时在doc_category更新updatedByName。
- - 因上述名称字段创建数据库迁移。
- 调整为:
- 分类新增:
- - created_by保存当前用户ID。
- - updated_by保存当前用户ID。
- - created_at和updated_at按模型规则维护。
- - CREATE_CATEGORY审计保存username、real_name和organization_name快照。
- 分类编辑:
- - updated_by保存当前用户ID。
- - updated_at更新。
- - row_version递增。
- - EDIT_CATEGORY审计保存用户、姓名、组织和分类名称快照。
- 分类删除:
- - updated_by保存当前用户ID。
- - updated_at和deleted_at更新。
- - row_version递增。
- - DELETE_CATEGORY审计保存用户、姓名、组织和分类名称快照。
- 三、禁止事项
- 1. 不增加created_by_name。
- 2. 不增加updated_by_name。
- 3. 不创建0002迁移。
- 4. 不修改现有0001迁移。
- 5. 不修改两份DMS契约。
- 6. 不在CategoryNode中增加操作人名称字段。
- 7. 不通过关联查询临时增加未定义API字段。
- 8. 不进入B4。
- 四、继续执行
- 请从B3中断位置继续执行原B3任务。
- 除本裁决明确调整的名称快照要求外,原B3提示词其他内容继续有效,包括:
- - 四个分类接口;
- - 分类树搜索;
- - 分类新增、编辑、移动;
- - 后代路径同步;
- - 删除占用冲突;
- - rowVersion并发控制;
- - 分类审计;
- - 开发分类数据初始化;
- - OpenAPI;
- - 自动化测试;
- - 真实MySQL验证。
- 五、完成报告补充要求
- B3最终报告增加“统领裁决执行情况”章节,明确说明:
- 1. doc_category只保存created_by和updated_by。
- 2. 操作人名称快照保存在sys_audit_log。
- 3. 未新增数据库字段。
- 4. 未创建新迁移。
- 5. 主库迁移仍为0001_initial_schema。
- 6. 该处理属于统领授权,不计为契约偏差。
- 现在继续执行B3,完成后停止,等待统领会话验收。
- -------------------------------------------------------
- 【阶段】B4:主案、子方案、共享附件和挂载关系只读接口
- 你是“会话3:后端设计与实现工程师”。
- B1、B2、B2-R1、B3均已经通过统领会话验收。
- 本轮只实现:
- 1. 主案和子方案分页查询
- 2. 主案、子方案详情
- 3. 主案直属子方案查询
- 4. 共享附件分页查询
- 5. 共享附件详情
- 6. 附件挂载主案查询
- 7. 主案已挂载附件查询
- 8. 文档可见性、密级、状态和allowedActions计算
- 9. 开发演示文档数据初始化
- 10. OpenAPI和自动化测试
- 不得进入文档上传、编辑、删除、附件挂载写入、权限保存、文件预览下载、审计查询和统计接口。
- --------------------------------------------------
- 一、强制契约
- --------------------------------------------------
- 执行前完整读取:
- 1. DMS_FUNCTION_CONTRACT.md
- 2. DMS_API_CONTRACT.md
- 补充参考:
- 3. FUNCTION_AND_API_SPECIFICATION.md
- 4. CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 优先级:
- 用户或统领会话最新明确要求
- → DMS_FUNCTION_CONTRACT.md
- → DMS_API_CONTRACT.md
- → 两份旧参考文档
- → 当前代码
- 不得修改两份DMS契约。
- 发现模型缺口或契约冲突时:
- 1. 停止相关实现。
- 2. 不得自行新增字段、表或迁移。
- 3. 报告具体缺口。
- 4. 等待统领会话裁决。
- --------------------------------------------------
- 二、测试数据库统一规则
- --------------------------------------------------
- 从B4开始,所有后端阶段统一使用:
- 主库:
- dms
- 测试库:
- dms_test
- 本地连接:
- DMS_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms?charset=utf8mb4
- DMS_TEST_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms_test?charset=utf8mb4
- 强制规则:
- 1. 不得创建dms_b4_test。
- 2. 不得创建其他以阶段命名的新测试库。
- 3. 如果dms_test不存在,只创建一次。
- 4. 每个阶段开始前执行alembic upgrade head。
- 5. 测试只清理dms_test数据。
- 6. 禁止在dms主库执行测试清表。
- 7. 禁止对dms主库执行downgrade。
- 8. 禁止删除dms主库。
- 9. 已有dms_b2_test、dms_b3_test不得在本轮删除或修改。
- 10. 后续B5、B6等继续复用dms_test。
- 11. 测试数据使用明确前缀,例如B4_TEST_*。
- 12. 测试结束时清理测试库中的测试数据,或者通过可靠测试隔离恢复基线。
- 如果使用事务回滚进行隔离,必须确认MySQL和Flask-SQLAlchemy会话行为真实有效;不得用SQLite结果代替MySQL验证。
- --------------------------------------------------
- 三、当前运行环境
- --------------------------------------------------
- MySQL:
- - 主机:localhost
- - 端口:3306
- - 用户:root
- - 密码:root
- - 主库:dms
- - MySQL版本:8.4.8
- - 当前迁移:0001_initial_schema
- 后端:
- http://localhost:8754
- 本地开发用户:
- - admin / ADMIN / TOP_SECRET
- - auditor / AUDITOR / TOP_SECRET
- - user / USER / SECRET
- 本地密码只通过环境变量或本地执行命令提供,不得写入源码、OpenAPI或Git文件。
- --------------------------------------------------
- 四、本轮接口范围
- --------------------------------------------------
- 只实现:
- GET /api/v1/documents
- GET /api/v1/documents/{id}
- GET /api/v1/main-plans/{id}/sub-plans
- GET /api/v1/attachments
- GET /api/v1/attachments/{id}
- GET /api/v1/attachments/{id}/main-plans
- GET /api/v1/main-plans/{id}/attachments
- 不得实现:
- POST /documents
- PUT /documents/{id}
- DELETE /documents/{id}
- POST /documents/batch-import
- POST /attachments
- PUT /attachments/{id}
- DELETE /attachments/{id}
- POST /attachments/batch-import
- POST /main-plans/{id}/attachments/bind
- DELETE /main-plans/{id}/attachments/{attachmentId}
- GET或PUT文档权限
- 文件preview或download
- 审计查询
- 统计查询
- 恢复接口
- 任何废止路径
- --------------------------------------------------
- 五、服务结构
- --------------------------------------------------
- 建议新增:
- backend/dms/services/document_query_service.py
- backend/dms/services/attachment_query_service.py
- backend/dms/services/authorization_service.py
- backend/dms/api/v1/documents.py
- backend/dms/api/v1/attachments.py
- backend/dms/api/v1/main_plans.py
- 可以根据现有结构合理调整。
- 要求:
- 1. 路由层只处理HTTP输入输出。
- 2. 查询和业务过滤位于service。
- 3. 权限、密级、状态和allowedActions集中计算。
- 4. 不在各路由复制权限逻辑。
- 5. 不在路由中直接拼接复杂SQL。
- 6. 不修改现有认证、分类和AI模块行为。
- 7. 不增加空repository或无意义抽象。
- --------------------------------------------------
- 六、访问与权限判定
- --------------------------------------------------
- 方案访问顺序严格为:
- 1. 用户已经认证。
- 2. 用户状态为ENABLED。
- 3. 文档未逻辑删除。
- 4. 文档类型正确。
- 5. 文档状态检查。
- 6. 用户密级大于或等于文档密级。
- 7. ADMIN业务特权。
- 8. visibilityType。
- 9. doc_permission允许记录。
- 10. 计算具体allowedActions。
- 密级比较值:
- - PUBLIC=10
- - INTERNAL=20
- - SECRET=30
- - CONFIDENTIAL=40
- - TOP_SECRET=50
- 状态规则:
- 普通USER:
- - 只允许查询PUBLISHED方案。
- - DRAFT和ARCHIVED不可见。
- - 仍需通过密级和ACL。
- ADMIN:
- - 可以查询DRAFT、PUBLISHED和ARCHIVED。
- - 仍需通过密级检查。
- - 开发admin为TOP_SECRET,因此能够查看全部开发数据。
- AUDITOR:
- - 审计角色不自动获得主案和子方案访问权。
- - GET /documents、文档详情和子方案接口默认返回403。
- - 共享附件仍按“全部有效登录用户共享”规则允许查看元数据。
- --------------------------------------------------
- 七、可见范围
- --------------------------------------------------
- ALL_AUTHENTICATED:
- - 通过认证、状态、文档状态和密级检查后可见。
- - 不要求doc_permission记录。
- ORGANIZATION:
- - 只使用ORG类型允许权限。
- - 用户属于授权组织自身或其有效下级组织时可见。
- - 不使用USER权限记录。
- - 组织上下级关系必须通过有效组织树判断。
- CUSTOM:
- - 使用ORG和USER允许权限。
- - 用户直接允许或所属组织命中时可见。
- - ORG和USER取并集。
- - 第一阶段没有显式拒绝。
- 没有匹配允许权限时拒绝访问。
- SUB_PLAN:
- - 不读取自身doc_permission。
- - 动态继承root_document_id所指向主案的visibilityType和ACL。
- - 子方案仍使用自身securityLevel和documentStatus。
- - root主案无效时,子方案不可见并记录系统一致性问题。
- ATTACHMENT:
- - 不读取doc_permission。
- - 固定PUBLIC。
- - 固定ALL_AUTHENTICATED。
- - 所有ENABLED登录用户可查询。
- --------------------------------------------------
- 八、allowedActions
- --------------------------------------------------
- 返回值只能使用契约枚举。
- USER对MAIN、SUB_PLAN:
- - 具有查看权限时返回VIEW。
- - 具有下载权限时返回DOWNLOAD。
- - 不返回EDIT、DELETE、CONFIG_PERMISSION。
- - 不返回BIND_ATTACHMENT或UNBIND_ATTACHMENT。
- ADMIN对MAIN:
- - VIEW
- - DOWNLOAD
- - EDIT
- - CONFIG_PERMISSION
- - DELETE
- - BIND_ATTACHMENT
- - 如果当前主案存在有效附件挂载,可返回UNBIND_ATTACHMENT。
- ADMIN对SUB_PLAN:
- - VIEW
- - DOWNLOAD
- - EDIT
- - DELETE
- - 不返回CONFIG_PERMISSION。
- - 不返回BIND_ATTACHMENT和UNBIND_ATTACHMENT。
- 共享附件:
- 普通有效登录用户:
- - VIEW
- - DOWNLOAD
- ADMIN额外:
- - EDIT
- - DELETE
- 注意:
- 本轮尚未实现文件下载和写操作接口。
- allowedActions表达业务授权能力,不代表本轮已经实现对应HTTP写接口。OpenAPI和完成报告必须明确当前只开放查询接口。
- --------------------------------------------------
- 九、文档分页查询
- --------------------------------------------------
- 实现:
- GET /api/v1/documents
- 只查询:
- - MAIN
- - SUB_PLAN
- 不得通过该接口查询ATTACHMENT。
- 支持参数:
- - documentType
- - categoryId
- - keyword
- - securityLevel
- - visibilityType
- - status
- - updatedFrom
- - updatedTo
- - sortBy
- - sortDirection
- - page
- - pageSize
- documentType:
- - 支持MAIN
- - 支持SUB_PLAN
- - 支持逗号分隔MAIN,SUB_PLAN
- - 包含ATTACHMENT时返回400 INVALID_ARGUMENT
- - 不传时默认MAIN,SUB_PLAN
- keyword:
- 搜索:
- - documentName
- - summary
- - tags
- - searchText
- 使用MySQL普通检索,不调用AI、Milvus或向量服务。
- categoryId:
- - 必须是有效数字字符串。
- - 按指定分类精确筛选。
- - 本阶段不自动包含下级分类,除非契约已有明确规定。
- - 不存在分类可以返回空列表,不必泄露分类状态。
- 分页:
- - page默认1
- - pageSize默认20
- - pageSize最大100
- sortBy只允许:
- - documentName
- - createdAt
- - updatedAt
- - viewCount
- - downloadCount
- sortDirection:
- - asc
- - desc
- 必须使用白名单,禁止把客户端字段直接拼入SQL。
- 返回:
- PageResult<DocumentSummary>
- 所有ID使用字符串。
- 普通USER必须在SQL查询或可靠服务层过滤中排除无权记录,不能先返回再依赖前端隐藏。
- --------------------------------------------------
- 十、文档详情
- --------------------------------------------------
- 实现:
- GET /api/v1/documents/{id}
- 仅适用于:
- - MAIN
- - SUB_PLAN
- ATTACHMENT调用该接口时:
- - 返回404 RESOURCE_NOT_FOUND,或按契约既定方式处理;
- - 不得通过此接口返回附件详情。
- 规则:
- 1. 检查文档有效性。
- 2. 检查文档类型。
- 3. 检查状态。
- 4. 检查密级。
- 5. 检查可见范围和ACL。
- 6. 返回DocumentDetail。
- 7. 不返回绝对文件路径。
- 8. 不返回password、Token或内部权限查询细节。
- 9. fileRelativePath不得对外返回。
- 10. ID全部为字符串。
- 11. permissionSummary按契约返回。
- 12. 子方案permissionSummary标记动态继承主案。
- 查看行为:
- - 成功查询详情视为VIEW_DOCUMENT。
- - 使用独立短事务更新view_count。
- - 写VIEW_DOCUMENT审计。
- - 审计失败按功能契约既定规则处理。
- - 不在数据库事务中执行长时间文件操作。
- - 本轮不读取磁盘文件。
- 列表查询不增加view_count,不写逐条查看日志。
- --------------------------------------------------
- 十一、主案子方案
- --------------------------------------------------
- 实现:
- GET /api/v1/main-plans/{id}/sub-plans
- 规则:
- 1. id必须指向有效MAIN。
- 2. 主案不存在或类型不正确返回404 MAIN_PLAN_NOT_FOUND。
- 3. 先检查当前用户对主案的访问资格。
- 4. 返回直属SUB_PLAN。
- 5. 不允许继续嵌套。
- 6. 子方案按自身状态和密级再次过滤。
- 7. ACL动态继承主案。
- 8. 支持keyword、status、page、pageSize、sortBy、sortDirection。
- 9. 返回PageResult<DocumentSummary>。
- 10. 不增加主案或子方案view_count。
- 11. 不写逐条VIEW审计。
- --------------------------------------------------
- 十二、共享附件分页
- --------------------------------------------------
- 实现:
- GET /api/v1/attachments
- 支持:
- - keyword
- - attachmentType
- - fileExtension
- - updatedFrom
- - updatedTo
- - sortBy
- - sortDirection
- - page
- - pageSize
- keyword搜索:
- - documentName
- - summary
- - tags
- - searchText
- 规则:
- 1. 只返回ATTACHMENT。
- 2. 默认排除逻辑删除。
- 3. 所有ENABLED登录用户可查询。
- 4. 不使用doc_permission。
- 5. securityLevel固定PUBLIC。
- 6. visibilityType固定ALL_AUTHENTICATED。
- 7. category相关字段返回null。
- 8. attachmentType必填。
- 9. 返回PageResult<DocumentSummary>。
- 10. mountedPlanCount使用有效挂载关系真实统计。
- 11. 不增加view_count。
- 12. 不写逐条查看审计。
- --------------------------------------------------
- 十三、附件详情
- --------------------------------------------------
- 实现:
- GET /api/v1/attachments/{id}
- 规则:
- 1. 必须是有效ATTACHMENT。
- 2. 所有ENABLED登录用户可调用。
- 3. 返回DocumentDetail。
- 4. category相关字段为null。
- 5. permissionSummary表达无ACL。
- 6. 不返回存储绝对路径。
- 7. 成功详情查询更新view_count。
- 8. 写VIEW_DOCUMENT审计,targetType=ATTACHMENT。
- 9. 不读取或返回真实文件流。
- 10. 非ATTACHMENT返回404。
- --------------------------------------------------
- 十四、附件挂载的主案
- --------------------------------------------------
- 实现:
- GET /api/v1/attachments/{id}/main-plans
- 规则:
- 1. id必须是有效ATTACHMENT。
- 2. 只统计有效挂载关系。
- 3. 只返回有效、未删除MAIN。
- 4. ADMIN可以查看全部有效挂载主案。
- 5. 普通USER只能看到自己有权访问的主案。
- 6. AUDITOR不因附件共享而自动获得主案详情,应只返回其有权访问的主案;默认可能为空。
- 7. 返回契约定义的简要主案集合。
- 8. 不返回主案ACL内部细节。
- 9. 不增加view_count。
- 10. 不写VIEW审计。
- --------------------------------------------------
- 十五、主案已挂载附件
- --------------------------------------------------
- 实现:
- GET /api/v1/main-plans/{id}/attachments
- 支持:
- - keyword
- - attachmentType
- - page
- - pageSize
- 规则:
- 1. id必须是有效MAIN。
- 2. 当前用户必须有权查看主案。
- 3. 只返回有效挂载关系。
- 4. 只返回有效ATTACHMENT。
- 5. 返回附件DocumentSummary并增加:
- - bindingId
- - bindingSortNo
- - mountedPlanCount
- 6. 按bindingSortNo和bindingId稳定排序。
- 7. keyword和attachmentType按附件字段过滤。
- 8. 不增加附件或主案view_count。
- 9. 不写逐条查看审计。
- --------------------------------------------------
- 十六、DTO输出
- --------------------------------------------------
- 严格遵循DMS_API_CONTRACT.md:
- DocumentSummary至少包括:
- - id
- - documentName
- - summary
- - documentType
- - status
- - securityLevel
- - visibilityType
- - visibilitySummary
- - categoryId
- - categoryName
- - categoryPath
- - parentDocumentId
- - rootDocumentId
- - attachmentType
- - fileExtension
- - tags
- - childCount
- - attachmentCount
- - viewCount
- - downloadCount
- - createdByName
- - createdAt
- - updatedAt
- - rowVersion
- - allowedActions
- DocumentDetail增加:
- - originalFileName
- - mimeType
- - fileSize
- - fileHash
- - permissionSummary
- 要求:
- 1. JSON字段使用camelCase。
- 2. ID全部使用字符串。
- 3. 数据库BIGINT不能直接输出为number。
- 4. 不返回fileRelativePath。
- 5. 不返回createdBy、updatedBy内部ID,除非契约明确要求。
- 6. 不返回isDeleted、deletedAt。
- 7. 不返回searchText。
- 8. 不返回authVersion。
- 9. tags无值时返回空数组,不返回无法预测的类型。
- 10. allowedActions去重并保持稳定顺序。
- --------------------------------------------------
- 十七、开发演示数据初始化
- --------------------------------------------------
- 为了F4能够替换模拟文档,提供显式、幂等的开发数据初始化命令。
- 建议:
- python -m dms.seed_documents
- 不得在应用启动或Alembic迁移时自动执行。
- 初始化至少包括:
- 主案:
- 1. 2024年度综合应急预案
- - MAIN
- - 分类SCENE_A
- - PUBLISHED
- - INTERNAL
- - ALL_AUTHENTICATED
- 2. 战略物资管理规程
- - MAIN
- - 分类SCENE_B
- - PUBLISHED
- - SECRET
- - ORGANIZATION
- - 授权作战部
- 3. 通信保障方案
- - MAIN
- - 分类SCENE_C
- - PUBLISHED
- - SECRET
- - CUSTOM
- - 直接授权user查看和下载
- 第一个主案的子方案:
- - 人员组织子案
- - 资源组织子案
- - 重点任务子案
- 共享附件至少三个:
- - 装备保障工作规范 / WORK_STANDARD
- - 应急资源清单模板 / TABLE
- - 通信保障流程图 / DIAGRAM
- 挂载关系:
- - 2024年度综合应急预案挂载前两个附件
- - 战略物资管理规程挂载装备保障工作规范
- - 用于验证一个附件挂载多个主案
- 初始化要求:
- 1. 显式执行。
- 2. 幂等。
- 3. 不重复创建。
- 4. 不覆盖已有同名有效业务数据。
- 5. 不恢复已逻辑删除数据。
- 6. 正确维护child_count。
- 7. 正确维护attachment_count。
- 8. 正确维护mountedPlanCount查询结果。
- 9. 正确创建MAIN权限。
- 10. SUB_PLAN不创建权限副本。
- 11. ATTACHMENT不创建ACL。
- 12. searchText正确生成。
- 13. 创建真实有效的最小DOCX演示文件。
- 14. 文件放入backend/dms-storage/original/约定路径。
- 15. 数据库只保存相对路径。
- 16. 使用UUID磁盘文件名。
- 17. 原始文件名保存在数据库。
- 18. 生成SHA-256。
- 19. 生成的DOCX必须能被python-docx重新打开。
- 20. 不创建空文件或不存在路径记录。
- 21. 不调用AI、Milvus或向量化。
- 22. 文件创建失败时补偿数据库记录。
- 23. 数据库失败时清理本次新建的孤儿文件。
- 24. 不修改用户已有文件。
- 25. 输出新增、已存在和失败数量。
- 该命令属于开发数据工具,不是上传业务接口。
- 完成后在真实dms主库显式执行一次。
- --------------------------------------------------
- 十八、OpenAPI
- --------------------------------------------------
- 新增且只新增本轮7个查询接口。
- 必须包含:
- - operationId
- - Bearer认证
- - 查询参数
- - PageResult
- - DocumentSummary
- - DocumentDetail
- - AttachmentBindingSummary
- - 字符串ID
- - allowedActions
- - 200、400、401、403、404、500
- - MAIN_PLAN_NOT_FOUND
- - DOCUMENT_VIEW_FORBIDDEN
- - SECURITY_LEVEL_FORBIDDEN
- - RESOURCE_NOT_FOUND
- 不得提前加入上传、编辑、删除、挂载写、权限和文件路径。
- OpenAPI路径和Flask路由必须完全一致。
- 外部$ref必须有效。
- --------------------------------------------------
- 十九、测试要求
- --------------------------------------------------
- 至少覆盖:
- 1. documents未认证。
- 2. USER文档分页。
- 3. ADMIN文档分页。
- 4. AUDITOR文档分页403。
- 5. MAIN筛选。
- 6. SUB_PLAN筛选。
- 7. MAIN,SUB_PLAN组合筛选。
- 8. ATTACHMENT类型参数拒绝。
- 9. 分类筛选。
- 10. keyword搜索名称。
- 11. keyword搜索摘要或标签。
- 12. 状态过滤。
- 13. 密级过滤。
- 14. 可见范围过滤。
- 15. 非法sortBy拒绝。
- 16. pageSize上限。
- 17. 字符串ID。
- 18. 逻辑删除过滤。
- 19. DRAFT对USER不可见。
- 20. DRAFT对ADMIN可见。
- 21. 密级不足拒绝。
- 22. ALL_AUTHENTICATED。
- 23. ORGANIZATION及下级组织。
- 24. CUSTOM用户授权。
- 25. 无ACL拒绝。
- 26. 子方案动态继承。
- 27. 文档详情。
- 28. 附件不能通过documents详情获取。
- 29. 详情增加view_count。
- 30. 详情写审计。
- 31. 列表不增加view_count。
- 32. 主案子方案分页。
- 33. 非主案调用子方案接口。
- 34. 子方案自身密级过滤。
- 35. attachments未认证。
- 36. USER附件分页。
- 37. AUDITOR附件分页。
- 38. ADMIN附件分页。
- 39. attachmentType过滤。
- 40. fileExtension过滤。
- 41. 附件详情。
- 42. 非附件调用附件详情。
- 43. 附件详情增加view_count和审计。
- 44. 附件挂载主案查询。
- 45. USER只能看到有权主案。
- 46. 主案挂载附件查询。
- 47. bindingId字符串。
- 48. bindingSortNo排序。
- 49. mountedPlanCount。
- 50. allowedActions稳定。
- 51. 响应不泄露fileRelativePath。
- 52. tags始终为数组。
- 53. 开发初始化幂等。
- 54. 开发文件真实存在。
- 55. DOCX可打开。
- 56. SHA-256正确。
- 57. child_count一致。
- 58. attachment_count一致。
- 59. 权限记录符合规则。
- 60. 测试只使用dms_test。
- 61. 无环境变量时skip而非error。
- 62. B2、B3接口回归。
- 63. OpenAPI和路由一致。
- 64. 旧AI接口回归。
- --------------------------------------------------
- 二十、验证要求
- --------------------------------------------------
- 执行:
- python -m compileall -q dms
- 无测试环境变量:
- python -m pytest -q tests/dms test_annotation_repair.py
- 完整测试环境:
- DMS_TEST_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms_test?charset=utf8mb4
- DMS_TEST_USER_PASSWORD=TestUser@123456
- DMS_TEST_JWT_SECRET=local-test-jwt-secret-not-for-production
- python -m pytest -q tests/dms test_annotation_repair.py
- 真实主库只执行:
- 1. alembic current
- 2. seed_documents
- 3. 七个查询接口验证
- 4. 三类账号权限验证
- 5. 计数一致性检查
- 6. 文件存在性和哈希检查
- 不得在主库运行测试清理或downgrade。
- --------------------------------------------------
- 二十一、禁止事项
- --------------------------------------------------
- - 不修改前端。
- - 不修改DMS契约。
- - 不创建新业务表。
- - 不创建阶段专属测试数据库。
- - 不实现上传。
- - 不实现编辑和删除。
- - 不实现附件挂载写操作。
- - 不实现权限保存。
- - 不实现文件预览下载。
- - 不实现审计查询和统计。
- - 不实现恢复接口。
- - 不调用AI或Milvus。
- - 不修改backend/src/**。
- - 不提交或推送Git。
- - 不进入B5。
- --------------------------------------------------
- 二十二、完成报告
- --------------------------------------------------
- 必须返回:
- 1. 阶段结论。
- 2. 契约加载情况。
- 3. 修改文件清单。
- 4. 七个查询接口。
- 5. 权限判定顺序。
- 6. 密级和状态过滤。
- 7. 子方案动态继承。
- 8. allowedActions。
- 9. 分页、搜索和排序。
- 10. 详情查看计数和审计。
- 11. 共享附件查询。
- 12. 挂载关系查询。
- 13. 开发演示数据初始化。
- 14. 真实文件和哈希验证。
- 15. dms主库验证。
- 16. dms_test统一测试库使用情况。
- 17. 测试结果。
- 18. OpenAPI变化。
- 19. 回归测试。
- 20. 契约符合性。
- 21. 是否存在偏差。
- 22. 未实现内容。
- 23. B5建议,但不得执行。
- 完成B4后立即停止,等待统领会话验收。
- --------------------------------------------------
- 【阶段任务】B5:文档与共享附件的上传、批量导入、元数据编辑、逻辑删除及文件读取
- 你是本项目的后端设计与实现工程师。本轮只执行 B5,不得进入 B6,不得修改前端。
- 一、开始前必须加载的约束
- 开始分析或修改前,必须完整读取:
- 1. F:\Project\wsj\document-management-system\DMS_FUNCTION_CONTRACT.md
- 2. F:\Project\wsj\document-management-system\DMS_API_CONTRACT.md
- 以下文档只能作为背景参考;如有冲突,以上述两份 DMS 契约为准:
- 3. F:\Project\wsj\document-management-system\FUNCTION_AND_API_SPECIFICATION.md
- 4. F:\Project\wsj\document-management-system\CODEX_BACKEND_PERSISTENCE_GUIDE.md
- 同时检查:
- 5. backend/openapi/**
- 6. B1—B4 已实现的模型、迁移、存储服务、认证、授权、审计及查询服务
- 7. backend/dms-storage/**
- 8. backend/tests/dms/**
- 9. 当前 Flask 实际路由表
- 10. 当前 MySQL 迁移状态和七张核心表结构
- 不得修改上述两份 DMS 契约。
- 二、已完成并验收的基础
- B1—B4、F1—F4 均已通过统领验收。
- 现有能力包括:
- - JWT认证和三类角色;
- - 组织、人员查询;
- - 分类树和分类管理;
- - 主案、子方案、共享附件只读查询;
- - 主案直属子方案查询;
- - 正向、反向附件挂载关系查询;
- - 集中授权判定;
- - 真实DOCX文件和SHA-256校验;
- - 查看计数和查看审计;
- - OpenAPI及自动化测试基础设施。
- 后端标准地址:
- http://127.0.0.1:8754
- 数据库:
- - 业务主库:dms
- - 唯一自动化测试库:dms_test
- 数据库账号:
- - 用户名:root
- - 密码:root
- 三、统一测试数据库规则
- 本轮继续复用:
- dms_test
- 禁止创建:
- - dms_b5_test
- - dms_b5_verify
- - dms_upload_test
- - 其他阶段专用测试数据库
- 历史库 `dms_b2_test`、`dms_b3_test` 不得连接、清理、降级或删除。
- 自动化测试只能对 `dms_test` 执行测试数据写入、清理和迁移验证。
- 不得:
- - 清理 `dms` 主库;
- - downgrade `dms` 主库;
- - 删除 `dms` 主库业务数据;
- - 使用主库执行自动化测试;
- - 为每个阶段创建新测试库。
- 测试数据库URL继续使用:
- mysql+pymysql://root:root@localhost:3306/dms_test?charset=utf8mb4
- 四、B5范围
- 本轮只新增以下10个接口。
- 方案文档:
- 1. POST /api/v1/documents
- 2. POST /api/v1/documents/batch-import
- 3. PUT /api/v1/documents/{id}
- 4. DELETE /api/v1/documents/{id}
- 共享附件:
- 5. POST /api/v1/attachments
- 6. POST /api/v1/attachments/batch-import
- 7. PUT /api/v1/attachments/{id}
- 8. DELETE /api/v1/attachments/{id}
- 统一文件读取:
- 9. GET /api/v1/documents/{id}/preview
- 10. GET /api/v1/documents/{id}/download
- 本轮不得新增其他业务接口。
- 五、本轮明确不实现
- 不得实现:
- 1. 附件挂载写接口;
- 2. 解除挂载接口;
- 3. 权限读取和保存接口;
- 4. 审计日志查询接口;
- 5. 统计接口;
- 6. 文档恢复接口;
- 7. 恢复页面配套接口;
- 8. 强制删除已挂载附件;
- 9. 子方案独立权限;
- 10. 文档文件替换;
- 11. 复杂版本历史;
- 12. 物理删除文档文件;
- 13. 自动清理逻辑删除文件;
- 14. Office转PDF;
- 15. Office在线预览;
- 16. Milvus或向量化;
- 17. AI模块改造;
- 18. frontend/**修改;
- 19. B6功能;
- 20. Git提交、推送或合并。
- 特别禁止实现:
- POST /api/v1/documents/{id}/restore
- 以及任何其他恢复路径。
- 六、数据库和迁移边界
- B5原则上应复用现有七张表和 `0001_initial_schema`。
- 开始实施前必须核对现有字段是否能够满足:
- - 文件元数据;
- - SHA-256;
- -相对存储路径;
- -附件类型;
- -状态和密级;
- -逻辑删除;
- -rowVersion;
- -创建人和修改人快照;
- -主案子方案计数;
- -附件挂载计数;
- -下载计数;
- -审计日志。
- 如果发现必须新增数据库字段、索引、约束或迁移:
- 1. 立即停止依赖该结构的实现;
- 2. 不得擅自修改 `0001_initial_schema`;
- 3. 不得擅自创建新迁移;
- 4. 向统领会话提交明确的模型缺口、影响接口和建议方案;
- 5. 等待书面裁决。
- 不得为了避免迁移而复用语义不符的字段。
- 七、文件存储规则
- 存储根目录为:
- F:\Project\wsj\document-management-system\backend\dms-storage
- 原始文件存储在:
- backend/dms-storage/original/
- 必须遵守:
- 1. 数据库只保存相对于 `dms-storage` 的路径。
- 2. 数据库不得保存绝对路径。
- 3. 原始文件名仅用于展示和下载文件名。
- 4. 原始文件名不得参与磁盘路径拼接。
- 5. 磁盘文件名必须使用后端生成的UUID。
- 6. 上传文件不得覆盖已有文件。
- 7. 计算并保存真实SHA-256。
- 8. 相同SHA-256允许作为不同业务文档上传。
- 9. 存储目录不得注册为Flask静态资源目录。
- 10. 所有文件读取必须经过认证、授权和业务状态检查。
- 11. 文件路径解析后必须仍位于配置的存储根目录。
- 12. 拒绝绝对路径、`..`、路径穿越和越界符号链接。
- 13. API响应不得返回:
- - fileRelativePath;
- - 绝对路径;
- - 临时文件路径;
- - 服务器目录结构。
- 八、允许的文件类型和安全校验
- 第一阶段只允许:
- - .doc
- - .docx
- - .pdf
- - .xls
- - .xlsx
- 不得只根据扩展名或客户端Content-Type判断。
- 必须同时校验:
- 1. 扩展名;
- 2. 文件头或容器结构;
- 3. 文件类型与扩展名的一致性;
- 4. 文件大小;
- 5. 请求总大小;
- 6. 批量文件数量;
- 7. 空文件;
- 8. 损坏容器。
- 最低校验要求:
- - PDF:验证合法PDF文件头;
- - DOC、XLS:验证OLE/CFB文件头;
- - DOCX:验证ZIP容器以及必要Office结构;
- - XLSX:验证ZIP容器以及必要Office结构;
- - DOCX不得只验证ZIP文件头;
- - XLSX不得只验证ZIP文件头;
- - 不得解压到不受控目录;
- - 容器检查应避免ZIP路径穿越;
- - 损坏、伪造或类型不匹配文件返回契约规定错误。
- 应优先复用Python标准库和现有依赖。新增依赖必须必要、最小化,并在报告中说明原因。
- 九、上传事务和文件补偿
- 单文件上传必须保证数据库和文件系统最终一致。
- 建议流程:
- 1. 校验认证和ADMIN权限;
- 2. 校验请求结构;
- 3. 校验metadata;
- 4. 校验文件大小和类型;
- 5. 写入受控临时文件;
- 6. 计算SHA-256;
- 7. 生成UUID存储名;
- 8. 建立数据库业务记录;
- 9. 写入同事务审计;
- 10. 提交业务事务;
- 11. 将文件安全落入最终目录或采用等价可靠流程;
- 12. 清理临时文件。
- 无论采用哪种顺序,都必须覆盖以下失败补偿:
- - 文件写入失败时不留下数据库记录;
- - 数据库提交失败时不留下孤立新文件;
- - 审计写入失败时业务写入回滚;
- - 临时文件必须清理;
- - 已存在的其他业务文件不得受影响;
- - 不得删除逻辑删除记录对应的原始文件;
- - 不得在异常日志中输出文件正文、Token或密码。
- 需要通过自动化测试验证补偿行为,不能只在代码注释中说明。
- 十、方案文档单文件上传
- 实现:
- POST /api/v1/documents
- 仅ADMIN可调用。
- 请求为 `multipart/form-data`:
- - `file`:单个文件;
- - `metadata`:JSON字符串。
- 主案metadata严格按契约处理:
- - documentName
- - documentType=MAIN
- - summary
- - categoryId
- - securityLevel
- - visibilityType
- - status
- - tags
- 子方案metadata增加:
- - documentType=SUB_PLAN
- - parentDocumentId
- 要求:
- 1. 严格拒绝未知字段。
- 2. `categoryId`、`parentDocumentId`为字符串ID。
- 3. 禁止number ID。
- 4. 子方案父节点必须是有效、未删除的MAIN。
- 5. 子方案不得挂到SUB_PLAN。
- 6. 子方案动态继承根主案权限,不复制ACL。
- 7. 后端生成:
- - 文件身份字段;
- - fileRelativePath;
- - fileHash;
- - fileSize;
- - fileExtension;
- - mimeType;
- - categoryName;
- - categoryPath;
- - rootDocumentId;
- - searchText;
- - 创建人和修改人快照;
- - 时间和rowVersion。
- 8. 主案的父文档字段必须为空。
- 9. 新建子方案后,应在同一业务事务内维护主案 `childCount`及必要版本。
- 10. 维护分类冗余计数和其他现有冗余字段。
- 11. 返回 `DocumentDetail`,HTTP 201。
- 12. 不得返回磁盘路径。
- 13. 写入 `UPLOAD_DOCUMENT` 审计。
- 14. 审计与业务记录在同一事务。
- 十一、方案文档批量导入
- 实现:
- POST /api/v1/documents/batch-import
- 仅ADMIN可调用。
- 请求:
- - 重复字段 `files`
- - `items`:JSON数组字符串
- - `files[n]` 与 `items[n]`按顺序一一对应
- 要求:
- 1. 数量不一致返回:
- HTTP 400
- code=BATCH_MANIFEST_MISMATCH
- 2. 检查批量文件数量和请求总大小。
- 3. 每个文件使用独立业务事务。
- 4. 一个文件失败不得回滚其他成功文件。
- 5. 返回项顺序必须与原请求顺序一致。
- 6. 每项必须包含:
- - index;
- - originalFileName;
- - success;
- - 成功时document;
- - 失败时errorCode和errorMessage。
- 7. 整体HTTP为200。
- 8. 统计:
- - total;
- - successCount;
- - failureCount。
- 9. 单项成功记录真实业务文档和审计。
- 10. 单项失败必须完成文件补偿。
- 11. 不得因单项错误泄露堆栈或服务器路径。
- 12. 写入契约定义的 `BATCH_IMPORT`/`UPLOAD_DOCUMENT`审计语义,不得增加未知动作枚举。
- 13. 批量重试不得误覆盖已有文件。
- 十二、方案文档元数据编辑
- 实现:
- PUT /api/v1/documents/{id}
- 仅ADMIN可调用,只编辑元数据,不替换文件。
- 请求字段严格按契约:
- - documentName
- - summary
- - categoryId
- - securityLevel
- - visibilityType
- - status
- - tags
- - rowVersion
- 禁止修改:
- - documentType;
- - parentDocumentId;
- - rootDocumentId;
- - originalFileName;
- - fileRelativePath;
- - fileExtension;
- - mimeType;
- - fileSize;
- - fileHash;
- - 文件正文。
- 要求:
- 1. 文档必须是MAIN或SUB_PLAN。
- 2. 附件调用此接口必须返回类型错误。
- 3. 校验分类有效性和分类类型规则。
- 4. 使用rowVersion乐观锁。
- 5. 版本不一致返回:
- HTTP 409
- code=DATA_VERSION_CONFLICT
- details.currentRowVersion
- 6. 更新分类时同步categoryName和categoryPath。
- 7. 同步维护searchText。
- 8. 同步维护updatedBy、updatedByName、updatedAt和rowVersion。
- 9. 不得因编辑子方案创建独立ACL。
- 10. 元数据编辑和 `EDIT_DOCUMENT`审计处于同一事务。
- 11. 返回最新 `DocumentDetail`。
- 12. 编辑操作不得增加viewCount或downloadCount。
- 十三、方案文档逻辑删除
- 实现:
- DELETE /api/v1/documents/{id}?rowVersion=<integer>
- 仅ADMIN可调用。
- 要求:
- 1. 只用于MAIN和SUB_PLAN。
- 2. 使用rowVersion乐观锁。
- 3. 不得物理删除数据库记录。
- 4. 不得物理删除原始文件。
- 5. 删除后正常查询不可见。
- 6. 共享附件不得通过该接口删除。
- 删除MAIN:
- - 存在有效直属或间接子方案时返回:
- HTTP 409
- code=MAIN_PLAN_HAS_CHILDREN
- - 不递归删除子方案;
- - 逻辑删除该主案有效ACL;
- - 逻辑删除该主案有效附件挂载关系;
- - 不删除共享附件;
- - 同步维护必要冗余计数和版本。
- 删除SUB_PLAN:
- - 逻辑删除子方案;
- - 更新所属主案childCount;
- - 不影响主案ACL;
- - 不影响共享附件;
- - 不删除挂载文件。
- 成功返回:
- - 字符串id;
- - deleted=true。
- 逻辑删除及关联关系处理、计数维护和 `DELETE_DOCUMENT`审计必须在同一事务。
- 十四、共享附件单文件上传
- 实现:
- POST /api/v1/attachments
- 仅ADMIN可调用。
- 请求为 `multipart/form-data`:
- - file
- - metadata
- metadata严格包含契约允许字段:
- - documentName
- - attachmentType
- - summary
- - tags
- 后端强制设置:
- - documentType=ATTACHMENT
- - securityLevel=PUBLIC
- - visibilityType=ALL_AUTHENTICATED
- - categoryId=null
- - parentDocumentId=null
- - rootDocumentId=null
- 要求:
- 1. 前端即使提交固定字段,也不得允许其覆盖后端强制值。
- 2. 附件不得创建ACL。
- 3. 计算并保存真实文件元数据和SHA-256。
- 4. 新附件mountedPlanCount初始为0。
- 5. 返回 `DocumentDetail`,HTTP 201。
- 6. 写入 `UPLOAD_DOCUMENT`审计,targetType按现有契约使用。
- 7. 业务记录、文件和审计必须符合失败补偿规则。
- 十五、共享附件批量导入
- 实现:
- POST /api/v1/attachments/batch-import
- 要求与方案批量导入一致:
- - 重复 `files`;
- - 顺序对应的 `items`;
- - 每项使用附件metadata;
- - 每个文件独立事务;
- - 一个失败不影响其他成功项;
- - 返回逐文件结果;
- - 文件数量与items数量不一致返回 `BATCH_MANIFEST_MISMATCH`;
- - 完成文件失败补偿;
- - 不创建ACL或分类关系。
- 十六、共享附件元数据编辑
- 实现:
- PUT /api/v1/attachments/{id}
- 仅ADMIN可调用。
- 请求字段:
- - documentName
- - attachmentType
- - summary
- - tags
- - rowVersion
- 要求:
- 1. 只允许ATTACHMENT。
- 2. 使用rowVersion乐观锁。
- 3. 不得修改固定PUBLIC密级。
- 4. 不得修改固定ALL_AUTHENTICATED可见范围。
- 5. 不得修改文件身份。
- 6. 不得替换文件。
- 7. 同步维护searchText和更新人快照。
- 8. 编辑与 `EDIT_DOCUMENT`审计在同一事务。
- 9. 返回最新 `DocumentDetail`。
- 十七、共享附件逻辑删除
- 实现:
- DELETE /api/v1/attachments/{id}?rowVersion=<integer>
- 仅ADMIN可调用。
- 要求:
- 1. 只允许ATTACHMENT。
- 2. 使用rowVersion乐观锁。
- 3. 存在有效挂载时返回:
- HTTP 409
- code=ATTACHMENT_IN_USE
- 4. details至少按契约提供:
- - mountedPlanCount;
- - mainPlans。
- 5. 不得自动解除挂载。
- 6. 不得提供强制删除参数。
- 7. 无有效挂载时允许逻辑删除。
- 8. 不得物理删除原始文件。
- 9. 删除与 `DELETE_DOCUMENT`审计在同一事务。
- 10. 删除后正常附件列表、详情和关系查询不可见。
- 11. 返回字符串ID和 `deleted=true`。
- 十八、统一文件预览
- 实现:
- GET /api/v1/documents/{id}/preview
- 适用于:
- - MAIN
- - SUB_PLAN
- - ATTACHMENT
- 不得增加附件专用preview路径。
- 要求:
- 1. 先认证,再检查用户状态和文档有效性。
- 2. MAIN、SUB_PLAN使用现有集中授权服务校验VIEW。
- 3. ATTACHMENT对所有有效登录用户开放。
- 4. PDF成功返回inline Blob。
- 5. Office文件:
- - DOC
- - DOCX
- - XLS
- - XLSX
- 返回:
- HTTP 415
- code=PREVIEW_UNAVAILABLE
- 6. 不得将Office原文件伪装成HTML或PDF。
- 7. 文件不存在返回:
- HTTP 404
- code=FILE_NOT_FOUND
- 8. 路径越界必须拒绝,并记录系统错误。
- 9. 响应应设置正确Content-Type和安全的Content-Disposition。
- 10. 建议设置 `X-Content-Type-Options: nosniff`。
- 11. 不返回文件路径。
- 12. 预览失败不得增加下载计数。
- 13. 不得因preview读取绕过现有密级和ACL规则。
- 十九、统一文件下载
- 实现:
- GET /api/v1/documents/{id}/download
- 适用于所有三类文档,不得增加附件专用下载路径。
- 权限规则:
- - MAIN、SUB_PLAN必须具备DOWNLOAD能力;
- - ATTACHMENT只要求有效登录用户;
- - ADMIN仍不得绕过用户密级规则;
- - AUDITOR不因审计角色自动获得方案下载权限。
- 成功时:
- 1. 返回真实原始文件。
- 2. 使用数据库保存的原始文件名作为下载名称。
- 3. 文件名必须安全编码,防止响应头注入。
- 4. 设置正确Content-Type。
- 5. 设置attachment Content-Disposition。
- 6. 建议设置 `X-Content-Type-Options: nosniff`。
- 7. 原子更新downloadCount。
- 8. 写入 `DOWNLOAD_DOCUMENT`审计。
- 9. 不得返回fileRelativePath。
- 10. 不得一次请求重复增加下载计数。
- 失败规则:
- - 无权限:403 `DOCUMENT_DOWNLOAD_FORBIDDEN`或契约规定错误;
- - 文件不存在:404 `FILE_NOT_FOUND`;
- - 文档不存在或已删除:404;
- - 未认证或Token失效:401;
- - 文件读取失败不得伪装成成功下载。
- 根据正式契约,下载计数和下载审计采用独立短事务。审计失败应记录系统错误,但第一阶段不阻断已通过鉴权的文件读取。
- 二十、授权与allowedActions
- 必须复用B4集中授权服务,禁止在新接口中复制一套不一致的权限判断。
- 要求:
- 1. 所有写接口仅ADMIN。
- 2. 查看和下载使用集中授权逻辑。
- 3. 子方案权限动态继承根主案。
- 4. 共享附件不读取doc_permission。
- 5. 文档状态、密级、角色、可见范围和ACL的顺序与B4一致。
- 6. 新增、编辑、删除后返回的 `allowedActions`必须基于最新状态实时生成。
- 7. 后端不得相信前端按钮隐藏。
- 8. 不能用allowedActions代替后端鉴权。
- 二十一、审计要求
- 本轮使用契约已有动作:
- - DOWNLOAD_DOCUMENT
- - UPLOAD_DOCUMENT
- - BATCH_IMPORT
- - EDIT_DOCUMENT
- - DELETE_DOCUMENT
- 不得增加未知动作枚举。
- 审计必须包含:
- - 用户ID;
- - 用户名;
- -姓名快照;
- -组织ID;
- -组织名称快照;
- -客户端IP;
- -User-Agent;
- -requestId;
- -targetType;
- -targetId;
- -targetName快照;
- -operationResult;
- -必要操作差异或失败原因。
- 规则:
- 1. 上传、编辑、删除等修改类审计与业务事务一致。
- 2. 修改类审计失败时业务回滚。
- 3. 下载审计采用独立短事务。
- 4. 审计不得保存文件正文、密码、Token或绝对路径。
- 5. `sys_audit_log`不得被修改或删除。
- 二十二、错误处理
- 必须按契约实现并测试相关错误,包括但不限于:
- - INVALID_REQUEST
- - INVALID_ID
- - UNAUTHORIZED
- - FORBIDDEN
- - RESOURCE_NOT_FOUND
- - DOCUMENT_VIEW_FORBIDDEN
- - DOCUMENT_DOWNLOAD_FORBIDDEN
- - UNSUPPORTED_FILE_TYPE
- - PREVIEW_UNAVAILABLE
- - PAYLOAD_TOO_LARGE
- - BATCH_MANIFEST_MISMATCH
- - DATA_VERSION_CONFLICT
- - MAIN_PLAN_HAS_CHILDREN
- - ATTACHMENT_IN_USE
- - FILE_NOT_FOUND
- - INTERNAL_ERROR
- 如果契约已有更精确错误码,以契约为准。
- 所有JSON错误响应必须保持统一结构,并包含requestId。
- Blob成功响应也应保留 `X-Request-Id` 响应头。
- 不得泄露:
- - SQL语句;
- - Python堆栈;
- - 文件绝对路径;
- - JWT;
- - 数据库连接串;
- - 文件正文。
- 二十三、OpenAPI要求
- 更新 backend/openapi,仅增加B5的10个接口及必要DTO、参数、multipart和错误响应。
- 要求:
- 1. 路径、方法和Flask实际路由完全一致。
- 2. operationId唯一。
- 3. multipart/form-data定义准确。
- 4. 批量重复files字段和items JSON字符串描述准确。
- 5. preview/download使用二进制响应定义。
- 6. 201、200、400、401、403、404、409、413、415、500按实际接口声明。
- 7. 字符串ID不得声明为integer。
- 8. 不得加入恢复、挂载写、权限写、审计或统计路径。
- 9. 全部外部 `$ref` 和fragment引用必须可解析。
- 二十四、自动化测试要求
- 必须在统一 `dms_test` 上覆盖,至少包括:
- (一)单文件上传
- - MAIN上传成功;
- - SUB_PLAN上传成功;
- - ATTACHMENT上传成功;
- - 字符串ID;
- - number ID拒绝;
- - 未知字段拒绝;
- - 无效枚举拒绝;
- - 无效分类拒绝;
- - 子方案父级不是MAIN;
- - 非ADMIN返回403;
- - 文件元数据和SHA-256正确;
- - 数据库只保存相对路径;
- - 原始文件名不参与磁盘路径;
- - 同哈希允许多业务文档。
- (二)文件安全
- - 合法PDF;
- - 合法DOCX;
- - 合法XLSX;
- - 合法DOC或XLS的CFB校验;
- - 扩展名和文件头不一致;
- - 损坏ZIP;
- - 普通ZIP伪装DOCX;
- - 普通ZIP伪装XLSX;
- - 空文件;
- - 不支持扩展名;
- - 路径穿越文件名;
- - 超过单文件限制;
- - 超过请求总大小;
- - 超过批量文件数;
- - 临时文件清理;
- - 数据库失败后的文件补偿;
- - 文件失败后的数据库回滚。
- (三)批量导入
- - 全部成功;
- - 部分成功;
- - 全部失败;
- - files/items数量不一致;
- - 返回顺序稳定;
- - 成功失败统计正确;
- - 每文件事务相互隔离;
- - 单项失败不回滚其他项;
- - 失败不留下孤立文件或数据库记录。
- (四)编辑
- - MAIN编辑;
- - SUB_PLAN编辑;
- - ATTACHMENT编辑;
- - 非ADMIN拒绝;
- - rowVersion冲突;
- - 禁止修改文件身份;
- - 禁止修改文档类型和父子关系;
- - 分类冗余更新;
- - searchText更新;
- - 编辑不增加查看或下载计数;
- - 审计与业务事务一致。
- (五)删除
- - MAIN无子方案时逻辑删除;
- - MAIN存在子方案时409;
- - SUB_PLAN逻辑删除并更新主案计数;
- - 删除MAIN逻辑删除ACL和挂载关系;
- - 删除MAIN不删除共享附件;
- - ATTACHMENT未挂载时逻辑删除;
- - ATTACHMENT已挂载时409;
- - 不强制解除挂载;
- - 不物理删除文件;
- - rowVersion冲突;
- - 删除后正常查询不可见;
- - 无恢复接口。
- (六)预览和下载
- - PDF预览成功;
- - Office预览415;
- - 文件缺失404;
- - 路径越界拒绝;
- - 无VIEW权限拒绝预览;
- - 无DOWNLOAD权限拒绝下载;
- - 共享附件有效用户可下载;
- - AUDITOR不能下载无权方案;
- - ADMIN不绕过密级;
- - 下载文件内容与磁盘一致;
- - 下载文件名安全;
- - 下载计数准确加1;
- - 下载审计准确且只写一次;
- - 失败下载不增加计数;
- - 响应不泄露文件路径;
- - X-Request-Id存在。
- (七)回归
- - B1—B4全部测试继续通过;
- - 现有AI测试继续通过;
- - OpenAPI解析和路由一致性通过;
- - 无环境变量模式不得出现KeyError;
- - 测试数据库必须仍为dms_test;
- - 不得连接主库执行清理或downgrade。
- 二十五、真实验证策略
- 自动化测试和写接口验证统一使用 `dms_test`。
- 如需启动真实HTTP服务验证写接口:
- 1. 使用独立端口;
- 2. 数据库指向 `dms_test`;
- 3. 存储根目录指向明确的测试存储目录;
- 4. 不得使用 `dms` 主库上传测试文档;
- 5. 不得污染业务主库存储目录;
- 6. 验证后停止测试服务;
- 7. 只清理明确的测试临时目录;
- 8. 清理前必须确认目录位于指定测试根目录内。
- `dms` 主库只做非破坏性检查:
- - 迁移版本;
- - 表结构;
- - 已有业务数据计数;
- - 已有文件存在性。
- 除非统领会话另行授权,不要向 `dms` 主库写入B5验证数据。
- 二十六、必须执行的验证命令
- 至少执行:
- 1. 完整B1—B5测试;
- 2. 既有AI回归测试;
- 3. python -m compileall -q dms;
- 4. OpenAPI YAML解析和 `$ref`检查;
- 5. Flask实际路由与OpenAPI一致性检查;
- 6. 有测试环境变量的完整测试;
- 7. 无测试环境变量的安全跳过测试。
- 测试环境变量继续使用:
- DMS_TEST_DATABASE_URL=mysql+pymysql://root:root@localhost:3306/dms_test?charset=utf8mb4
- DMS_TEST_USER_PASSWORD=TestUser@123456
- DMS_TEST_JWT_SECRET=local-test-jwt-secret-not-for-production
- 测试凭据不得写入源码、OpenAPI、契约或提交文件。
- 二十七、阻塞规则
- 发生以下情况必须停止并提交统领裁决:
- 1. 需要新增数据库字段或迁移;
- 2. 正式契约与OpenAPI存在冲突;
- 3. 需要修改两份DMS契约;
- 4. 需要新增第11个B5接口;
- 5. 需要实现恢复;
- 6. 需要物理删除文件;
- 7. 需要实现挂载或权限写入;
- 8. 需要修改前端;
- 9. 需要修改AI模块;
- 10. 现有授权服务无法表达契约规则;
- 11. 文件事务无法在不改变契约的情况下保证补偿;
- 12. 需要创建新的测试数据库;
- 13. 真实响应需要增加未定义字段;
- 14. 测试必须清理主库才能继续。
- 不得自行兼容、猜测或扩大范围。
- 二十八、最终报告格式
- 完成后必须输出:
- 1. 阶段结论:B5是否完成,是否停止在B5。
- 2. 契约加载情况。
- 3. 修改文件清单。
- 4. 数据库和迁移检查结果。
- 5. 10个B5接口实现情况。
- 6. 文件存储结构。
- 7. 文件类型及安全校验方案。
- 8. 单文件上传事务边界。
- 9. 文件失败补偿机制。
- 10. 主案和子方案上传结果。
- 11. 共享附件上传结果。
- 12. 两类批量导入结果。
- 13. 文档元数据编辑规则。
- 14. 附件元数据编辑规则。
- 15. 主案、子方案和附件删除规则。
- 16. PDF预览和Office拒绝预览结果。
- 17. 下载授权、计数和审计结果。
- 18. 冗余字段和计数维护结果。
- 19. rowVersion并发控制结果。
- 20. 审计实现结果。
- 21. OpenAPI变化。
- 22. dms_test使用情况。
- 23. 是否创建了任何新测试数据库。
- 24. 完整测试结果。
- 25. 无环境变量测试结果。
- 26. AI和旧阶段回归结果。
- 27. dms主库非破坏检查结果。
- 28. 契约符合性检查。
- 29. 是否存在偏差。
- 30. 未实现内容。
- 31. B6建议,但不得执行。
- 再次强调:
- - 本轮只执行B5。
- - 只复用dms_test。
- - 不创建阶段测试库。
- - 不向dms主库写入测试文档。
- - 不修改前端。
- - 不实现挂载写和权限写。
- - 不实现审计查询和统计。
- - 不实现任何恢复功能。
- - 不物理删除原始文件。
- - 不进入B6。
- - 不提交或推送Git。
- --------------------------------------
|