自主产品,供应链食堂系统。将两个端拆开了。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

431 lines
11 KiB

  1. <template>
  2. <view>
  3. <view class="box">
  4. <view class="title">报价清单</view>
  5. <view class="lf-font-24 lf-color-gray lf-m-t-5">请在以下物资信息表内填写报价</view>
  6. </view>
  7. <!-- 修饰条 -->
  8. <self-line></self-line>
  9. <view class="box lf-row-between relation">
  10. <view>
  11. <text class="title">关联食堂</text>
  12. <text class="lf-font-24 lf-color-555 lf-m-l-10">(多选)</text>
  13. </view>
  14. <view class="lf-font-24 lf-color-gray lf-text-right lf-row-center" style="width: 370rpx; justify-content: flex-end;" @click="switchRelation">
  15. <view class="lf-line-1">{{ selectName }}</view>
  16. <u-icon name="arrow-right" class="lf-text-vertical"></u-icon>
  17. </view>
  18. <view class="mask" :style="{top: node_top +'px'}" v-if="is_show" @click="is_show = false">
  19. <view class="list">
  20. <view class="lf-row-between item" v-for="(item, index) in relation_list" :key="index" @click.stop="selectItem(index)">
  21. <view>{{ item.canteen_name }}</view>
  22. <u-icon name="checkmark-circle" color="#1833F2" size="40" v-if="item.checked"></u-icon>
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. <self-line></self-line>
  28. <!-- 物料table -->
  29. <view class="box">
  30. <wyb-table :first-line-fixed="true"
  31. contentBgColor="#eef6fe"
  32. :headers="headers"
  33. :contents="contents"
  34. @onInputChange="onInputChange"
  35. @onButtonClick="onButtonClick"
  36. width="100%" height="80vh"></wyb-table>
  37. </view>
  38. <view style="height: 140rpx;"></view>
  39. <!-- 操作按钮 -->
  40. <view class="fixed-bottom">
  41. <button class="btn btn1" @click="save(0)">临时保存</button>
  42. <button class="btn btn2" @click="save(1)">直接报价</button>
  43. </view>
  44. </view>
  45. </template>
  46. <script>
  47. import wybTable from '@/components/wyb-table/wyb-table';
  48. let app = getApp();
  49. export default {
  50. components: {
  51. wybTable
  52. },
  53. data(){
  54. return {
  55. headers: [{
  56. label: '物资名称',
  57. key: 'name'
  58. },{
  59. label: '规格',
  60. key: 'spec'
  61. },{
  62. label: '单位',
  63. key: 'unit'
  64. },{
  65. label: '分类',
  66. key: 'category'
  67. },{
  68. label: '品牌',
  69. key: 'brand'
  70. },{
  71. label: '品级',
  72. key: 'quality_level'
  73. },{
  74. label: '编号',
  75. key: 'number'
  76. },{
  77. label: '起购数',
  78. key: 'purchase_limit'
  79. },{
  80. label: '含税价',
  81. key: 'tax_price'
  82. },{
  83. label: '非含税价',
  84. key: 'non_tax_price'
  85. },{
  86. label: '操作',
  87. key: 'operation'
  88. }],
  89. contents: [],
  90. is_show: false,
  91. relation_list: [], // 关联食堂列表
  92. node_top: 0,
  93. code: '', // 订单号,批次号,如果有
  94. type: 0
  95. }
  96. },
  97. computed: {
  98. selectName(){
  99. let arr = [];
  100. this.relation_list.map(item => {
  101. if(item.checked){
  102. arr.push(item.canteen_name);
  103. }
  104. });
  105. let str = '请选择...';
  106. if(arr.length > 0){
  107. str = arr.join(',');
  108. }
  109. return str;
  110. }
  111. },
  112. onLoad(options){
  113. this.code = options.code || '';
  114. this.type = options.type || 0;
  115. if(options.type == 1){
  116. // 编辑,不可更换食堂
  117. this.materialListByOrder();
  118. }else if(options.type == 2){
  119. // 复用订单号
  120. this.materialListByOrder();
  121. }else if(options.type == 3){
  122. // 复用批次号
  123. this.materialListByBatch();
  124. }else{
  125. // 单纯发起报价
  126. this.getMaterialList();
  127. }
  128. },
  129. onReady(){
  130. let that = this;
  131. let info = uni.createSelectorQuery().select(".relation");
  132.     info.boundingClientRect(function(data) {
  133. let num = app.globalData.customBarH;
  134. num += data.height;
  135. num += data.top;
  136. that.node_top = num;
  137.    }).exec()
  138. },
  139. onPageScroll(){
  140. if(this.is_show){
  141. this.is_show = false;
  142. }
  143. },
  144. methods: {
  145. // 获取物资列表
  146. getMaterialList(){
  147. this.$http(this.API.API_SUPPLIER_MATERIALLIST).then(res => {
  148. let list = res.data.spec || [];
  149. let contents = list.map(item => {
  150. return {
  151. name: item?.material?.m_name || '',
  152. material_id: item?.material?.id || 0,
  153. spec: item.name,
  154. spec_id: item.id,
  155. brand: item?.material?.brand || '',
  156. quality_level: item?.material?.quality_level || '',
  157. number: item?.material?.m_sn || '',
  158. purchase_limit: {edit: true, value: 1},
  159. tax_price: {edit: true, value: ''},
  160. non_tax_price: {edit: true, value: ''},
  161. operation: {button: true, key: 'delete', value: '删除'},
  162. unit: item?.material?.unit?.unit_name || '',
  163. category: item?.material?.category?.m_cate_name || ''
  164. }
  165. })
  166. this.contents = contents;
  167. this.getCanteenList();
  168. })
  169. },
  170. // 复用报价订单号 & 编辑共用
  171. materialListByOrder(){
  172. this.$http(this.API.API_SUPPLIER_QUOTATIONREUSEBYORDER, {
  173. q_sn: this.code
  174. }).then(res => {
  175. console.log("materialListByOrder", res);
  176. let list = res.data.order || [];
  177. let canteen = res.data.canteen || [];
  178. let contents = list.map(item => {
  179. let obj = {
  180. name: item?.material?.m_name || '',
  181. material_id: item?.material?.id || 0,
  182. spec: item.name,
  183. spec_id: item.id,
  184. brand: item?.material?.brand || '',
  185. quality_level: item?.material?.quality_level || '',
  186. number: item?.material?.m_sn || '',
  187. purchase_limit: {edit: true, value: item?.quotation?.purchase_limit || ''},
  188. tax_price: {edit: true, value: item?.quotation?.tax_price || ''},
  189. non_tax_price: {edit: true, value: item?.quotation?.non_tax_price || ''},
  190. quotation_id: item?.quotation?.id || 0,
  191. operation: {button: true, key: 'delete', value: '删除'},
  192. unit: item?.material?.unit?.unit_name || '',
  193. category: item?.material?.category?.m_cate_name || ''
  194. }
  195. if(item?.material?.state && item?.material?.state != '启用'){
  196. obj.disabled = true;
  197. }
  198. return obj;
  199. })
  200. this.contents = contents;
  201. this.getCanteenList(canteen);
  202. })
  203. },
  204. // 复用批次号
  205. materialListByBatch(){
  206. this.$http(this.API.API_SUPPLIER_QUOTATIONREUSEBYBATCH, {
  207. batch_sn: this.code
  208. }).then(res => {
  209. console.log("materialListByBatch", res);
  210. let list = res.data.order || [];
  211. let canteen = res.data.canteen || [];
  212. let contents = list.map(item => {
  213. return {
  214. name: item?.material?.m_name || '',
  215. material_id: item?.material?.id || 0,
  216. spec: item.name,
  217. spec_id: item.id,
  218. brand: item?.material?.brand || '',
  219. quality_level: item?.material?.quality_level || '',
  220. number: item?.material?.m_sn || '',
  221. purchase_limit: {edit: true, value: item?.quotation?.purchase_limit || ''},
  222. tax_price: {edit: true, value: item?.quotation?.tax_price || ''},
  223. non_tax_price: {edit: true, value: item?.quotation?.non_tax_price || ''}
  224. }
  225. })
  226. this.contents = contents;
  227. this.getCanteenList(canteen);
  228. })
  229. },
  230. // 关联食堂列表
  231. getCanteenList(canteen = []){
  232. this.$http(this.API.API_SUPPLIER_CANTEENLIST).then(res => {
  233. let list = res.data.list.map(item => {
  234. item.checked = false;
  235. canteen.map(ct => {
  236. if(ct == item.id){
  237. item.checked = true;
  238. }
  239. })
  240. return item;
  241. })
  242. this.relation_list = list;
  243. })
  244. },
  245. // 监听表格被输入
  246. onInputChange(event){
  247. this.contents[event.contentIndex][event.key].value = event.detailValue;
  248. },
  249. // table操作按钮被点击
  250. onButtonClick(event){
  251. if(event.content.key == 'delete'){
  252. let contentIndex = event.contentIndex;
  253. let name = event.lineData.name;
  254. let spec = event.lineData.spec;
  255. uni.showModal({
  256. title: '温馨提示',
  257. content: `确定删除 ${name}-${spec} 吗?`,
  258. confirmColor: '#1833F2',
  259. success: result => {
  260. if(result.confirm){
  261. this.contents.splice(contentIndex, 1);
  262. }
  263. }
  264. })
  265. }
  266. },
  267. // 切换显示关联食堂modal
  268. switchRelation(){
  269. if(this.type == 1) return this.$msg('编辑不可更换关联食堂哦');
  270. this.is_show = !this.is_show;
  271. },
  272. // 选择食堂
  273. selectItem(index){
  274. this.relation_list[index].checked = !this.relation_list[index].checked;
  275. },
  276. // 报价订单编辑时保存
  277. editMaterial(_t){
  278. // 物资列表
  279. let list = [];
  280. this.contents.map(item => {
  281. list.push({
  282. id: item.quotation_id,
  283. tax_price: item.tax_price.value,
  284. non_tax_price: item.non_tax_price.value,
  285. purchase_limit: Number(item.purchase_limit.value) || 1
  286. })
  287. });
  288. // 操作状态,是保存还是直接发起
  289. let state = ['待发起', '待审核'][_t];
  290. this.$http(this.API.API_SUPPLIER_QUOTATIONSAVE, {
  291. data: list,
  292. state: state,
  293. q_sn: this.code
  294. }).then(res => {
  295. this.$msg('操作成功').then(result => {
  296. this.$toBack();
  297. })
  298. })
  299. },
  300. // 保存
  301. save(_t){
  302. // 拦截是编辑的情况
  303. if(this.type == 1){
  304. this.editMaterial(_t);
  305. return;
  306. }
  307. // 物资列表
  308. let list = [];
  309. this.contents.map(item => {
  310. if(item.tax_price.value && item.non_tax_price.value){
  311. list.push({
  312. m_id: item.material_id,
  313. m_spec_id: item.spec_id,
  314. tax_price: item.tax_price.value,
  315. non_tax_price: item.non_tax_price.value,
  316. purchase_limit: Number(item.purchase_limit.value) || 1
  317. })
  318. }
  319. });
  320. // 关联食堂
  321. let canteen_ids = [];
  322. this.relation_list.map(item => {
  323. if(item.checked){
  324. canteen_ids.push(item.id);
  325. }
  326. })
  327. if(canteen_ids.length <= 0){
  328. return this.$msg('您未选择关联食堂哦')
  329. }
  330. if(list.length <= 0){
  331. return this.$msg('没有需要报价的物资')
  332. }
  333. // 操作状态,是保存还是直接发起
  334. let state = ['待发起', '待审核'][_t];
  335. this.$http(this.API.API_SUPPLIER_QUOTATIONAPPLY, {
  336. data: list,
  337. state: state,
  338. canteen_ids: canteen_ids
  339. }).then(res => {
  340. this.$msg(res.data).then(result => {
  341. this.$toBack();
  342. })
  343. })
  344. }
  345. }
  346. }
  347. </script>
  348. <style>
  349. page{
  350. overflow: hidden;
  351. }
  352. </style>
  353. <style lang="scss" scoped="scoped">
  354. .lf-m-t-5{
  355. margin-top: 5rpx;
  356. }
  357. .box{
  358. padding: 30rpx 32rpx;
  359. width: 100%;
  360. height: max-content;
  361. box-sizing: border-box;
  362. }
  363. .title{
  364. color: #222222;
  365. font-size: 28rpx;
  366. font-weight: bold;
  367. }
  368. .fixed-bottom{
  369. position: fixed;
  370. bottom: 0rpx;
  371. left: 0rpx;
  372. z-index: 99;
  373. width: 750rpx;
  374. height: 98rpx;
  375. display: flex;
  376. justify-content: center;
  377. align-items: center;
  378. border-top: 1rpx solid #E5E5E5;
  379. background-color: #fff;
  380. .btn{
  381. width: 320rpx;
  382. height: 82rpx;
  383. border-radius: 41rpx;
  384. margin: 0;
  385. padding: 0;
  386. font-size: 32rpx;
  387. display: flex;
  388. justify-content: center;
  389. align-items: center;
  390. }
  391. .btn1{
  392. border: 2rpx solid #555555;
  393. opacity: .5;
  394. }
  395. .btn2{
  396. background: #1833F2;
  397. color: #FFFFFF;
  398. margin-left: 50rpx;
  399. }
  400. }
  401. .relation{
  402. position: relative;
  403. border-bottom: 1rpx solid #E5E5E5;
  404. }
  405. .mask{
  406. position: fixed;
  407. background-color: rgba(0,0,0,0.4);
  408. width: 100%;
  409. // top: 149px;
  410. bottom: 0;
  411. left: 0;
  412. z-index: 100;
  413. .list{
  414. min-height: max-content;
  415. max-height: 500rpx;
  416. overflow: scroll;
  417. background-color: #FFFFFF;
  418. width: 100%;
  419. .item{
  420. height: 92rpx;
  421. padding: 0 32rpx;
  422. border-bottom: 1rpx solid #E5E5E5;
  423. color: #222222;
  424. font-size: 28rpx;
  425. }
  426. }
  427. }
  428. </style>