instrument-edit.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. const Editor = window.createEditorComponent()
  2. const FormVideoGroup = window.createFormVideoGroup()
  3. const app = new Vue({
  4. components: {
  5. Editor,
  6. FormVideoGroup
  7. },
  8. data() {
  9. var validateQuestionList = (rule, value, callback) => {
  10. if (!value) {
  11. callback(new Error('问答列表不能为空'))
  12. } else if (value < this.minLimitQuestions) {
  13. callback(new Error(`请填写至少${this.minLimitQuestions}条问答`))
  14. } else {
  15. callback();
  16. }
  17. }
  18. var validateParamList = (rule, value, callback) => {
  19. if (!value) {
  20. callback(new Error('参数列表不能为空'))
  21. } else if (value < this.minLimitParams) {
  22. callback(new Error(`请填写至少${this.minLimitParams}条参数`))
  23. } else {
  24. callback();
  25. }
  26. }
  27. return {
  28. productId: 0,
  29. commodityType: 2, // 商品类型 1: 产品 2: 仪器
  30. shopId: GLOBAL_SHOP_ID,
  31. action: $('#coreServer').val() + '/tools/image/upload/multi',
  32. formData: {
  33. // 仪器名称
  34. name: '',
  35. // 仪器别名
  36. alias: '',
  37. // 仪器概述
  38. discription: '',
  39. // 仪器图片
  40. image: '',
  41. // 认证链接
  42. authLink: '',
  43. // 认证二维码
  44. authQrCode: '',
  45. // 仪器参数
  46. paramList: '',
  47. // 仪器优点
  48. advantage: '',
  49. // 仪器缺点
  50. disadvantage: '',
  51. // 仪器原理
  52. principle: '',
  53. // 品牌
  54. brand: '',
  55. // 产地
  56. producePlace: '',
  57. // 上市时间
  58. marketTime: '',
  59. // 供应商
  60. company: '',
  61. // NMPA认证时间
  62. nmpaTime: '',
  63. // 仪器认证
  64. authImageList: '',
  65. // 适应证
  66. adaptiveMan: '',
  67. // 不适应人群
  68. unAdaptiveMan: '',
  69. // 注意事项
  70. aroundOperation: '',
  71. // 效果展示图片列表
  72. // displayImageList: '',
  73. // 常见问题
  74. questionList: '',
  75. // 仪器类别
  76. typeId: '',
  77. // 仪器状态
  78. status: 1,
  79. // seo关键词
  80. seoKeyword: '',
  81. // 仪器链接
  82. productLink: '',
  83. },
  84. rules: {
  85. // 仪器名称
  86. name: [{required: true, message: '仪器名称不能为空', trigger: ['change', 'blur']}],
  87. // 仪器别名
  88. alias: [{required: true, message: '仪器别名不能为空', trigger: ['change', 'blur']}],
  89. // 仪器概述
  90. discription: [{required: true, message: '仪器概述不能为空', trigger: ['change', 'blur']}],
  91. // 仪器图片
  92. image: [{required: true, message: '请上传仪器图片', trigger: 'change'}],
  93. // 产品链接
  94. productLink: [{required: true, message: '产品链接不能为空', trigger: ['change', 'blur']}],
  95. // 产仪器参数
  96. paramList: [{required: true, validator: validateParamList, trigger: 'change'}],
  97. // // 认证链接
  98. // authLink: [{required: true, message: '请输入认证链接', trigger: ['change', 'blur']}],
  99. // // 认证二维码
  100. // authQrCode: [{required: true, message: '请上传证二维码', trigger: 'change'}],
  101. // // 仪器优点
  102. // advantage: [{required: true, message: '仪器优点不能为空', trigger: 'change'}],
  103. // // 仪器缺点
  104. // disadvantage: [{required: true, message: '仪器缺点不能为空', trigger: 'change'}],
  105. // // 仪器原理
  106. // principle: [{required: true, message: '仪器原理不能为空', trigger: 'change'}],
  107. // // 品牌
  108. // brand: [{required: true, message: '请输入仪器品牌', trigger: ['change', 'blur']}],
  109. // // 产地
  110. // producePlace: [{required: true, message: '仪器产地不能为空', trigger: ['change', 'blur']}],
  111. // // 上市时间
  112. // marketTime: [{required: true, message: '请填写上市时间', trigger: 'change'}],
  113. // // 供应商
  114. // company: [{required: true, message: '公司/厂商不能为空', trigger: ['change', 'blur']}],
  115. // // NMPA认证时间
  116. // nmpaTime: [{required: true, message: '请填写NMPA认证时间', trigger: 'change'}],
  117. // // 仪器认证
  118. // authImageList: [{required: true, message: '请上传仪器认证图片', trigger: 'change'}],
  119. // // 适应证
  120. // adaptiveMan: [{required: true, message: '适应人群不能为空', trigger: 'change'}],
  121. // // 不适应人群
  122. // unAdaptiveMan: [{required: true, message: '不适应人群不能为空', trigger: 'change'}],
  123. // // 术前术后
  124. // aroundOperation: [{required: true, message: '术前术后不能为空', trigger: 'change'}],
  125. // // 效果展示图片列表
  126. // displayImageList: [{required: true, message: '请上传效果展示图片', trigger: 'change'}],
  127. // // 常见问题
  128. // questionList: [{required: true, validator: validateQuestionList, trigger: 'change'}],
  129. // // 仪器类别
  130. // typeId: [{required: true, message: '请选择仪器类别', trigger: 'change'}],
  131. // // 仪器状态
  132. // status: [{required: true, message: '请选择仪器状态', trigger: 'change'}],
  133. },
  134. // 仪器类别列表
  135. typeList: [],
  136. // 仪器参数
  137. // paramList: [],
  138. paramEmptyList: [], // 占位
  139. minLimitParams: 2,
  140. // 常见问题
  141. questionEmptyList: [], // 占位
  142. minLimitQuestions: 2,
  143. // 仪器认证
  144. authImageList: [],
  145. // 效果展示图片列表
  146. displayImageList: [], // 初始化列表
  147. dialogVisible: false,
  148. dialogImageUrl: '',
  149. // 日期选择格式
  150. marketTimeType: 'year',
  151. nmpaTimeType: 'year',
  152. // 空缺数量
  153. emptyNum: ''
  154. }
  155. },
  156. computed: {
  157. // 仪器参数
  158. paramList() {
  159. const filter = this.paramEmptyList.filter(param => param.content !== '' && param.name !== '')
  160. if (filter.length > 0) return filter.map(param => ({name: param.name, content: param.content}))
  161. return []
  162. },
  163. // 常见问题
  164. questionList() {
  165. const filter = this.questionEmptyList.filter(item => item.question !== '' && item.answer !== '')
  166. if (filter.length > 0) return filter.map(item => ({question: item.question, answer: item.answer}))
  167. return []
  168. }
  169. },
  170. mounted: function mounted() {
  171. $('.navLayout').find('.navList').removeClass("on").find('.con').hide().find('a').removeClass("on");
  172. $('.navLayout').find('.navList').eq(3).addClass("on").find('.con').show().find('a').eq(1).addClass("on");
  173. },
  174. created() {
  175. this.getTypeList();
  176. this.watchArrayStatus(['paramList', 'questionList', 'authImageList']);
  177. this.getProductFormData();
  178. },
  179. methods: {
  180. // 返回文章列表页面
  181. handleBack: function handleBack() {
  182. localStorage.removeItem('target-name');
  183. window.open('/supplier/encyclopedia/instrument-list.html', 'supplier-instrument-list');
  184. window.close();
  185. },
  186. // 保存事件
  187. handleSave() {
  188. this.$refs.ruleForm.validate(valide => {
  189. console.log(valide);
  190. if (!valide) {
  191. this.socrllToErrorInput()
  192. return;
  193. }
  194. this.emptyNum = this.validateEmptyParams(this.formData)
  195. if( this.emptyNum> 0 && this.formData.status === 1){
  196. this.$confirm('您还剩余' + this.emptyNum + '项未完善,将会导致用户对您产品/仪器的认识度不够,确认是否提交?', '提示', {
  197. confirmButtonText: '是',
  198. cancelButtonText: '否'
  199. }).then(() => {
  200. this.saveFormData()
  201. })
  202. } else{
  203. this.saveFormData()
  204. }
  205. })
  206. },
  207. // 校验空参数个数
  208. validateEmptyParams(params){
  209. const keys = Object.keys(params)
  210. console.log(params)
  211. let count = 0
  212. keys.forEach(key => {
  213. if(typeof params[key] === "string"){
  214. if(params[key] === '' || params[key].trim().length <= 0){
  215. count ++
  216. }
  217. }else if(typeof params[key] === 'number'){
  218. console.log(key)
  219. }else if(typeof params[key] === 'object'){
  220. if(params[key] instanceof Array){
  221. if(params[key].length <= 0){
  222. count ++
  223. }
  224. }else {
  225. if(params[key] === null){
  226. count ++
  227. }
  228. }
  229. }else if(typeof params[key] === 'undefined'){
  230. count ++
  231. }
  232. })
  233. return count;
  234. },
  235. // 裁切时间格式
  236. sliceDateStr(time, type) {
  237. if(!time) return ''
  238. time = dateFormat(time, 'yyyy-MM-dd')
  239. if (type === 'year') {
  240. time = time.slice(0, 4)
  241. } else if (type === 'month') {
  242. time = time.slice(0, 7)
  243. }
  244. return time
  245. },
  246. // 保存表单数据
  247. saveFormData() {
  248. const that = this;
  249. const params = {
  250. ...this.formData,
  251. shopId: this.shopId,
  252. commodityType: this.commodityType,
  253. paramList: JSON.stringify(this.paramList),
  254. questionList: JSON.stringify(this.questionList),
  255. // marketTime: dateFormat(this.formData.marketTime, 'yyyy-MM-dd'),
  256. // nmpaTime: dateFormat(this.formData.nmpaTime, 'yyyy-MM-dd'),
  257. authImageList: this.authImageList.map(image => (image.response ? image.response.data : image.url)),
  258. // displayImageList: this.displayImageList.map(image => (image.response ? image.response.data : image.url))
  259. };
  260. /* 处理时间 */
  261. if(this.formData.marketTime){
  262. params.marketTime = this.sliceDateStr(this.formData.marketTime, this.marketTimeType)
  263. }
  264. /* 处理时间 */
  265. if(this.formData.nmpaTime){
  266. params.nmpaTime = this.sliceDateStr(this.formData.nmpaTime, this.nmpaTimeType)
  267. }
  268. if (this.productId) params.productId = this.productId;
  269. params.emptyNum = this.emptyNum;
  270. console.log(params);
  271. SupplierApi.ShopBaikeProductSave(params, function (res) {
  272. if (res.code === 0) {
  273. CAIMEI.dialog('保存成功', false);
  274. setTimeout(function () {
  275. that.handleBack();
  276. }, 2000);
  277. } else {
  278. CAIMEI.Alert(res.msg, '确认', false)
  279. }
  280. })
  281. },
  282. // 获取时间类型(年月日)
  283. getTimeType(time){
  284. time = time.split('-')
  285. if(time.length === 1){
  286. return 'year'
  287. }else if(time.length === 2){
  288. return 'month'
  289. }else {
  290. return 'date'
  291. }
  292. },
  293. initFormData: function(formData){
  294. console.log(formData);
  295. // 初始化this.formData
  296. for (var key in this.formData) {
  297. if (formData.hasOwnProperty(key)) {
  298. // 如果是数组 就取值length
  299. if(formData[key] instanceof Array){
  300. const len = formData[key].length
  301. this.formData[key] = len > 0 ? len : ''
  302. } else if(['marketTime', 'nmpaTime'].includes(key)){
  303. this.formData[key] = new Date(formData[key])
  304. if(key === 'marketTime'){
  305. this.marketTimeType = this.getTimeType(formData[key])
  306. }else{
  307. this.nmpaTimeType = this.getTimeType(formData[key])
  308. }
  309. }
  310. else {
  311. this.formData[key] = formData[key];
  312. }
  313. }
  314. }
  315. // 处理参数
  316. this.resetEmptyListData(formData.paramList, formData.questionList);
  317. // 处理图片
  318. this.authImageList = formData.authImageList.map(image => ({ url: image, name: 'authImage'}))
  319. // this.displayImageList = formData.displayImageList.map(image => ({ url: image, name: 'authImage'}))
  320. },
  321. // 获取表单数据
  322. getProductFormData() {
  323. this.productId = localStorage.getItem('productId') || 0;
  324. localStorage.removeItem('productId');
  325. if (this.productId > 0) {
  326. const that = this;
  327. SupplierApi.GetShopBaikeProductForm({productId: this.productId}, function (res) {
  328. if (res.code === 0) {
  329. that.initFormData(res.data);
  330. } else {
  331. CAIMEI.dialog('获取仪器数据失败', false);
  332. setTimeout(function () {
  333. that.handleBack();
  334. }, 2000);
  335. }
  336. });
  337. }else {
  338. this.resetEmptyListData([],[])
  339. }
  340. },
  341. // 获取分类列表
  342. getTypeList() {
  343. const that = this;
  344. SupplierApi.ShopBaikeProductTypeList({commodityType: this.commodityType}, function (res) {
  345. that.typeList = res.data;
  346. console.log(res);
  347. })
  348. },
  349. //添加一条参数
  350. addParam() {
  351. this.paramEmptyList.push({
  352. name: '',
  353. content: '',
  354. p1: '参数名',
  355. p2: '参数信息',
  356. })
  357. },
  358. // 删除一条参数
  359. removeParam(index) {
  360. this.paramEmptyList.splice(index, 1)
  361. },
  362. //添加一条问答
  363. addQuestion() {
  364. this.questionEmptyList.push({
  365. question: '',
  366. answer: '',
  367. p1: '请输入问题内容',
  368. p2: '请输入问题解答内容',
  369. })
  370. },
  371. // 删除一条问答
  372. removeQuestion(index) {
  373. this.questionEmptyList.splice(index, 1)
  374. },
  375. // 初始化可变表单数据
  376. resetEmptyListData(paramSource, questionSource) {
  377. this.makeEmptyList({
  378. target: this.paramEmptyList,
  379. source: paramSource,
  380. limit: this.minLimitParams,
  381. key: 'name',
  382. value: 'content',
  383. })
  384. this.makeEmptyList({
  385. target: this.questionEmptyList,
  386. source: questionSource,
  387. limit: this.minLimitQuestions,
  388. key: 'question',
  389. value: 'answer',
  390. })
  391. },
  392. // 创建可变表单占位列表
  393. makeEmptyList(options) {
  394. options = {
  395. target: [], // 目标数组
  396. source: [], // 数据源数组
  397. key: '',
  398. value: '',
  399. limit: 0, // 最小条数
  400. argsList: ['参数', '品牌'], // placeholder文本
  401. ...options,
  402. }
  403. let {target, source, limit, argsList, key, value} = options
  404. let len = 0
  405. target.push(
  406. ...source.map(v => {
  407. v.p1 = `例如:${argsList[0]}`
  408. v.p2 = `请输入:${argsList[0]}信息`
  409. return v
  410. })
  411. )
  412. len = limit - target.length
  413. for (let i = 0; i < len; i++) {
  414. const obj = {}
  415. obj[key] = ''
  416. obj[value] = ''
  417. if (i <= argsList.length - 1) {
  418. obj.p1 = `例如:${argsList[i]}`
  419. obj.p2 = `请输入:${argsList[i]}信息`
  420. } else {
  421. obj.p1 = `例如:${argsList[0]}`
  422. obj.p2 = `请输入:${argsList[0]}信息`
  423. }
  424. target.push(obj)
  425. }
  426. },
  427. handleAuthQrCodeSuccess(response){
  428. this.$refs.authQrCodeUploader.clearFiles();
  429. this.formData.authQrCode = response.data
  430. },
  431. // 仪器图片上传成功的回调
  432. handleImageSuccess(response) {
  433. this.$refs.coverUploader.clearFiles();
  434. this.formData.image = response.data
  435. },
  436. // 认证图片上传成功的回调
  437. handleAuthImageSuccess(response, file, fileList) {
  438. this.authImageList = fileList
  439. },
  440. // 移除认证图片
  441. handleAuthImageRemove(file, fileList) {
  442. // console.log(fileList)
  443. this.authImageList = fileList
  444. },
  445. // 效果图片上传成功的回调
  446. handleDisplayImageSuccess(response, file, fileList) {
  447. this.displayImageList = fileList
  448. },
  449. // 移除效果图片
  450. handleDisplayImageRemove(file, fileList) {
  451. this.displayImageList = fileList
  452. },
  453. // 图片上传前的回调
  454. beforeImageUpload(file) {
  455. const isLt2M = file.size / 1024 / 1024 < 2
  456. if (!isLt2M) {
  457. this.$message.error('上传头像图片大小不能超过 2MB!')
  458. }
  459. return isLt2M
  460. },
  461. // 预览图片
  462. handlePictureCardPreview(file) {
  463. this.dialogImageUrl = file.url
  464. this.dialogVisible = true
  465. },
  466. // 预览图片弹窗
  467. handlePictureCardPreview(file) {
  468. this.dialogImageUrl = file.url
  469. this.dialogVisible = true
  470. },
  471. // 监听formData中类型为数组的数据状态
  472. watchArrayStatus(args = []) {
  473. args.forEach(arg => {
  474. if (this[arg] instanceof Array) {
  475. this.$watch(
  476. arg,
  477. (nval, oval) => {
  478. console.log(arg, nval.length);
  479. console.log(this[arg]);
  480. if(nval.length > 0){
  481. this.formData[arg] = nval.length
  482. } else{
  483. this.formData[arg] = ''
  484. }
  485. },
  486. {deep: true}
  487. )
  488. }
  489. })
  490. },
  491. // 滚动到必填位置
  492. socrllToErrorInput(){
  493. this.$nextTick(() => {
  494. const scrollTop = $('.el-form-item__error').eq(0).parent().siblings('.el-form-item__label').offset().top
  495. $('body,html').animate({
  496. scrollTop: scrollTop - $('#globalHead').height() - 40
  497. }, 800)
  498. })
  499. }
  500. },
  501. })
  502. app.$mount('#instrumentEdit')