index.vue 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583
  1. <template>
  2. <div class="pageIndexClass">
  3. <div class="content">
  4. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" :selectConfig="selectConfig"
  5. highlight-current-row :action-list="[
  6. {
  7. text: '新建报价单',
  8. action: () => newPriceSheet(),
  9. },
  10. ]" @get-list="getList">
  11. <template #code="{ item }">
  12. <div style="width: 100%">
  13. <!-- <span style="color: #409eff; cursor: pointer; word-break: break-all" @click="getDtl(item,true)">{{ item.code }}</span> -->
  14. <span style="color: #409eff; cursor: pointer; word-break: break-all" @click="handleOpenDetail(item)">{{ item.code }}</span>
  15. </div>
  16. </template>
  17. <template #status="{ item }">
  18. <div style="width: 100%">
  19. <span :style="{color: item.status ==88? 'red' :''}">{{dictValueLabel(item.status, statusData)}}</span>
  20. </div>
  21. </template>
  22. <template #quotationStatus="{item}">
  23. <div style="width: 100%">
  24. <span
  25. :class="{ 'tag-active-1': item.quotationStatus==1, 'tag-active': item.quotationStatus==2 }">{{dictValueLabel(item.quotationStatus, quotationStatusData)}}</span>
  26. </div>
  27. </template>
  28. <template #amount="{ item }">
  29. <div style="width:100%">
  30. <span class="el-click" @click="getConfirmDtl(item,true)">{{ moneyFormat(item.amount, 2) }}</span>
  31. </div>
  32. </template>
  33. <template #product="{ item }">
  34. <div style="width:100%;">
  35. <el-popover placement="bottom-start" title="" :width="300" trigger="hover">
  36. <div default>
  37. <div v-for="(product,index) in item.quotationProductList">
  38. {{index+1}}、{{product.productName}}
  39. <!-- <span v-if="index<item.quotationProductList.length-1">,</span> -->
  40. </div>
  41. </div>
  42. <template #reference>
  43. <div style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:pointer">
  44. <span v-for="(product,index) in item.quotationProductList">
  45. {{product.productName}}
  46. <span v-if="index<item.quotationProductList.length-1"> , </span>
  47. </span>
  48. </div>
  49. </template>
  50. </el-popover>
  51. </div>
  52. </template>
  53. <template #btn="{item}">
  54. <div style="width: 100%">
  55. <div>
  56. <span v-if="item.status == 0">
  57. <el-button type="primary" text v-debounce @click="getDtl(item, false)" v-hasPermi="['quotation:edit']">修改</el-button>
  58. <el-button type="danger" text v-debounce @click="handleRepeal(item,'/saleQuotation/delete')"
  59. v-hasPermi="['quotation:del']">删除</el-button>
  60. </span>
  61. <span v-if="item.status !=88">
  62. <!-- <el-button type="primary" text v-debounce v-if="item.status == 30 && item.quotationStatus==2"
  63. @click="getDtl(item, false,true)">变更</el-button> -->
  64. <span v-if="item.quotationStatus==2 && !item.extQuotationId && item.confirmStatus==0">
  65. <el-button type="primary" text v-debounce v-hasPermi="['quotation:price:back']" @click="handleBack(item)">退回</el-button>
  66. </span>
  67. <span v-if="item.confirmStatus==2&&item.quotationStatus==2 && !item.extQuotationId">
  68. <el-button type="primary" text v-debounce v-hasPermi="['quotation:price:change']" @click="handleForeign(item)">转对外</el-button>
  69. </span>
  70. <span v-if="item.status !=0 && item.status !=88 && item.confirmStatus==0">
  71. <el-button type="danger" text v-debounce v-hasPermi="['quotation:remove']"
  72. @click="handleRepeal(item,'/saleQuotation/cancellation')">作废</el-button>
  73. </span>
  74. </span>
  75. <span v-if="item.status !=88">
  76. <span v-if="item.confirmStatus==0 && item.quotationStatus==2">
  77. <el-button type="primary" text v-debounce v-hasPermi="['quotation:price:confirm']"
  78. @click="getConfirmDtl(item, false)">价格确认</el-button>
  79. </span>
  80. </span>
  81. </div>
  82. </div>
  83. </template>
  84. </byTable>
  85. </div>
  86. <el-dialog v-if="openAddDialog" v-model="openAddDialog" title="报价单" width="90%" append-to-body>
  87. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
  88. <template #chart>
  89. <div style="width:100%;padding-left:25px">
  90. <div ref="chartDom" style="height:300px"></div>
  91. </div>
  92. </template>
  93. <template #buyer>
  94. <div style="width: 100%">
  95. <el-form-item label="客户名称" prop="buyCorporationId" class="wid100">
  96. <el-select v-model="formData.data.buyCorporationId" filterable remote reserve-keyword placeholder="请输入关键字" remote-show-suffix
  97. :remote-method="remoteMethod" :loading="loadingSearch" @input="remoteMethod" style="width: 100%" @change="changeCustomer">
  98. <el-option v-for="item in customerList" :key="item.value" :label="item.label" :value="item.value" />
  99. </el-select>
  100. </el-form-item>
  101. <!-- <el-row style="width: 100%">
  102. <el-col :span="12">
  103. <el-form-item label="地址" class="wid100 margin-b-0">
  104. <el-row style="padding-right:5px;width:100%">
  105. <el-col :span="6">
  106. <el-form-item label="" prop="buyCountryId" class="margin-b-0 wid100" label-width="0px">
  107. <el-select v-model="formData.data.buyCountryId" placeholder="国家" style="width:100%" filterable
  108. @change="(val) => getCityData(val, '20', true)">
  109. <el-option v-for="item in countryData" :label="item.name" :value="item.id">
  110. </el-option>
  111. </el-select>
  112. </el-form-item>
  113. </el-col>
  114. <el-col :span="6">
  115. <el-form-item label="" prop="provinceName" class="margin-b-0 wid100" label-width="0px">
  116. <selectCity placeholder="省/洲" @change="(val) => getCityData(val, '30', true)" addressId="buyProvinceId"
  117. addressName="provinceName" v-model="formData.data" :data="provinceData">
  118. </selectCity>
  119. </el-form-item>
  120. </el-col>
  121. <el-col :span="6">
  122. <el-form-item label="" prop="cityName" class="margin-b-0 wid100" label-width="0px">
  123. <selectCity placeholder="城市" addressId="buyCityId" addressName="cityName" v-model="formData.data" :data="cityData">
  124. </selectCity>
  125. </el-form-item>
  126. </el-col>
  127. <el-col :span="6">
  128. <el-form-item label="" prop="buyPostalCode" class="margin-b-0" label-width="0px">
  129. <el-input v-model="formData.data.buyPostalCode" placeholder="请输入邮编" />
  130. </el-form-item>
  131. </el-col>
  132. </el-row>
  133. </el-form-item>
  134. </el-col>
  135. <el-col :span="12" style="padding-left:5px">
  136. <el-form-item label="详细地址" prop="buyAddress" class="margin-b-0 wid100">
  137. <el-input v-model="formData.data.buyAddress" type="text" placeholder="请输入详细地址">
  138. </el-input>
  139. </el-form-item>
  140. </el-col>
  141. </el-row> -->
  142. </div>
  143. </template>
  144. <template #commodity>
  145. <div style="width: 100%;padding-left:25px">
  146. <el-button type="warning" @click="clickPushProduct" plain style="margin-bottom: 16px" v-if="!isDetail"
  147. :disabled="!formData.data.companyId">定制</el-button>
  148. <el-button type="primary" @click="openProductCompany = true" plain style="margin-bottom: 16px" v-if="!isDetail"
  149. :disabled="!formData.data.companyId">选择产品库</el-button>
  150. <!-- <el-table :data="formData.data.quotationProductList" style="width: 100%;" default-expand-all>
  151. <el-table-column type="expand" width="50" align="center">
  152. <template #default="scope">
  153. <div style="padding-left:50px">
  154. <div style="margin-bottom:10px; ">
  155. <TitleInfo content='BOM单:'></TitleInfo>
  156. </div>
  157. <el-table :data="scope.row.quotationProductBomList" style="width: 100%;" border class="bom-table">
  158. <el-table-column label="图片" width="80">
  159. <template #default="{ row }">
  160. <div v-if="row.fileUrl">
  161. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  162. </div>
  163. <div v-else></div>
  164. </template>
  165. </el-table-column>
  166. <el-table-column prop="productCode" label="物料编码" width="190" />
  167. <el-table-column prop="productName" label="物料名称" min-width="200" />
  168. <el-table-column label="尺寸 (cm)" width="150">
  169. <template #default="{ row, $index }">
  170. <div style="width: 100%">
  171. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  172. </div>
  173. </template>
  174. </el-table-column>
  175. <el-table-column label="备注" width="180">
  176. <template #default="{ row, $index }">
  177. <div style="width: 100%">
  178. <el-form-item :prop="'quotationProductList.' + scope.$index + '.quotationProductBomList.' + $index + '.remark'"
  179. :rules="rules.remark" :inline-message="true" class="margin-b-0 wid100">
  180. <el-input v-model="row.remark" placeholder="请输入" style="width: 100%" :min="0" />
  181. </el-form-item>
  182. </div>
  183. </template>
  184. </el-table-column>
  185. <el-table-column label="操作" width="60" align="center" fixed="right" v-if="!isDetail">
  186. <template #default="{ row,$index }">
  187. <el-button type="primary" link @click="handleDeleteMaterial(scope.$index,$index)" v-if="row.type==2">删除</el-button>
  188. </template>
  189. </el-table-column>
  190. </el-table>
  191. </div>
  192. </template>
  193. </el-table-column>
  194. <el-table-column label="图片" width="80">
  195. <template #default="{ row }">
  196. <div v-if="row.fileUrl">
  197. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  198. </div>
  199. <div v-else></div>
  200. </template>
  201. </el-table-column>
  202. <el-table-column prop="productCode" label="商品编码" width="190" />
  203. <el-table-column prop="productName" label="商品名称" min-width="200" />
  204. <el-table-column label="尺寸 (cm)" width="150">
  205. <template #default="{ row, $index }">
  206. <div style="width: 100%">
  207. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  208. </div>
  209. </template>
  210. </el-table-column>
  211. <el-table-column prop="productColor" label="颜色" width="100" />
  212. <el-table-column label="数量" width="110">
  213. <template #default="{ row, $index }">
  214. <div style="width: 100%">
  215. <el-form-item :prop="'quotationProductList.' + $index + '.quantity'" :rules="rules.quantity" :inline-message="true"
  216. class="margin-b-0 wid100">
  217. <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="请输入" style="width: 100%" :precision="0"
  218. :controls="false" :min="1" @change="changeQuantity()" />
  219. </el-form-item>
  220. </div>
  221. </template>
  222. </el-table-column>
  223. <el-table-column label="单价" width="110">
  224. <template #default="{ row, $index }">
  225. <div style="width: 100%">
  226. <span v-if="row.price">¥ {{row.price}}</span>
  227. <span v-else>待报价</span>
  228. </div>
  229. </template>
  230. </el-table-column>
  231. <el-table-column prop="amount" label="小计" width="110">
  232. <template #default="{ row, $index }">
  233. <div style="width: 100%">
  234. <span v-if="row.amount">¥ {{row.amount}}</span>
  235. <span v-else>一</span>
  236. </div>
  237. </template>
  238. </el-table-column>
  239. <el-table-column label="操作" width="140" align="center" fixed="right" v-if="!isDetail">
  240. <template #default="{ $index }">
  241. <el-button type="primary" link @click="handleClickSelectMaterial($index)">包材/配件/辅材</el-button>
  242. <el-button type="primary" link @click="handleRemove($index)">删除</el-button>
  243. </template>
  244. </el-table-column>
  245. </el-table> -->
  246. <el-collapse v-model="activeNames">
  247. <el-collapse-item :name="index" v-for="(product,index) in formData.data.quotationProductList" :key="index">
  248. <template #title>
  249. <!-- <TitleInfo :content="'主材'"></TitleInfo> -->
  250. <div style="font-size:14px;font-weight:700;padding-left:25px;width:300px">
  251. 产品编码:{{product.productCode || '定制产品'}}
  252. </div>
  253. <el-form-item label="数量" class="margin-b-0" style="width:300px !important;" :prop="'quotationProductList.' +index + '.quantity'"
  254. :rules="rules.quantity" :inline-message="true" @click.stop>
  255. <el-input-number v-model="product.quantity" placeholder="请输入" style="width: 100%" :precision="0" :controls="false" :min="1"
  256. onmousewheel="return false;" />
  257. </el-form-item>
  258. <el-button text type="primary" style="margin-left:10px" @click="handleRemove(index)">删除</el-button>
  259. </template>
  260. <div style="width:100%">
  261. <div style="margin:10px 0">
  262. <TitleInfo :content="'主材'"></TitleInfo>
  263. </div>
  264. <div style="width: 100%;padding-left:15px">
  265. <el-row>
  266. <el-col :span="12">
  267. <el-form-item :prop="'quotationProductList.' +index + '.rawMaterialId'" :rules="rules.rawMaterialId" :inline-message="true"
  268. label="原材料" class="wid100">
  269. <el-select v-model="product.rawMaterialId" placeholder="请选择" style="width:100%">
  270. <el-option v-for="item in rawMaterialData" :key="item.value" :label="item.label" :value="item.value" />
  271. </el-select>
  272. </el-form-item>
  273. </el-col>
  274. <el-col :span="12">
  275. <el-form-item label="颜色" class="margin-b-0 wid100">
  276. <el-row style="width: 100%">
  277. <el-col :span="12">
  278. <el-form-item prop="productColor" label-width="0px" class="margin-b-0 wid100">
  279. <el-input v-model="product.productColor" placeholder="颜色" />
  280. </el-form-item>
  281. </el-col>
  282. <el-col :span="12">
  283. <el-form-item prop="colorCardCode" label-width="0px" class="margin-b-0 wid100">
  284. <el-input v-model="product.colorCardCode" placeholder="色卡号" />
  285. </el-form-item>
  286. </el-col>
  287. </el-row>
  288. </el-form-item>
  289. </el-col>
  290. </el-row>
  291. <el-row>
  292. <el-col :span="12">
  293. <el-form-item label="尺寸" class="margin-b-0 wid100" required>
  294. <el-row style="width:100%">
  295. <el-col :span="8">
  296. <el-form-item :prop="'quotationProductList.' +index + '.productLength'" :rules="rules.productLength"
  297. :inline-message="true" label-width="0px" class="margin-b-0 wid100">
  298. <el-input-number v-model="product.productLength" placeholder="长 (cm)" style="width: 100%" :precision="2"
  299. :controls="false" :min="0" onmousewheel="return false;" />
  300. </el-form-item>
  301. </el-col>
  302. <el-col :span="8">
  303. <el-form-item :prop="'quotationProductList.' +index + '.productWidth'" :rules="rules.productWidth"
  304. :inline-message="true" label-width="0px" class="margin-b-0 wid100">
  305. <el-input-number v-model="product.productWidth" placeholder="宽 (cm)" style="width: 100%" :precision="2"
  306. :controls="false" :min="0" onmousewheel="return false;" />
  307. </el-form-item>
  308. </el-col>
  309. <el-col :span="8">
  310. <el-form-item :prop="'quotationProductList.' +index + '.productHeight'" :rules="rules.productHeight"
  311. :inline-message="true" label-width="0px" class="margin-b-0 wid100">
  312. <el-input-number v-model="product.productHeight" placeholder="高 (cm)" style="width: 100%" :precision="2"
  313. :controls="false" :min="0" onmousewheel="return false;" />
  314. </el-form-item>
  315. </el-col>
  316. </el-row>
  317. </el-form-item>
  318. </el-col>
  319. <el-col :span="12">
  320. <el-form-item label="净重(kg)" prop="netWeight" class="margin-b-0 wid100">
  321. <el-input-number v-model="product.netWeight" placeholder="请输入" style="width: 100%" :precision="2" :controls="false" :min="0"
  322. onmousewheel="return false;" />
  323. </el-form-item>
  324. </el-col>
  325. </el-row>
  326. </div>
  327. <div style="margin:10px 0">
  328. <TitleInfo :content="'辅材'"></TitleInfo>
  329. </div>
  330. <div style="width: 100%;padding-left:15px">
  331. <el-button type="primary" @click="handleClickSelectMaterial(index)" plain>选择包材/配件/辅材</el-button>
  332. <el-table :data="product.quotationProductBomList" style="width: 100%; margin-top: 16px">
  333. <el-table-column prop="materialName" label="物料名称" min-width="130" />
  334. <el-table-column prop="materialCode" label="物料编码" width="150" />
  335. <el-table-column label="数量" width="150">
  336. <template #default="{ row, $index }">
  337. <div style="width: 100%">
  338. <el-form-item :prop="'quotationProductList.' + index + '.quotationProductBomList.' + $index + '.quantity'"
  339. :rules="rules.quantity" :inline-message="true" class="margin-b-0 wid100">
  340. <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="请输入" style="width: 100%"
  341. :precision="0" :controls="false" :min="1" />
  342. </el-form-item>
  343. </div>
  344. </template>
  345. </el-table-column>
  346. <el-table-column label="操作" width="60" align="center" fixed="right">
  347. <template #default="{ $index }">
  348. <el-button type="primary" link @click="handleRemoveBom(index,$index)">删除</el-button>
  349. </template>
  350. </el-table-column>
  351. </el-table>
  352. </div>
  353. <div style="margin:10px 0">
  354. <TitleInfo :content="'附加工艺要求'"></TitleInfo>
  355. </div>
  356. <div style="width:100%;padding-left:15px">
  357. <div class="small-title">
  358. ① 工艺线路
  359. </div>
  360. <el-row style="width:100%">
  361. <el-col :span="12">
  362. <el-form-item label="工艺产线" class="wid100" :prop="'quotationProductList.' + index + '.technologyId'"
  363. :rules="rules.technologyId" :inline-message="true">
  364. <el-select v-model="product.technologyId" placeholder="请选择" style="width:100%">
  365. <el-option v-for="item in technologyData" :key="item.id" :label="item.name" :value="item.id" />
  366. </el-select>
  367. </el-form-item>
  368. </el-col>
  369. </el-row>
  370. <div class="small-title">
  371. ② LOGO
  372. </div>
  373. <el-row style="width:100%">
  374. <el-col :span="12">
  375. <el-form-item label="LOGO尺寸" class="wid100">
  376. <el-row>
  377. <el-col :span="8">
  378. <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoLength'"
  379. :rules="rules.logoLength" :inline-message="true">
  380. <el-input-number v-model="product.logoLength" placeholder="长 (cm)" style="width: 100%" :precision="2"
  381. :controls="false" :min="0" onmousewheel="return false;" />
  382. </el-form-item>
  383. </el-col>
  384. <el-col :span="8">
  385. <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoWidth'"
  386. :rules="rules.logoWidth" :inline-message="true">
  387. <el-input-number v-model="product.logoWidth" placeholder="宽 (cm)" style="width: 100%" :precision="2" :controls="false"
  388. :min="0" onmousewheel="return false;" />
  389. </el-form-item>
  390. </el-col>
  391. <el-col :span="8">
  392. <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoHeight'"
  393. :rules="rules.logoHeight" :inline-message="true">
  394. <el-input-number v-model="product.logoHeight" placeholder="高 (cm)" style="width: 100%" :precision="2"
  395. :controls="false" :min="0" onmousewheel="return false;" />
  396. </el-form-item>
  397. </el-col>
  398. </el-row>
  399. </el-form-item>
  400. </el-col>
  401. <el-col :span="12">
  402. <el-form-item label="几色印刷" class="wid100">
  403. <el-input-number v-model="product.colorCount" placeholder="请输入" style="width: 100%" :precision="0" :controls="false"
  404. :min="1" onmousewheel="return false;" />
  405. </el-form-item>
  406. </el-col>
  407. </el-row>
  408. <div class="small-title">
  409. ③ 折叠
  410. </div>
  411. <el-row style="width:100%">
  412. <el-col :span="12">
  413. <el-form-item label="是否折叠" class="wid100">
  414. <el-select v-model="product.isFold" placeholder="请选择" style="width:100%">
  415. <el-option :label="'否'" :value="0" />
  416. <el-option :label="'是'" :value="1" />
  417. </el-select>
  418. </el-form-item>
  419. </el-col>
  420. <el-col :span="12">
  421. <el-form-item label="折叠数" class="wid100" :prop="'quotationProductList.' +index + '.foldWay'" v-if="product.isFold==1"
  422. :rules="product.isFold==1?rules.foldWay:''">
  423. <el-select v-model="product.foldWay" placeholder="请选择" style="width:100%">
  424. <el-option v-for="item in foldWayData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  425. </el-select>
  426. </el-form-item>
  427. </el-col>
  428. </el-row>
  429. <div class="small-title">
  430. ④ 包装要求
  431. </div>
  432. <el-row style="width:100%">
  433. <el-col :span="12">
  434. <el-form-item label="包装要求" class="wid100">
  435. <el-select v-model="product.packAsk" placeholder="请选择" style="width:100%" multiple>
  436. <el-option v-for="item in packAskData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  437. </el-select>
  438. </el-form-item>
  439. </el-col>
  440. </el-row>
  441. <div class="small-title">
  442. ⑤ 是否定制
  443. </div>
  444. <el-row style="width:100%">
  445. <el-col :span="12">
  446. <el-form-item prop="isCustomized" label="是否定制" class="wid100">
  447. <el-select v-model="product.isCustomized" placeholder="请选择" style="width:100%">
  448. <el-option :label="'否'" :value="0" />
  449. <el-option :label="'是'" :value="1" />
  450. </el-select>
  451. </el-form-item>
  452. </el-col>
  453. </el-row>
  454. <el-row style="width:100%">
  455. <el-form-item label="定制内容" class="wid100" v-if="product.isCustomized==1">
  456. <table style="width:100%" border class="table">
  457. <tr>
  458. <td style="width:20%">
  459. </td>
  460. <td style="width:40%">附件</td>
  461. <td style="width:40%">备注</td>
  462. </tr>
  463. <tr v-for="(row,sonIndex) in product.quotationProductCustomInfoList" :key="sonIndex">
  464. <td>
  465. <el-checkbox v-model="row.isCheckBox" label="" /> <span style="position:relative;top:-2px">
  466. {{getLabelOne(row.type)}}</span>
  467. </td>
  468. <td>
  469. <el-upload :file-list="row.fileList" :action="uploadUrl" :data="uploadData" :limit="1" :list-type="'text'"
  470. :before-upload="(file)=>handleBeforeUploadOne(file,index,sonIndex)"
  471. :on-success="()=>handleSuccessOne(index,sonIndex)" :on-remove="(file)=>handleRemoveFile(file,index,sonIndex)"
  472. :on-preview="onPreviewFile" :on-exceed="()=>msgTip(`上传文件数量不可大于1`, 2)">
  473. <el-button text type="primary">上传附件</el-button>
  474. </el-upload>
  475. </td>
  476. <td>
  477. <el-form-item :prop="'quotationProductList.' + index + '.quotationProductCustomInfoList.' + sonIndex + '.remark'"
  478. :rules="row.isCheckBox?rules.remark:''" :inline-message="true" class="margin-b-0 wid100">
  479. <el-input v-model="row.remark" placeholder="请输入备注" />
  480. </el-form-item>
  481. </td>
  482. </tr>
  483. </table>
  484. </el-form-item>
  485. </el-row>
  486. </div>
  487. </div>
  488. </el-collapse-item>
  489. </el-collapse>
  490. </div>
  491. </template>
  492. </byForm>
  493. <template #footer v-if="!isDetail">
  494. <el-button @click="openAddDialog = false" size="default" v-debounce>关 闭</el-button>
  495. <el-button type="primary" @click="handleSubmit(0)" size="default" v-debounce v-if="!isChange">暂 存</el-button>
  496. <el-button type="primary" @click="handleSubmit(30)" size="default" v-debounce>提 交</el-button>
  497. </template>
  498. </el-dialog>
  499. <el-dialog v-if="foreignDialog" v-model="foreignDialog" title="转对外报价单" width="90%" append-to-body>
  500. <byForm :formConfig="formConfigOne" :formOption="formOptionOne" v-model="formData.data" :rules="rulesOne" ref="formDomOne"
  501. v-loading="submitLoading">
  502. <template #commodity>
  503. <div style="width: 100%;padding-left:25px">
  504. <el-table :data="formData.data.quotationProductList" style="width: 100%;" row-key="productId">
  505. <el-table-column type="expand" width="50" align="center">
  506. <template #default="scope">
  507. <div style="padding-left:50px">
  508. <div style="margin-bottom:10px; ">
  509. <TitleInfo content='BOM单:'></TitleInfo>
  510. </div>
  511. <el-table :data="scope.row.quotationProductBomList" style="width: 100%;" border class="bom-table">
  512. <el-table-column label="图片" width="80">
  513. <template #default="{ row }">
  514. <div v-if="row.fileUrl">
  515. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  516. </div>
  517. <div v-else></div>
  518. </template>
  519. </el-table-column>
  520. <el-table-column prop="productCode" label="物料编码" width="190" />
  521. <el-table-column prop="productName" label="物料名称" min-width="200" />
  522. <el-table-column label="尺寸 (cm)" width="150">
  523. <template #default="{ row, $index }">
  524. <div style="width: 100%">
  525. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  526. </div>
  527. </template>
  528. </el-table-column>
  529. <!-- <el-table-column label="数量" width="80" prop="quantity">
  530. </el-table-column>
  531. <el-table-column label="总数量" width="80" prop="allQuantity">
  532. </el-table-column>
  533. <el-table-column label="原本单价" width="110" prop="priceCopy">
  534. <template #default="{ row, $index }">
  535. <div style="width: 100%">
  536. ¥ {{row.priceCopy}}
  537. </div>
  538. </template>
  539. </el-table-column>
  540. <el-table-column label="利润点数" width="110">
  541. <template #default="{ row, $index }">
  542. <div style="width: 100%">
  543. <el-form-item :prop="'quotationProductList.' + scope.$index + '.quotationProductBomList.' + $index + '.coefficient'"
  544. :rules="rules.coefficient" :inline-message="true" class="margin-b-0 wid100">
  545. <el-input-number onmousewheel="return false;" v-model="row.coefficient" placeholder="请输入" style="width: 100%"
  546. :precision="2" :controls="false" :min="0" @change="totalAmount()" />
  547. </el-form-item>
  548. </div>
  549. </template>
  550. </el-table-column>
  551. <el-table-column label="单价" width="110" prop="price">
  552. <template #default="{ row, $index }">
  553. <div style="width: 100%">
  554. ¥ {{row.price}}
  555. </div>
  556. </template>
  557. </el-table-column>
  558. <el-table-column prop="amount" label="小计" width="110">
  559. <template #default="{ row, $index }">
  560. <div style="width: 100%">
  561. ¥ {{row.amount}}
  562. </div>
  563. </template>
  564. </el-table-column> -->
  565. <el-table-column label="备注" width="180" prop="remark">
  566. </el-table-column>
  567. </el-table>
  568. </div>
  569. </template>
  570. </el-table-column>
  571. <el-table-column label="图片" width="80">
  572. <template #default="{ row }">
  573. <div v-if="row.fileUrl">
  574. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  575. </div>
  576. <div v-else></div>
  577. </template>
  578. </el-table-column>
  579. <el-table-column prop="productCode" label="商品编码" width="190" />
  580. <el-table-column prop="productName" label="商品名称" min-width="200" />
  581. <el-table-column label="尺寸 (cm)" width="150">
  582. <template #default="{ row, $index }">
  583. <div style="width: 100%">
  584. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  585. </div>
  586. </template>
  587. </el-table-column>
  588. <el-table-column prop="productColor" label="颜色" width="100" />
  589. <el-table-column label="数量" width="110" prop="quantity">
  590. </el-table-column>
  591. <el-table-column label="指导价" width="100" prop="guidePrice">
  592. <template #default="{ row, $index }">
  593. <div style="width: 100%">
  594. <span class="tag-active">{{row.guidePrice}}</span>
  595. </div>
  596. </template>
  597. </el-table-column>
  598. <el-table-column label="最低价" width="100" prop="minPrice">
  599. <template #default="{ row, $index }">
  600. <div style="width: 100%">
  601. <span style="color:red">{{row.minPrice}}</span>
  602. </div>
  603. </template>
  604. </el-table-column>
  605. <el-table-column label="最高价" width="100" prop="maxPrice">
  606. <template #default="{ row, $index }">
  607. <div style="width: 100%">
  608. <span style="color:red">{{row.maxPrice}}</span>
  609. </div>
  610. </template>
  611. </el-table-column>
  612. <el-table-column label="单价" width="110" prop="price">
  613. <template #default="{ row, $index }">
  614. <el-form-item :prop="'quotationProductList.' + $index + '.price'" :rules="rulesOne.price" :inline-message="true"
  615. class="margin-b-0 wid100">
  616. <el-input-number onmousewheel="return false;" v-model="row.price" placeholder="请输入" style="width: 100%" :precision="2"
  617. :controls="false" :min="row.minPrice" @change="changeForeignQuantity()" :max="row.maxPrice" />
  618. </el-form-item>
  619. </template>
  620. </el-table-column>
  621. <el-table-column prop="amount" label="小计" width="110">
  622. <template #default="{ row, $index }">
  623. <div style="width: 100%">
  624. ¥ {{row.amount}}
  625. </div>
  626. </template>
  627. </el-table-column>
  628. </el-table>
  629. </div>
  630. </template>
  631. </byForm>
  632. <template #footer>
  633. <el-button @click="foreignDialog = false" size="default" v-debounce>关 闭</el-button>
  634. <el-button type="primary" @click="handleSubmitOne()" size="default" v-debounce>提 交</el-button>
  635. </template>
  636. </el-dialog>
  637. <el-dialog v-if="confirmDialog" v-model="confirmDialog" title="价格确认" width="90%" append-to-body>
  638. <byForm :formConfig="formConfigTwo" :formOption="formOptionTwo" v-model="formData.dataTwo" :rules="rulesTwo" ref="formDomTwo"
  639. v-loading="submitLoading">
  640. <template #commodity>
  641. <div style="width: 100%;padding-left:25px">
  642. <el-table :data="formData.dataTwo.quotationProductList" style="width: 100%;" row-key="id">
  643. <el-table-column type="expand" width="50" align="center">
  644. <template #default="scope">
  645. <div style="padding-left:50px">
  646. <div style="margin-bottom:10px;">
  647. <TitleInfo content='BOM单:'></TitleInfo>
  648. </div>
  649. <el-table :data="scope.row.quotationProductBomList" style="width: 100%;" border class="bom-table">
  650. <el-table-column label="图片" width="80">
  651. <template #default="{ row }">
  652. <div v-if="row.fileUrl">
  653. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  654. </div>
  655. <div v-else></div>
  656. </template>
  657. </el-table-column>
  658. <el-table-column prop="productCode" label="物料编码" width="190" />
  659. <el-table-column prop="productName" label="物料名称" min-width="200" />
  660. <el-table-column label="尺寸 (cm)" width="150">
  661. <template #default="{ row, $index }">
  662. <div style="width: 100%">
  663. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  664. </div>
  665. </template>
  666. </el-table-column>
  667. <el-table-column label="备注" width="180" prop="remark">
  668. </el-table-column>
  669. </el-table>
  670. </div>
  671. </template>
  672. </el-table-column>
  673. <el-table-column label="图片" width="70" align="center">
  674. <template #default="{ row }">
  675. <div v-if="row.fileUrl">
  676. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  677. </div>
  678. <div v-else></div>
  679. </template>
  680. </el-table-column>
  681. <el-table-column prop="productCode" label="商品编码" width="190" />
  682. <el-table-column prop="productName" label="商品名称" min-width="200" />
  683. <el-table-column label="尺寸 (cm)" width="120">
  684. <template #default="{ row, $index }">
  685. <div style="width: 100%">
  686. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  687. </div>
  688. </template>
  689. </el-table-column>
  690. <el-table-column prop="productColor" label="颜色" width="100" />
  691. <el-table-column label="数量" width="80" prop="quantity">
  692. </el-table-column>
  693. <el-table-column label="工厂单价" width="100" prop="prodPrice">
  694. </el-table-column>
  695. <el-table-column label="指导价" width="120" prop="price">
  696. <template #default="{ row, $index }">
  697. <div style="width: 100%">
  698. <el-form-item :prop="'quotationProductList.' + $index + '.price'" :rules="rulesTwo.price" :inline-message="true"
  699. class="margin-b-0 wid100">
  700. <el-input-number onmousewheel="return false;" v-model="row.price" placeholder="请输入" style="width: 100%" :precision="2"
  701. :controls="false" :min="0" @change="changeQuantityOne" />
  702. </el-form-item>
  703. </div>
  704. </template>
  705. </el-table-column>
  706. <el-table-column label="业务员最低报价" width="125" prop="minPrice">
  707. <template #default="{ row, $index }">
  708. <div style="width: 100%">
  709. <el-form-item :prop="'quotationProductList.' + $index + '.minPrice'" :rules="rulesTwo.minPrice" :inline-message="true"
  710. class="margin-b-0 wid100">
  711. <el-input-number onmousewheel="return false;" v-model="row.minPrice" placeholder="请输入" style="width: 100%" :precision="2"
  712. :controls="false" :min="row.price" @change="changeMinPrice" />
  713. </el-form-item>
  714. </div>
  715. </template>
  716. </el-table-column>
  717. <el-table-column label="上调比列(%)" width="110" prop="amplifyRatio">
  718. <template #default="{ row, $index }">
  719. <div style="width: 100%">
  720. <el-form-item :prop="'quotationProductList.' + $index + '.amplifyRatio'" :rules="rulesTwo.amplifyRatio" :inline-message="true"
  721. class="margin-b-0 wid100">
  722. <el-input-number onmousewheel="return false;" v-model="row.amplifyRatio" placeholder="请输入" style="width: 100%" :precision="2"
  723. :controls="false" :min="1" :max="100" @change="changeMinPrice" />
  724. </el-form-item>
  725. </div>
  726. </template>
  727. </el-table-column>
  728. <el-table-column label="业务员最高报价" width="125" prop="maxPrice">
  729. </el-table-column>
  730. <el-table-column prop="amount" label="小计" width="110">
  731. <template #default="{ row, $index }">
  732. <div style="width: 100%">
  733. ¥ {{row.amount}}
  734. </div>
  735. </template>
  736. </el-table-column>
  737. </el-table>
  738. </div>
  739. </template>
  740. </byForm>
  741. <template #footer v-if="!isDetailData">
  742. <el-button @click="confirmDialog = false" size="default" v-debounce>关 闭</el-button>
  743. <el-button type="primary" size="default" v-debounce @click="confirmSubmit()">提 交</el-button>
  744. </template>
  745. </el-dialog>
  746. <el-dialog v-if="openProductCompany" v-model="openProductCompany" title="产品库" width="90%" append-to-body>
  747. <SelectProduct @selectProduct="selectProduct" :companyId="companyId" :isRawMaterial="'1'" :disablePerm="'1'"></SelectProduct>
  748. <template #footer>
  749. <el-button @click="openProductCompany = false" size="defualt" v-debounce>关 闭</el-button>
  750. </template>
  751. </el-dialog>
  752. <el-dialog :title="'物料选择'" v-model="openSelectMaterial" width="90%" destroy-on-close>
  753. <SelectMaterial :isNeRawMaterial="'1'" @selectMaterial="selectMaterial"></SelectMaterial>
  754. <template #footer>
  755. <el-button @click="openSelectMaterial = false" size="defualt" v-debounce>关 闭</el-button>
  756. </template>
  757. </el-dialog>
  758. <el-dialog v-if="detailDialog" v-model="detailDialog" title="报价详情" width="90%" append-to-body>
  759. <PriceSheetDetailList :rowData="detailRowData" dataType="1" @changeLeftData="changeLeftData"></PriceSheetDetailList>
  760. <template #footer>
  761. <el-button @click="detailDialog = false" size="defualt" v-debounce>关 闭</el-button>
  762. <!-- <el-button type="primary" v-debounce
  763. v-if="leftRowData.quotationStatus==2 && !leftRowData.extQuotationId &&leftRowData.status !=88 &&leftRowData.status !=70"
  764. @click="handleBack(leftRowData)">退回</el-button>
  765. <el-button type="primary" v-debounce
  766. v-if="leftRowData.status == 30 && leftRowData.quotationStatus==2 && leftRowData.status !=88 &&leftRowData.status !=70"
  767. @click="getDtl(leftRowData, false,true)">变更</el-button>
  768. <el-button type="primary" v-debounce
  769. v-if="leftRowData.quotationStatus==2 && !leftRowData.extQuotationId &&leftRowData.status !=88 &&leftRowData.status !=70"
  770. @click="handleForeign(leftRowData)">转对外</el-button>
  771. <el-button type="danger" v-debounce v-if="leftRowData.status !=0 && leftRowData.status !=88 &&leftRowData.status !=70"
  772. @click="handleRepeal(leftRowData,'/saleQuotation/cancellation')">作废</el-button> -->
  773. </template>
  774. </el-dialog>
  775. <el-dialog v-if="backDialog" v-model="backDialog" title="退回" width="50%" append-to-body>
  776. <byForm :formConfig="backFormConfig" :formOption="backFormOption" v-model="formData.backData" :rules="backRules" ref="backFormDom"
  777. v-loading="submitLoading">
  778. </byForm>
  779. <template #footer>
  780. <el-button @click="backDialog = false" size="default" v-debounce>关 闭</el-button>
  781. <el-button type="primary" @click="handleSubmitBack()" size="default" v-debounce>提 交</el-button>
  782. </template>
  783. </el-dialog>
  784. </div>
  785. </template>
  786. <script setup>
  787. import byTable from "@/components/byTable/index";
  788. import moment from "moment";
  789. import byForm from "@/components/byForm/index";
  790. import selectCity from "@/components/selectCity/index.vue";
  791. import SelectProduct from "@/components/product/SelectProduct.vue";
  792. import SelectMaterial from "@/components/product/SelectMaterial.vue";
  793. import * as echarts from "echarts";
  794. import PriceSheetDetailList from "@/views/EHSD/saleContract/PriceSheetDetailList";
  795. const { proxy } = getCurrentInstance();
  796. const uploadData = ref({});
  797. const packAskData = computed(() => proxy.useUserStore().allDict["pack_ask"]);
  798. const foldWayData = computed(() => proxy.useUserStore().allDict["fold_way"]);
  799. const companyId = ref("");
  800. const accountList = ref([]);
  801. const corporationList = ref([]);
  802. const tradeMethods = ref([]);
  803. const accountCurrency = ref([]);
  804. const companyData = ref([]);
  805. const statusData = ref([
  806. {
  807. label: "草稿",
  808. value: 0,
  809. },
  810. {
  811. label: "正常",
  812. value: 30,
  813. },
  814. {
  815. label: "作废",
  816. value: 88,
  817. },
  818. ]);
  819. const quotationStatusData = ref([
  820. {
  821. label: "未报价",
  822. value: 0,
  823. },
  824. {
  825. label: "报价中",
  826. value: 1,
  827. },
  828. {
  829. label: "已报价",
  830. value: 2,
  831. },
  832. ]);
  833. const typeData = ref([
  834. {
  835. label: "内销订单",
  836. value: 1,
  837. },
  838. {
  839. label: "外贸",
  840. value: 2,
  841. },
  842. ]);
  843. const sourceList = ref({
  844. data: [],
  845. pagination: {
  846. total: 0,
  847. pageNum: 1,
  848. pageSize: 10,
  849. keyword: "",
  850. status: "",
  851. type: "",
  852. quotationStatus: "",
  853. companyId: "",
  854. quotationTimeSta: "",
  855. quotationTimeEnd: "",
  856. beginTime: "",
  857. endTime: "",
  858. },
  859. });
  860. const loading = ref(false);
  861. const selectConfig = computed(() => {
  862. return [
  863. {
  864. label: "业务公司",
  865. prop: "ofCompanyId",
  866. data: proxy.useUserStore().allDict["list_company_data"],
  867. },
  868. {
  869. label: "报价单状态",
  870. prop: "status",
  871. data: statusData.value,
  872. },
  873. {
  874. label: "报价单类型",
  875. prop: "type",
  876. data: typeData.value,
  877. },
  878. {
  879. label: "工厂报价状态",
  880. prop: "quotationStatus",
  881. data: quotationStatusData.value,
  882. },
  883. {
  884. label: "报价工厂",
  885. prop: "companyId",
  886. data: companyData.value,
  887. },
  888. {
  889. type: "time",
  890. label: "报价时间",
  891. placeholder: "开始日期",
  892. prop: "quotationTimeSta",
  893. placeholderOne: "结束日期",
  894. propOne: "quotationTimeEnd",
  895. },
  896. // {
  897. // type: "time",
  898. // label: "创建时间",
  899. // placeholder: "开始日期",
  900. // prop: "beginTime",
  901. // placeholderOne: "结束日期",
  902. // propOne: "endTime",
  903. // },
  904. ];
  905. });
  906. const config = computed(() => {
  907. return [
  908. {
  909. attrs: {
  910. label: "业务公司",
  911. prop: "ofCompanyName",
  912. width: 110,
  913. },
  914. },
  915. {
  916. attrs: {
  917. label: "报价单号",
  918. slot: "code",
  919. width: 180,
  920. },
  921. },
  922. {
  923. attrs: {
  924. label: "报价单状态",
  925. slot: "status",
  926. width: 100,
  927. },
  928. },
  929. {
  930. attrs: {
  931. label: "报价单类型",
  932. prop: "type",
  933. width: 100,
  934. },
  935. render(val) {
  936. return proxy.dictValueLabel(val, typeData.value);
  937. },
  938. },
  939. {
  940. attrs: {
  941. label: "报价工厂",
  942. prop: "companyName",
  943. width: 100,
  944. },
  945. },
  946. {
  947. attrs: {
  948. label: "客户名称",
  949. prop: "buyCorporationName",
  950. "min-width": 170,
  951. },
  952. },
  953. {
  954. attrs: {
  955. label: "工厂报价状态",
  956. slot: "quotationStatus",
  957. width: 130,
  958. },
  959. },
  960. {
  961. attrs: {
  962. label: "报价金额",
  963. slot: "amount",
  964. width: 120,
  965. },
  966. },
  967. {
  968. attrs: {
  969. label: "报价时间",
  970. prop: "quotationTime",
  971. width: 160,
  972. },
  973. },
  974. {
  975. attrs: {
  976. label: "报价单产品",
  977. slot: "product",
  978. "min-width": 180,
  979. },
  980. },
  981. {
  982. attrs: {
  983. label: "创建时间",
  984. prop: "createTime",
  985. width: 160,
  986. },
  987. },
  988. {
  989. attrs: {
  990. label: "创建人",
  991. prop: "userName",
  992. width: 80,
  993. },
  994. },
  995. {
  996. attrs: {
  997. label: "操作",
  998. width: 220,
  999. slot: "btn",
  1000. align: "right",
  1001. fixed: "right",
  1002. },
  1003. },
  1004. ];
  1005. });
  1006. const getDict = () => {
  1007. proxy
  1008. .post("/customer/selPage", {
  1009. pageNum: 1,
  1010. pageSize: 50,
  1011. })
  1012. .then((res) => {
  1013. customerList.value = res.rows.map((x) => ({
  1014. ...x,
  1015. label: x.name,
  1016. value: x.id,
  1017. }));
  1018. });
  1019. proxy
  1020. .get("/tenantDept/list", {
  1021. pageNum: 1,
  1022. pageSize: 9999,
  1023. keyword: "",
  1024. tenantId: proxy.useUserStore().user.tenantId,
  1025. type: 0,
  1026. })
  1027. .then((res) => {
  1028. companyData.value = res.data.map((x) => ({
  1029. ...x,
  1030. label: x.deptName,
  1031. value: x.deptId,
  1032. }));
  1033. treeData.value = proxy.handleTree(res.data, "deptId");
  1034. });
  1035. };
  1036. const getList = async (req) => {
  1037. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  1038. loading.value = true;
  1039. proxy.post("/saleQuotation/page", sourceList.value.pagination).then((res) => {
  1040. sourceList.value.data = res.rows;
  1041. sourceList.value.pagination.total = res.total;
  1042. setTimeout(() => {
  1043. loading.value = false;
  1044. }, 200);
  1045. });
  1046. };
  1047. getDict();
  1048. getList();
  1049. const rawMaterialData = ref([]);
  1050. const technologyData = ref([]);
  1051. const getRawMaterialData = () => {
  1052. proxy.post("/productInfo/page", { productClassifyId: 100 }).then((res) => {
  1053. rawMaterialData.value = res.rows.map((x) => ({
  1054. ...x,
  1055. label:
  1056. x.name +
  1057. "," +
  1058. x.customCode +
  1059. "," +
  1060. `${x["length"]}*${x.width}*${x.height}(cm)` +
  1061. "," +
  1062. x.color,
  1063. value: x.id,
  1064. }));
  1065. });
  1066. proxy.post("/technology/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  1067. technologyData.value = res.rows;
  1068. });
  1069. };
  1070. getRawMaterialData();
  1071. const openAddDialog = ref(false);
  1072. const submitLoading = ref(false);
  1073. const modalType = ref("add");
  1074. const newPriceSheet = () => {
  1075. formOption.disabled = false;
  1076. isDetail.value = false;
  1077. isChange.value = false;
  1078. isShowChart.value = false;
  1079. modalType.value = "add";
  1080. openAddDialog.value = true;
  1081. formData.data = {
  1082. type: 1,
  1083. quotationProductList: [],
  1084. };
  1085. };
  1086. const isDetail = ref(false);
  1087. const isChange = ref(false);
  1088. const getFileData = () => {
  1089. let ids = [];
  1090. formData.data.quotationProductList.map((x) => {
  1091. // ids.push(x.productId);
  1092. x.quotationProductBomList.map((y) => {
  1093. ids.push(y.materialId);
  1094. });
  1095. });
  1096. ids = Array.from(new Set(ids));
  1097. proxy
  1098. .post("/fileInfo/getList", {
  1099. businessIdList: ids,
  1100. })
  1101. .then((fileObj) => {
  1102. formData.data.quotationProductList.map((x) => {
  1103. // x.fileList = fileObj[x.productId] || [];
  1104. // if (x.fileList && x.fileList.length > 0) {
  1105. // x.fileUrl = x.fileList[0].fileUrl;
  1106. // }
  1107. x.quotationProductBomList.map((y) => {
  1108. y.fileList = fileObj[y.materialId] || [];
  1109. if (y.fileList && y.fileList.length > 0) {
  1110. y.fileUrl = y.fileList[0].fileUrl;
  1111. }
  1112. });
  1113. });
  1114. });
  1115. };
  1116. const getDtl = (row, flag, change = false) => {
  1117. formOption.disabled = flag;
  1118. modalType.value = "edit";
  1119. isChange.value = change;
  1120. isDetail.value = flag;
  1121. isShowChart.value = flag;
  1122. openAddDialog.value = true;
  1123. proxy.post("/saleQuotation/detail", { id: row.id }).then((res) => {
  1124. formData.data = res;
  1125. // 城市数据回显
  1126. if (formData.data.buyCountryId) {
  1127. getCityData(formData.data.buyCountryId, "20");
  1128. }
  1129. if (formData.data.buyProvinceId) {
  1130. getCityData(formData.data.buyProvinceId, "30");
  1131. }
  1132. // 文件数据回显
  1133. getFileData();
  1134. let productIds = formData.data.quotationProductList.map((x) => x.productId);
  1135. proxy.getFileData({
  1136. businessIdList: productIds,
  1137. data: formData.data.quotationProductList,
  1138. att: "productId",
  1139. businessType: "0",
  1140. fileAtt: "productFile",
  1141. filePathAtt: "fileUrl",
  1142. });
  1143. // 价格计算
  1144. changeQuantity();
  1145. //折线图
  1146. if (flag && res.quotationTrendList && res.quotationTrendList.length >= 2) {
  1147. nextTick(() => {
  1148. myChart = echarts.init(chartDom.value);
  1149. window.addEventListener("resize", () => {
  1150. myChart.resize();
  1151. });
  1152. chartData.value = res.quotationTrendList;
  1153. chartOption.data.xAxis.data = chartData.value.map((item) => {
  1154. return item.createTime.slice(0, 10);
  1155. });
  1156. chartOption.data.series[0].data = chartData.value.map((item, index) => {
  1157. if (item.code == row.code) {
  1158. return {
  1159. value: item.amount || 0,
  1160. itemStyle: { color: "red" },
  1161. };
  1162. } else {
  1163. return item.amount || 0;
  1164. }
  1165. });
  1166. myChart.setOption(chartOption.data);
  1167. myChart.resize();
  1168. });
  1169. } else {
  1170. isShowChart.value = false;
  1171. }
  1172. });
  1173. };
  1174. const openPrint = ref(false);
  1175. const printDetails = ref({});
  1176. const clickPrint = (row) => {
  1177. printDetails.value = {};
  1178. openPrint.value = true;
  1179. proxy.post("/saleQuotation/detail", { id: row.id }).then((res) => {
  1180. printDetails.value = res;
  1181. if (printDetails.value.ehsdJson) {
  1182. let ehsdJson = JSON.parse(printDetails.value.ehsdJson);
  1183. printDetails.value.deliveryTime = ehsdJson.deliveryTime;
  1184. }
  1185. });
  1186. };
  1187. const clickDownload = () => {
  1188. proxy.getPdf("报价单PDF文件");
  1189. };
  1190. const statistics = (label, index) => {
  1191. let num = 0;
  1192. if (
  1193. printDetails.value.quotationProductList &&
  1194. printDetails.value.quotationProductList.length > 0
  1195. ) {
  1196. printDetails.value.quotationProductList.map((item) => {
  1197. if (item[label]) {
  1198. num = parseFloat(Number(num) + Number(item[label])).toFixed(index);
  1199. }
  1200. });
  1201. }
  1202. return num;
  1203. };
  1204. const getLabel = (key, list, label) => {
  1205. let text = "";
  1206. if (list && list.length > 0) {
  1207. let data = list.filter((item) => item.id === key);
  1208. if (data && data.length > 0) {
  1209. text = data[0][label];
  1210. }
  1211. }
  1212. return text;
  1213. };
  1214. const getAllMoney = (num) => {
  1215. let money = num;
  1216. if (
  1217. printDetails.value.quotationPayList &&
  1218. printDetails.value.quotationPayList.length > 0
  1219. ) {
  1220. printDetails.value.quotationPayList.map((item) => {
  1221. if (item.amount) {
  1222. money = parseFloat(Number(money) + Number(item.amount)).toFixed(2);
  1223. }
  1224. });
  1225. }
  1226. return money;
  1227. };
  1228. const currencyData = computed(
  1229. () => proxy.useUserStore().allDict["account_currency"]
  1230. );
  1231. const fundsPaymentMethod = computed(
  1232. () => proxy.useUserStore().allDict["funds_payment_method"]
  1233. );
  1234. const shippingMethod = computed(
  1235. () => proxy.useUserStore().allDict["shipping_method"]
  1236. );
  1237. const treeData = ref([]);
  1238. const customerList = ref([]);
  1239. const customerUserList = ref([]);
  1240. const countryData = ref([]);
  1241. const provinceData = ref([]);
  1242. const cityData = ref([]);
  1243. const openProductCompany = ref(false);
  1244. const copyType = ref(1);
  1245. const copyContract = ref(false);
  1246. const indexValue = ref(-1);
  1247. const openSelectMaterial = ref(false);
  1248. const formData = reactive({
  1249. data: {
  1250. type: "1",
  1251. quotationProductList: [],
  1252. },
  1253. backData: {},
  1254. dataTwo: {},
  1255. });
  1256. const formDom = ref(null);
  1257. const formOption = reactive({
  1258. inline: true,
  1259. labelWidth: 100,
  1260. itemWidth: 100,
  1261. disabled: false,
  1262. });
  1263. let myChart = null;
  1264. const chartDom = ref(null);
  1265. const chartData = ref([]);
  1266. const isShowChart = ref(false);
  1267. const formConfig = computed(() => {
  1268. return [
  1269. {
  1270. type: "title1",
  1271. title: "报价趋势",
  1272. isShow: isShowChart.value,
  1273. },
  1274. {
  1275. type: "slot",
  1276. slotName: "chart",
  1277. isShow: isShowChart.value,
  1278. },
  1279. {
  1280. type: "title1",
  1281. title: "基本信息",
  1282. },
  1283. // {
  1284. // type: "select",
  1285. // prop: "type",
  1286. // label: "报价类型",
  1287. // data: typeData.value,
  1288. // itemWidth: 50,
  1289. // },
  1290. {
  1291. type: "treeSelect",
  1292. prop: "ofCompanyId",
  1293. label: "业务公司",
  1294. data: proxy.useUserStore().allDict["tree_company_data"],
  1295. propsTreeLabel: "deptName",
  1296. propsTreeValue: "deptId",
  1297. itemWidth: 50,
  1298. },
  1299. {
  1300. type: "treeSelect",
  1301. prop: "companyId",
  1302. label: "报价公司",
  1303. data: treeData.value,
  1304. propsTreeLabel: "deptName",
  1305. propsTreeValue: "deptId",
  1306. itemWidth: 50,
  1307. fn: (val) => {
  1308. companyId.value = val;
  1309. formData.data.quotationProductList = [];
  1310. },
  1311. },
  1312. {
  1313. type: "title1",
  1314. title: "贸易信息",
  1315. },
  1316. {
  1317. type: "slot",
  1318. slotName: "buyer",
  1319. label: "",
  1320. itemWidth: 100,
  1321. },
  1322. // {
  1323. // type: "input",
  1324. // itemType: "text",
  1325. // label: "联系人",
  1326. // prop: "buyContactName",
  1327. // itemWidth: 50,
  1328. // },
  1329. // {
  1330. // type: "input",
  1331. // itemType: "text",
  1332. // label: "联系人电话",
  1333. // prop: "buyContactNumber",
  1334. // itemWidth: 50,
  1335. // },
  1336. {
  1337. type: "title1",
  1338. title: "商品信息",
  1339. },
  1340. {
  1341. type: "slot",
  1342. slotName: "commodity",
  1343. label: "",
  1344. },
  1345. {
  1346. type: "title1",
  1347. title: "报价总金额",
  1348. },
  1349. {
  1350. type: "input",
  1351. prop: "amount",
  1352. label: "报价总金额",
  1353. itemWidth: 25,
  1354. disabled: true,
  1355. },
  1356. ];
  1357. });
  1358. const rules = ref({
  1359. // type: [{ required: true, message: "请选择报价类型", trigger: "change" }],
  1360. ofCompanyId: [
  1361. { required: true, message: "请选择业务公司", trigger: "change" },
  1362. ],
  1363. companyId: [{ required: true, message: "请选择报价公司", trigger: "change" }],
  1364. buyCorporationId: [
  1365. { required: true, message: "请选择客户公司", trigger: "change" },
  1366. ],
  1367. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  1368. productLength: [
  1369. { required: true, message: "请输入长 (cm)", trigger: "blur" },
  1370. ],
  1371. productWidth: [
  1372. { required: true, message: "请输入宽 (cm)", trigger: "blur" },
  1373. ],
  1374. productHeight: [
  1375. { required: true, message: "请输入高 (cm)", trigger: "blur" },
  1376. ],
  1377. rawMaterialId: [
  1378. { required: true, message: "请选择原材料", trigger: "change" },
  1379. ],
  1380. technologyId: [
  1381. { required: true, message: "请选择工艺产线", trigger: "change" },
  1382. ],
  1383. foldWay: [{ required: true, message: "请选择折叠数", trigger: "change" }],
  1384. remark: [{ required: true, message: "请输入备注", trigger: "blur" }],
  1385. });
  1386. const getCityData = (id, type, isChange = false) => {
  1387. proxy.post("/customizeArea/list", { parentId: id }).then((res) => {
  1388. if (type === "20") {
  1389. provinceData.value = res;
  1390. if (isChange) {
  1391. formData.data.buyProvinceId = "";
  1392. formData.data.provinceName = "";
  1393. formData.data.buyCityId = "";
  1394. formData.data.cityName = "";
  1395. }
  1396. } else if (type === "30") {
  1397. cityData.value = res;
  1398. if (isChange) {
  1399. formData.data.buyCityId = "";
  1400. formData.data.cityName = "";
  1401. }
  1402. } else {
  1403. countryData.value = res;
  1404. }
  1405. });
  1406. };
  1407. getCityData("0");
  1408. const changeCustomer = (val) => {
  1409. formData.data.quotationProductList = [];
  1410. if (val) {
  1411. proxy.post("/customer/detail", { id: val }).then(
  1412. (res) => {
  1413. formData.data.buyCorporationName = res.name;
  1414. if (res.customerUserList && res.customerUserList.length > 0) {
  1415. formData.data.buyContactName = res.customerUserList[0].name;
  1416. if (res.customerUserList[0].contactJson) {
  1417. let contactJson = JSON.parse(res.customerUserList[0].contactJson);
  1418. if (contactJson && contactJson.length > 0) {
  1419. formData.data.buyContactNumber = contactJson[0].contactNo;
  1420. }
  1421. }
  1422. customerUserList.value = res.customerUserList.map((item) => {
  1423. return {
  1424. ...item,
  1425. value: item.name,
  1426. };
  1427. });
  1428. }
  1429. // 回填客户的账户信息
  1430. // formData.data.beneficiaryName = res.beneficiaryName;
  1431. // formData.data.beneficiaryBank = res.beneficiaryBank;
  1432. // formData.data.beneficiaryBankAddress = res.beneficiaryBankAddress;
  1433. // formData.data.beneficiaryAccountNumber = res.beneficiaryAccountNumber;
  1434. // formData.data.swiftCode = res.swiftCode;
  1435. // formData.data.beneficiaryAddress = res.beneficiaryAddress;
  1436. formData.data.buyCountryId = res.countryId;
  1437. formData.data.buyProvinceId = res.provinceId;
  1438. formData.data.buyCityId = res.cityId;
  1439. formData.data.buyPostalCode = res.zipCode;
  1440. formData.data.buyAddress = res.address;
  1441. getCityData(formData.data.buyCountryId, "20");
  1442. if (formData.data.buyProvinceId) {
  1443. getCityData(formData.data.buyProvinceId, "30");
  1444. }
  1445. },
  1446. (err) => {
  1447. formData.data.buyCountryId = "";
  1448. formData.data.buyProvinceId = "";
  1449. formData.data.buyCityId = "";
  1450. formData.data.buyPostalCode = "";
  1451. formData.data.buyAddress = "";
  1452. }
  1453. );
  1454. } else {
  1455. formData.data.buyCountryId = "";
  1456. formData.data.buyProvinceId = "";
  1457. formData.data.buyCityId = "";
  1458. formData.data.buyPostalCode = "";
  1459. formData.data.buyAddress = "";
  1460. }
  1461. };
  1462. const handlePerson = (item) => {
  1463. if (item.contactJson) {
  1464. let data = JSON.parse(item.contactJson);
  1465. formData.data.buyContactNumber = data[0].contactNo;
  1466. }
  1467. };
  1468. const quotationProductBomList = ref([]);
  1469. const productCustomInfoListData = ref([
  1470. {
  1471. type: 1,
  1472. isCheck: 0,
  1473. isCheckBox: false,
  1474. fileList: [],
  1475. remark: "",
  1476. },
  1477. {
  1478. type: 2,
  1479. isCheck: 0,
  1480. isCheckBox: false,
  1481. fileList: [],
  1482. remark: "",
  1483. },
  1484. {
  1485. type: 3,
  1486. isCheck: 0,
  1487. isCheckBox: false,
  1488. fileList: [],
  1489. remark: "",
  1490. },
  1491. ]);
  1492. const selectProduct = (row) => {
  1493. if (row && row.id) {
  1494. proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
  1495. let goods = res;
  1496. if (goods.productBomDetailList && goods.productBomDetailList.length > 0) {
  1497. let quotationProductCustomInfoList = goods.productCustomInfoList.map(
  1498. (x) => {
  1499. if (x.fileList) {
  1500. x.fileList = x.fileList.map((y) => ({
  1501. ...y,
  1502. url: y.fileUrl,
  1503. name: y.fileName,
  1504. }));
  1505. } else {
  1506. x.fileList = [];
  1507. }
  1508. x.isCheckBox = x.isCheck == 1;
  1509. delete x.id;
  1510. return x;
  1511. }
  1512. );
  1513. if (goods.isCustomized == 0) {
  1514. quotationProductCustomInfoList = productCustomInfoListData.value;
  1515. }
  1516. let packAsk = goods.packAsk;
  1517. if (packAsk) {
  1518. packAsk = packAsk.split(",");
  1519. }
  1520. formData.data.quotationProductList.push({
  1521. productId: goods.id,
  1522. productName: goods.name,
  1523. productCode: goods.customCode,
  1524. productLength: goods["length"],
  1525. productWidth: goods.width,
  1526. productHeight: goods.height,
  1527. productColor: goods.color,
  1528. colorCardCode: goods.colorCardCode,
  1529. netWeight: goods.netWeight,
  1530. quantity: null,
  1531. price: null,
  1532. amount: "",
  1533. fileList: [],
  1534. rawMaterialId: goods.rawMaterialId,
  1535. technologyId: goods.technologyId,
  1536. logoLength: goods.logoLength,
  1537. logoWidth: goods.logoWidth,
  1538. logoHeight: goods.logoHeight,
  1539. colorCount: goods.colorCount,
  1540. isFold: goods.isFold || 0,
  1541. foldWay: goods.foldWay,
  1542. packAsk: packAsk,
  1543. isCustomized: goods.isCustomized || 0,
  1544. quotationProductBomList: goods.productBomDetailList,
  1545. quotationProductCustomInfoList: quotationProductCustomInfoList,
  1546. });
  1547. activeNames.value.push(formData.data.quotationProductList.length - 1);
  1548. proxy.msgTip("添加成功", 1);
  1549. } else {
  1550. return proxy.msgTip("该产品未配置BOM", 2);
  1551. }
  1552. });
  1553. } else {
  1554. return proxy.msgTip("选择错误", 2);
  1555. }
  1556. };
  1557. const clickPushProduct = () => {
  1558. let quotationProductCustomInfoList = productCustomInfoListData.value;
  1559. formData.data.quotationProductList.push({
  1560. productId: "",
  1561. productName: "",
  1562. productCode: "",
  1563. productLength: null,
  1564. productWidth: null,
  1565. productHeight: null,
  1566. productColor: "",
  1567. colorCardCode: "",
  1568. netWeight: null,
  1569. quantity: null,
  1570. price: null,
  1571. amount: "",
  1572. fileList: [],
  1573. rawMaterialId: "",
  1574. technologyId: "",
  1575. logoLength: null,
  1576. logoWidth: null,
  1577. logoHeight: null,
  1578. colorCount: null,
  1579. isFold: 0,
  1580. foldWay: "",
  1581. packAsk: [],
  1582. isCustomized: 0,
  1583. quotationProductBomList: [],
  1584. quotationProductCustomInfoList: quotationProductCustomInfoList,
  1585. });
  1586. proxy.msgTip("添加成功", 1);
  1587. activeNames.value.push(formData.data.quotationProductList.length - 1);
  1588. };
  1589. // const selectProduct = (goods) => {
  1590. // if (goods && goods.id) {
  1591. // let fileUrl = "";
  1592. // if (goods.fileList && goods.fileList.length > 0) {
  1593. // fileUrl = goods.fileList[0].fileUrl;
  1594. // }
  1595. // proxy.post("/productBomInfo/detail", { id: goods.id }).then((res) => {
  1596. // if (res.productBomDetailList && res.productBomDetailList.length > 0) {
  1597. // quotationProductBomList.value = res.productBomDetailList.map((x) => ({
  1598. // fileUrl: "",
  1599. // materialId: x.materialId,
  1600. // productName: x.materialName,
  1601. // productCode: x.materialCode,
  1602. // productLength: x["materialLength"],
  1603. // productWidth: x.materialWidth,
  1604. // productHeight: x.materialHeight,
  1605. // quantity: x.quantity || null,
  1606. // allQuantity: "",
  1607. // price: null,
  1608. // amount: "",
  1609. // fileList: [],
  1610. // type: x.type,
  1611. // }));
  1612. // formData.data.quotationProductList.push({
  1613. // fileUrl: fileUrl,
  1614. // productId: goods.id,
  1615. // productName: goods.name,
  1616. // productCode: goods.customCode,
  1617. // productLength: goods["length"],
  1618. // productWidth: goods.width,
  1619. // productHeight: goods.height,
  1620. // productColor: goods.color,
  1621. // quantity: null,
  1622. // price: null,
  1623. // amount: "",
  1624. // fileList: [],
  1625. // quotationProductBomList: quotationProductBomList.value,
  1626. // });
  1627. // proxy.msgTip("添加成功", 1);
  1628. // let ids = quotationProductBomList.value.map((x) => x.materialId);
  1629. // proxy.getFile(
  1630. // ids,
  1631. // quotationProductBomList.value,
  1632. // "materialId",
  1633. // "fileList",
  1634. // "fileUrl"
  1635. // );
  1636. // } else {
  1637. // return proxy.msgTip("该产品未配置BOM", 2);
  1638. // }
  1639. // });
  1640. // } else {
  1641. // return proxy.msgTip("选择错误", 2);
  1642. // }
  1643. // };
  1644. const handleClickSelectMaterial = (index) => {
  1645. indexValue.value = index;
  1646. openSelectMaterial.value = true;
  1647. };
  1648. const handleRemoveBom = (index, sonIndex) => {
  1649. formData.data.quotationProductList[index].quotationProductBomList.splice(
  1650. sonIndex,
  1651. 1
  1652. );
  1653. };
  1654. const selectMaterial = (goods) => {
  1655. let flag = formData.data.quotationProductList[
  1656. indexValue.value
  1657. ].quotationProductBomList.some((x) => x.materialId == goods.id);
  1658. if (!flag) {
  1659. let fileUrl = "";
  1660. if (goods.fileList && goods.fileList.length > 0) {
  1661. fileUrl = goods.fileList[0].fileUrl;
  1662. }
  1663. formData.data.quotationProductList[
  1664. indexValue.value
  1665. ].quotationProductBomList.push({
  1666. fileUrl: fileUrl,
  1667. materialId: goods.id,
  1668. materialName: goods.name,
  1669. materialCode: goods.customCode,
  1670. // productLength: goods["length"],
  1671. // productWidth: goods.width,
  1672. // productHeight: goods.height,
  1673. quantity: null,
  1674. price: null,
  1675. amount: "",
  1676. fileList: [],
  1677. type: 2,
  1678. });
  1679. proxy.msgTip("选择成功");
  1680. } else {
  1681. proxy.msgTip("该物料已选择", 2);
  1682. }
  1683. };
  1684. // const selectMaterial = (goods) => {
  1685. // let flag = formData.data.quotationProductList[
  1686. // indexValue.value
  1687. // ].quotationProductBomList.some((x) => x.materialId == goods.id);
  1688. // if (!flag) {
  1689. // let fileUrl = "";
  1690. // if (goods.fileList && goods.fileList.length > 0) {
  1691. // fileUrl = goods.fileList[0].fileUrl;
  1692. // }
  1693. // formData.data.quotationProductList[
  1694. // indexValue.value
  1695. // ].quotationProductBomList.push({
  1696. // fileUrl: fileUrl,
  1697. // materialId: goods.id,
  1698. // productName: goods.name,
  1699. // productCode: goods.customCode,
  1700. // productLength: goods["length"],
  1701. // productWidth: goods.width,
  1702. // productHeight: goods.height,
  1703. // quantity: null,
  1704. // price: null,
  1705. // amount: "",
  1706. // fileList: [],
  1707. // type: 2,
  1708. // });
  1709. // proxy.msgTip("选择成功");
  1710. // } else {
  1711. // proxy.msgTip("该物料已选择", 2);
  1712. // }
  1713. // };
  1714. const onPicture = (path) => {
  1715. window.open(path, "_blank");
  1716. };
  1717. const handleRemove = (index) => {
  1718. formData.data.quotationProductList.splice(index, 1);
  1719. changeQuantity();
  1720. };
  1721. const handleDeleteMaterial = (index, sonIndex) => {
  1722. formData.data.quotationProductList[index].quotationProductBomList.splice(
  1723. sonIndex,
  1724. 1
  1725. );
  1726. changeQuantity();
  1727. };
  1728. const loadingSearch = ref(false);
  1729. const remoteMethod = (keyword) => {
  1730. if (keyword && typeof keyword === "string") {
  1731. loadingSearch.value = true;
  1732. proxy.post("/customer/selPage", { keyword }).then((res) => {
  1733. customerList.value = res.rows.map((x) => ({
  1734. ...x,
  1735. label: x.name,
  1736. value: x.id,
  1737. }));
  1738. loadingSearch.value = false;
  1739. });
  1740. }
  1741. return;
  1742. };
  1743. const changeQuantity = () => {
  1744. let money = 0;
  1745. if (
  1746. formData.data.quotationProductList &&
  1747. formData.data.quotationProductList.length > 0
  1748. ) {
  1749. // 单个产品的价格
  1750. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  1751. let iele = formData.data.quotationProductList[i];
  1752. let productPrice = 0;
  1753. for (let j = 0; j < iele.quotationProductBomList.length; j++) {
  1754. const jele = iele.quotationProductBomList[j];
  1755. productPrice += Number(
  1756. parseFloat(Number(jele.quantity) * Number(jele.price)).toFixed(2)
  1757. );
  1758. }
  1759. iele.price = parseFloat(productPrice).toFixed(2);
  1760. }
  1761. // 计算数量以及小计
  1762. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  1763. let iele = formData.data.quotationProductList[i];
  1764. if (iele.quantity) {
  1765. if (iele.price) {
  1766. iele.amount = parseFloat(
  1767. Number(iele.quantity) * Number(iele.price)
  1768. ).toFixed(2);
  1769. money += Number(iele.amount);
  1770. }
  1771. for (let j = 0; j < iele.quotationProductBomList.length; j++) {
  1772. const jele = iele.quotationProductBomList[j];
  1773. jele.allQuantity = iele.quantity * jele.quantity;
  1774. if (jele.price) {
  1775. jele.amount = parseFloat(
  1776. Number(jele.allQuantity) * Number(jele.price)
  1777. ).toFixed(2);
  1778. }
  1779. }
  1780. }
  1781. }
  1782. formData.data.amount = parseFloat(money).toFixed(2);
  1783. }
  1784. };
  1785. const handleSubmit = (type) => {
  1786. formDom.value.handleSubmit(() => {
  1787. if (
  1788. formData.data.quotationProductList &&
  1789. formData.data.quotationProductList.length > 0
  1790. ) {
  1791. let data = proxy.deepClone(formData.data);
  1792. for (let i = 0; i < data.quotationProductList.length; i++) {
  1793. const iele = data.quotationProductList[i];
  1794. if (
  1795. !(
  1796. iele.quotationProductBomList &&
  1797. iele.quotationProductBomList.length > 0
  1798. )
  1799. ) {
  1800. return proxy.msgTip("请添加辅材", 2);
  1801. }
  1802. iele.quotationProductBomList.push({
  1803. materialId: iele.rawMaterialId,
  1804. type: 1,
  1805. });
  1806. if (iele.packAsk) {
  1807. iele.packAsk = iele.packAsk.join(",");
  1808. }
  1809. if (
  1810. iele.quotationProductCustomInfoList &&
  1811. iele.quotationProductCustomInfoList.length > 0
  1812. ) {
  1813. let checkNum = 0;
  1814. for (let j = 0; j < iele.quotationProductCustomInfoList.length; j++) {
  1815. let jele = iele.quotationProductCustomInfoList[j];
  1816. jele.isCheck = jele.isCheckBox ? 1 : 0;
  1817. if (jele.isCheckBox) {
  1818. checkNum += 1;
  1819. }
  1820. if (jele.isCheckBox) {
  1821. if (!(jele.fileList && jele.fileList.length > 0)) {
  1822. return proxy.msgTip(
  1823. `请上传第${i + 1}条数据的${getLabel(jele.type)}附件`,
  1824. 2
  1825. );
  1826. }
  1827. }
  1828. }
  1829. if (checkNum == 0) {
  1830. return proxy.msgTip(`请至少勾选一个第${i + 1}条数据的定制内容`, 2);
  1831. }
  1832. }
  1833. }
  1834. submitLoading.value = true;
  1835. data.status = type;
  1836. if (isChange.value) {
  1837. proxy.post("/saleQuotation/change", data).then(
  1838. (res) => {
  1839. proxy.msgTip("操作成功", 1);
  1840. openAddDialog.value = false;
  1841. submitLoading.value = false;
  1842. detailDialog.value = false;
  1843. getList();
  1844. },
  1845. (err) => {
  1846. submitLoading.value = false;
  1847. }
  1848. );
  1849. } else {
  1850. proxy.post("/saleQuotation/" + modalType.value, data).then(
  1851. (res) => {
  1852. proxy.msgTip("操作成功", 1);
  1853. openAddDialog.value = false;
  1854. submitLoading.value = false;
  1855. detailDialog.value = false;
  1856. getList();
  1857. },
  1858. (err) => {
  1859. submitLoading.value = false;
  1860. }
  1861. );
  1862. }
  1863. } else {
  1864. return proxy.msgTip("请添加至少一件商品", 2);
  1865. }
  1866. });
  1867. };
  1868. const chartOption = reactive({
  1869. data: {
  1870. tooltip: {
  1871. trigger: "axis",
  1872. },
  1873. // legend: {
  1874. // data: ["价格"],
  1875. // },
  1876. grid: {
  1877. left: "3%",
  1878. right: "6%",
  1879. top: "10%",
  1880. bottom: "3%",
  1881. containLabel: true,
  1882. },
  1883. tooltip: {
  1884. show: true,
  1885. trigger: "axis",
  1886. // 格式化函数
  1887. // valueFormatter: (val) => {
  1888. // return val + "aaa";
  1889. // },
  1890. formatter: (params, ticket, callback) => {
  1891. return `
  1892. ${params[0].seriesName}:${params[0].value}
  1893. <br/>
  1894. 报价单号:${chartData.value[params[0].dataIndex].code}
  1895. `;
  1896. },
  1897. textStyle: {
  1898. fontSize: 12,
  1899. },
  1900. },
  1901. // toolbox: {
  1902. // feature: {
  1903. // saveAsImage: {},
  1904. // },
  1905. // },
  1906. xAxis: {
  1907. type: "category",
  1908. boundaryGap: false,
  1909. data: [],
  1910. },
  1911. yAxis: {
  1912. type: "value",
  1913. },
  1914. series: [
  1915. {
  1916. name: "报价金额",
  1917. type: "line",
  1918. data: [],
  1919. },
  1920. ],
  1921. },
  1922. });
  1923. const handleRepeal = (row, url) => {
  1924. proxy
  1925. .msgConfirm()
  1926. .then((res) => {
  1927. proxy
  1928. .post(url, {
  1929. id: row.id,
  1930. })
  1931. .then((res) => {
  1932. proxy.msgTip("操作成功", 1);
  1933. detailDialog.value = false;
  1934. getList();
  1935. });
  1936. })
  1937. .catch((err) => {});
  1938. };
  1939. const formDomOne = ref(null);
  1940. const foreignDialog = ref(false);
  1941. const formConfigOne = computed(() => {
  1942. return [
  1943. // {
  1944. // type: "title1",
  1945. // title: "利润点数",
  1946. // },
  1947. // {
  1948. // type: "number",
  1949. // prop: "coefficient",
  1950. // label: "利润点数",
  1951. // precision: 2,
  1952. // min: 0.01,
  1953. // controls: false,
  1954. // itemWidth: 25,
  1955. // fn: (val) => {
  1956. // publicTotalAmount(val);
  1957. // },
  1958. // },
  1959. {
  1960. type: "title1",
  1961. title: "商品信息",
  1962. },
  1963. {
  1964. type: "slot",
  1965. slotName: "commodity",
  1966. label: "",
  1967. },
  1968. {
  1969. type: "title1",
  1970. title: "报价总金额",
  1971. },
  1972. {
  1973. type: "input",
  1974. prop: "amount",
  1975. label: "报价总金额",
  1976. itemWidth: 25,
  1977. disabled: true,
  1978. },
  1979. ];
  1980. });
  1981. const formOptionOne = reactive({
  1982. inline: true,
  1983. labelWidth: 100,
  1984. itemWidth: 100,
  1985. disabled: false,
  1986. });
  1987. const rulesOne = ref({
  1988. price: [{ required: true, message: "请输入单价", trigger: "blur" }],
  1989. // coefficient: [{ required: true, message: "请输入系数", trigger: "blur" }],
  1990. });
  1991. const handleForeign = (row) => {
  1992. foreignDialog.value = true;
  1993. proxy.post("/saleQuotation/detail", { id: row.id }).then((res) => {
  1994. formData.data = res;
  1995. formData.data.saleQuotationId = res.id;
  1996. delete formData.data.code;
  1997. delete formData.data.id;
  1998. // 复制原本价格
  1999. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  2000. const iele = formData.data.quotationProductList[i];
  2001. iele.quotationProductId = iele.id;
  2002. delete iele.id;
  2003. iele.guidePrice = iele.price;
  2004. iele.maxPrice = Number(
  2005. parseFloat((iele.amplifyRatio / 100 + 1) * iele.minPrice).toFixed(2)
  2006. );
  2007. iele.price = iele.minPrice;
  2008. for (let j = 0; j < iele.quotationProductBomList.length; j++) {
  2009. const jele = iele.quotationProductBomList[j];
  2010. jele.quotationProductBomId = jele.id;
  2011. delete jele.id;
  2012. // jele.priceCopy = jele.price;
  2013. // jele.price = Number(parseFloat(jele.price * 1.1)).toFixed(2);
  2014. // 默认系数
  2015. // jele.coefficient = 1.1;
  2016. }
  2017. }
  2018. // changeQuantity();
  2019. // 城市数据回显
  2020. // if (formData.data.buyCountryId) {
  2021. // getCityData(formData.data.buyCountryId, "20");
  2022. // }
  2023. // if (formData.data.buyProvinceId) {
  2024. // getCityData(formData.data.buyProvinceId, "30");
  2025. // }
  2026. changeForeignQuantity();
  2027. // 文件数据回显
  2028. getFileData();
  2029. let productIds = formData.data.quotationProductList.map((x) => x.productId);
  2030. proxy.getFileData({
  2031. businessIdList: productIds,
  2032. data: formData.data.quotationProductList,
  2033. att: "productId",
  2034. businessType: "0",
  2035. fileAtt: "productFile",
  2036. filePathAtt: "fileUrl",
  2037. });
  2038. });
  2039. };
  2040. const totalAmount = () => {
  2041. let money = 0;
  2042. if (
  2043. formData.data.quotationProductList &&
  2044. formData.data.quotationProductList.length > 0
  2045. ) {
  2046. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  2047. let iele = formData.data.quotationProductList[i];
  2048. let productPrice = 0;
  2049. for (let j = 0; j < iele.quotationProductBomList.length; j++) {
  2050. const jele = iele.quotationProductBomList[j];
  2051. // 计算新单价
  2052. jele.price = parseFloat(
  2053. Number(jele.priceCopy) * Number(jele.coefficient)
  2054. ).toFixed(2);
  2055. // 计算物料总计
  2056. jele.amount = parseFloat(
  2057. Number(jele.allQuantity) *
  2058. Number(jele.priceCopy) *
  2059. Number(jele.coefficient)
  2060. ).toFixed(2);
  2061. // 单个产品的一个物料的钱
  2062. productPrice += Number(
  2063. parseFloat(
  2064. Number(jele.quantity) *
  2065. Number(jele.priceCopy) *
  2066. Number(jele.coefficient)
  2067. ).toFixed(2)
  2068. );
  2069. }
  2070. iele.price = parseFloat(productPrice).toFixed(2);
  2071. iele.amount = parseFloat(
  2072. Number(iele.quantity) * Number(iele.price)
  2073. ).toFixed(2);
  2074. money += Number(iele.amount);
  2075. }
  2076. }
  2077. formData.data.amount = parseFloat(money).toFixed(2);
  2078. };
  2079. const publicTotalAmount = (val) => {
  2080. if (val) {
  2081. let money = 0;
  2082. if (
  2083. formData.data.quotationProductList &&
  2084. formData.data.quotationProductList.length > 0
  2085. ) {
  2086. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  2087. let iele = formData.data.quotationProductList[i];
  2088. let productPrice = 0;
  2089. for (let j = 0; j < iele.quotationProductBomList.length; j++) {
  2090. const jele = iele.quotationProductBomList[j];
  2091. // 系数赋值
  2092. jele.coefficient = val;
  2093. // 计算新单价
  2094. jele.price = parseFloat(
  2095. Number(jele.priceCopy) * Number(jele.coefficient)
  2096. ).toFixed(2);
  2097. // 计算物料总计
  2098. jele.amount = parseFloat(
  2099. Number(jele.allQuantity) *
  2100. Number(jele.priceCopy) *
  2101. Number(jele.coefficient)
  2102. ).toFixed(2);
  2103. // 单个产品的一个物料的钱
  2104. productPrice += Number(
  2105. parseFloat(
  2106. Number(jele.quantity) *
  2107. Number(jele.priceCopy) *
  2108. Number(jele.coefficient)
  2109. ).toFixed(2)
  2110. );
  2111. }
  2112. iele.price = parseFloat(productPrice).toFixed(2);
  2113. iele.amount = parseFloat(
  2114. Number(iele.quantity) * Number(iele.price)
  2115. ).toFixed(2);
  2116. money += Number(iele.amount);
  2117. }
  2118. }
  2119. formData.data.amount = parseFloat(money).toFixed(2);
  2120. }
  2121. };
  2122. const handleSubmitOne = () => {
  2123. formDomOne.value.handleSubmit(() => {
  2124. proxy
  2125. .msgConfirm()
  2126. .then((res) => {
  2127. submitLoading.value = true;
  2128. proxy.post("/extQuotation/add", formData.data).then((res) => {
  2129. proxy.msgTip("操作成功", 1);
  2130. submitLoading.value = false;
  2131. foreignDialog.value = false;
  2132. getList();
  2133. });
  2134. })
  2135. .catch((err) => {
  2136. submitLoading.value = false;
  2137. });
  2138. });
  2139. };
  2140. const detailDialog = ref(false);
  2141. const detailRowData = ref({});
  2142. const handleOpenDetail = (item) => {
  2143. detailRowData.value = item;
  2144. detailDialog.value = true;
  2145. };
  2146. const leftRowData = ref({});
  2147. const changeLeftData = (i) => {
  2148. leftRowData.value = i;
  2149. };
  2150. const backFormDom = ref(null);
  2151. const backDialog = ref(false);
  2152. const backFormConfig = computed(() => {
  2153. return [
  2154. {
  2155. type: "input",
  2156. itemType: "textarea",
  2157. rows: 10,
  2158. prop: "backRemark",
  2159. label: "退回原因",
  2160. itemWidth: 100,
  2161. disabled: false,
  2162. },
  2163. ];
  2164. });
  2165. const backFormOption = reactive({
  2166. inline: true,
  2167. labelWidth: 100,
  2168. itemWidth: 100,
  2169. disabled: false,
  2170. });
  2171. const backRules = ref({
  2172. backRemark: [{ required: true, message: "请输入退回原因", trigger: "blur" }],
  2173. });
  2174. const handleBack = (row) => {
  2175. formData.backData = {
  2176. id: row.id,
  2177. quotationStatus: 1,
  2178. backRemark: "",
  2179. };
  2180. backDialog.value = true;
  2181. };
  2182. const handleSubmitBack = () => {
  2183. backFormDom.value.handleSubmit(() => {
  2184. submitLoading.value = true;
  2185. proxy
  2186. .msgConfirm()
  2187. .then((res) => {
  2188. proxy.post("/saleQuotation/edit", formData.backData).then((res) => {
  2189. proxy.msgTip("操作成功", 1);
  2190. submitLoading.value = false;
  2191. backDialog.value = false;
  2192. getList();
  2193. detailDialog.value = false;
  2194. });
  2195. })
  2196. .catch((err) => {
  2197. submitLoading.value = false;
  2198. });
  2199. });
  2200. };
  2201. const getFileDataOne = () => {
  2202. let ids = [];
  2203. formData.dataTwo.quotationProductList.map((x) => {
  2204. // ids.push(x.productId);
  2205. x.quotationProductBomList.map((y) => {
  2206. ids.push(y.materialId);
  2207. });
  2208. });
  2209. ids = Array.from(new Set(ids));
  2210. proxy
  2211. .post("/fileInfo/getList", {
  2212. businessIdList: ids,
  2213. })
  2214. .then((fileObj) => {
  2215. formData.dataTwo.quotationProductList.map((x) => {
  2216. // x.fileList = fileObj[x.productId] || [];
  2217. // if (x.fileList && x.fileList.length > 0) {
  2218. // x.fileUrl = x.fileList[0].fileUrl;
  2219. // }
  2220. x.quotationProductBomList.map((y) => {
  2221. y.fileList = fileObj[y.materialId] || [];
  2222. if (y.fileList && y.fileList.length > 0) {
  2223. y.fileUrl = y.fileList[0].fileUrl;
  2224. }
  2225. });
  2226. });
  2227. });
  2228. };
  2229. const changeQuantityOne = () => {
  2230. let money = 0;
  2231. if (
  2232. formData.dataTwo.quotationProductList &&
  2233. formData.dataTwo.quotationProductList.length > 0
  2234. ) {
  2235. // 单个产品的价格
  2236. for (let i = 0; i < formData.dataTwo.quotationProductList.length; i++) {
  2237. let iele = formData.dataTwo.quotationProductList[i];
  2238. iele.amount = Number(
  2239. parseFloat(Number(iele.quantity) * Number(iele.price)).toFixed(2)
  2240. );
  2241. money += iele.amount;
  2242. }
  2243. formData.dataTwo.amount = parseFloat(money).toFixed(2);
  2244. }
  2245. };
  2246. const changeQuantityTwo = () => {
  2247. let money = 0;
  2248. if (
  2249. formData.dataTwo.quotationProductList &&
  2250. formData.dataTwo.quotationProductList.length > 0
  2251. ) {
  2252. // 单个产品的价格
  2253. for (let i = 0; i < formData.dataTwo.quotationProductList.length; i++) {
  2254. let iele = formData.dataTwo.quotationProductList[i];
  2255. money += Number(
  2256. parseFloat(Number(iele.quantity) * Number(iele.prodPrice)).toFixed(2)
  2257. );
  2258. }
  2259. formData.dataTwo.amountTwo = parseFloat(money).toFixed(2);
  2260. }
  2261. };
  2262. const changeMinPrice = () => {
  2263. if (
  2264. formData.dataTwo.quotationProductList &&
  2265. formData.dataTwo.quotationProductList.length > 0
  2266. ) {
  2267. // 单个产品的价格
  2268. for (let i = 0; i < formData.dataTwo.quotationProductList.length; i++) {
  2269. let iele = formData.dataTwo.quotationProductList[i];
  2270. if (iele.minPrice && iele.amplifyRatio) {
  2271. iele.maxPrice = Number(
  2272. parseFloat(
  2273. Number(iele.minPrice) * (1 + Number(iele.amplifyRatio) / 100)
  2274. ).toFixed(2)
  2275. );
  2276. }
  2277. }
  2278. }
  2279. };
  2280. const isDetailData = ref(false);
  2281. const getConfirmDtl = (row, flag) => {
  2282. if (!proxy.useUserStore().roles.includes("GM")) {
  2283. return;
  2284. }
  2285. isDetailData.value = flag;
  2286. formOptionTwo.disabled = flag;
  2287. modalType.value = "edit";
  2288. confirmDialog.value = true;
  2289. proxy.post("/saleQuotation/detail", { id: row.id }).then((res) => {
  2290. formData.dataTwo = res;
  2291. if (!flag) {
  2292. formData.dataTwo.quotationProductList =
  2293. formData.dataTwo.quotationProductList.map((x) => ({
  2294. ...x,
  2295. price: x.prodPrice,
  2296. }));
  2297. }
  2298. // 文件数据回显
  2299. getFileDataOne();
  2300. let productIds = formData.dataTwo.quotationProductList.map(
  2301. (x) => x.productId
  2302. );
  2303. proxy.getFileData({
  2304. businessIdList: productIds,
  2305. data: formData.dataTwo.quotationProductList,
  2306. att: "productId",
  2307. businessType: "0",
  2308. fileAtt: "productFile",
  2309. filePathAtt: "fileUrl",
  2310. });
  2311. // 价格计算
  2312. changeQuantityOne();
  2313. changeQuantityTwo();
  2314. changeMinPrice();
  2315. });
  2316. };
  2317. const formDomTwo = ref(null);
  2318. const confirmDialog = ref(false);
  2319. const formConfigTwo = computed(() => {
  2320. return [
  2321. {
  2322. type: "title1",
  2323. title: "商品信息",
  2324. },
  2325. {
  2326. type: "slot",
  2327. slotName: "commodity",
  2328. label: "",
  2329. },
  2330. {
  2331. type: "title1",
  2332. title: "报价总金额",
  2333. },
  2334. {
  2335. type: "input",
  2336. prop: "amountTwo",
  2337. label: "工厂报价总额",
  2338. itemWidth: 25,
  2339. disabled: true,
  2340. },
  2341. {
  2342. type: "input",
  2343. prop: "amount",
  2344. label: "调整报价总额",
  2345. itemWidth: 25,
  2346. disabled: true,
  2347. },
  2348. ];
  2349. });
  2350. const formOptionTwo = reactive({
  2351. inline: true,
  2352. labelWidth: 100,
  2353. itemWidth: 100,
  2354. disabled: false,
  2355. });
  2356. const rulesTwo = ref({
  2357. price: [{ required: true, message: "请输入单价", trigger: "blur" }],
  2358. // coefficient: [{ required: true, message: "请输入系数", trigger: "blur" }],
  2359. minPrice: [{ required: true, message: "业务员最低报价", trigger: "blur" }],
  2360. amplifyRatio: [{ required: true, message: "上调比例", trigger: "blur" }],
  2361. });
  2362. const confirmSubmit = () => {
  2363. formDomTwo.value.handleSubmit(() => {
  2364. formData.dataTwo.quotationStatus = 2;
  2365. proxy
  2366. .msgConfirm()
  2367. .then((res) => {
  2368. submitLoading.value = true;
  2369. proxy.post("/saleQuotation/edit", formData.dataTwo).then((res) => {
  2370. proxy.msgTip("操作成功", 1);
  2371. submitLoading.value = false;
  2372. confirmDialog.value = false;
  2373. getList();
  2374. detailDialog.value = false;
  2375. });
  2376. })
  2377. .catch((err) => {
  2378. submitLoading.value = false;
  2379. });
  2380. });
  2381. };
  2382. const changeForeignQuantity = () => {
  2383. let money = 0;
  2384. if (
  2385. formData.data.quotationProductList &&
  2386. formData.data.quotationProductList.length > 0
  2387. ) {
  2388. // 单个产品的价格
  2389. for (let i = 0; i < formData.data.quotationProductList.length; i++) {
  2390. let iele = formData.data.quotationProductList[i];
  2391. iele.amount = Number(parseFloat(iele.price * iele.quantity).toFixed(2));
  2392. money += Number(iele.amount);
  2393. }
  2394. formData.data.amount = parseFloat(money).toFixed(2);
  2395. }
  2396. };
  2397. const activeNames = ref([]);
  2398. let obj = {
  2399. 1: "定制刀模",
  2400. 2: "定制纹路",
  2401. 3: "定制模具",
  2402. };
  2403. const getLabelOne = (type) => {
  2404. return obj[type];
  2405. };
  2406. const handleBeforeUploadOne = async (file, index, sonIndex) => {
  2407. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  2408. file.id = res.id;
  2409. file.fileUrl = res.fileUrl;
  2410. uploadData.value = res.uploadBody;
  2411. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2412. sonIndex
  2413. ].fileData = res;
  2414. return true;
  2415. };
  2416. const handleSuccessOne = (index, sonIndex) => {
  2417. if (
  2418. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2419. sonIndex
  2420. ].fileData &&
  2421. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2422. sonIndex
  2423. ].fileData.fileUrl
  2424. ) {
  2425. let file =
  2426. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2427. sonIndex
  2428. ].fileData;
  2429. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2430. sonIndex
  2431. ].fileList.push({
  2432. id: file.id,
  2433. fileName: file.fileName,
  2434. name: file.fileName,
  2435. url: file.fileUrl,
  2436. fileUrl: file.fileUrl,
  2437. });
  2438. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2439. sonIndex
  2440. ].fileData = {};
  2441. }
  2442. };
  2443. const handleRemoveFile = (file, index, sonIndex) => {
  2444. formData.data.quotationProductList[index].quotationProductCustomInfoList[
  2445. sonIndex
  2446. ].fileList.splice(sonIndex, 1);
  2447. };
  2448. const onPreviewFile = (file) => {
  2449. if (file && file.fileUrl) {
  2450. window.open(file.fileUrl, "_blank");
  2451. } else {
  2452. window.open(file.raw.fileUrl, "_blank");
  2453. }
  2454. };
  2455. </script>
  2456. <style lang="scss" scoped>
  2457. .tenant {
  2458. padding: 20px;
  2459. }
  2460. ::v-deep(.el-input-number .el-input__inner) {
  2461. text-align: left;
  2462. }
  2463. .baseRow {
  2464. min-height: 24px;
  2465. border-top: 1px solid black;
  2466. border-left: 1px solid black;
  2467. }
  2468. .contentRow {
  2469. border-right: 1px solid black;
  2470. line-height: 24px;
  2471. padding-left: 4px;
  2472. }
  2473. .pic {
  2474. object-fit: contain;
  2475. width: 50px;
  2476. height: 50px;
  2477. cursor: pointer;
  2478. vertical-align: middle;
  2479. }
  2480. :deep(.bom-table .el-table__body-wrapper .el-table__body .el-table__row) {
  2481. background: #f4f4f5 !important;
  2482. }
  2483. .table {
  2484. border-collapse: collapse;
  2485. border-spacing: 0;
  2486. td {
  2487. text-align: center;
  2488. padding: 2px 4px;
  2489. // padding: 5px 10px;
  2490. }
  2491. }
  2492. .small-title {
  2493. padding-left: 15px;
  2494. margin-bottom: 10px;
  2495. color: #3366ff;
  2496. font-size: 14px;
  2497. }
  2498. :deep(.el-checkbox) {
  2499. margin-right: 0px;
  2500. }
  2501. </style>