Przeglądaj źródła

新增样式修改

695593266@qq.com 1 miesiąc temu
rodzic
commit
79a19d2146

+ 9 - 0
src/api/material/list.js

@@ -170,6 +170,15 @@ export async function changeOnOff(id) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+
+// 发布物品/产品
+export async function publishCategory(data) {
+  const res = await request.post(`/main/category/publish`, data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 // 获取实体列表分页
 export async function queryBindSubstanceList(data) {
   let par = new URLSearchParams(data);

+ 4 - 5
src/enum/dict.js

@@ -89,7 +89,7 @@ export default {
   实验模板样式: 'experiment_template_style',
   表计类型: 'meter_type',
   印章类型: 'main_seal_type',
-  支付类型: 'payment_type',
+  支付类型: 'payment_type'
 };
 
 export const numberList = [
@@ -296,9 +296,9 @@ export const calcReceiveDateTypeOp = [
     label: '对账单日期',
     value: 5
   }
-]
+];
 
-// 收/付款日确定方式         
+// 收/付款日确定方式
 export const payConfirmTypeOp = [
   {
     label: '交易日',
@@ -308,8 +308,7 @@ export const payConfirmTypeOp = [
     label: 'X天后',
     value: 2
   }
-]
-
+];
 
 //持证类型
 export const holderTypeOptions = [

+ 36 - 2
src/views/material/product/components/index-data.vue

@@ -226,6 +226,17 @@
           BOM
         </el-link>
 
+        <el-popconfirm
+          class="ele-action"
+          title="确定要发布此物品吗?"
+          @confirm="publish(row)"
+          v-if="row.isPublished != 1 && $hasPermission('main:category:update')"
+        >
+          <template v-slot:reference>
+            <el-link type="primary" :underline="false"> 发布 </el-link>
+          </template>
+        </el-popconfirm>
+
         <!-- <el-link
           type="primary"
           v-if="row.isProduct == 1"
@@ -339,7 +350,8 @@
     removeMaterial,
     importCategorySparePart,
     exportFile,
-    changeOnOff
+    changeOnOff,
+    publishCategory
   } from '@/api/material/list.js';
 
   import { getBomGetById } from '@/api/material/BOM.js';
@@ -707,6 +719,16 @@
             align: 'center',
             showOverflowTooltip: true
           },
+          {
+            prop: 'isPublished',
+            label: '发布状态',
+            align: 'center',
+            minWidth: 100,
+            formatter: (row, column) => {
+              return row.isPublished == 1 ? '已发布' : '未发布';
+            },
+            showOverflowTooltip: true
+          },
           {
             prop: 'isEnabled',
             align: 'center',
@@ -921,7 +943,7 @@
             {
               columnKey: 'action',
               label: '操作',
-              width: 260,
+              width: 300,
               align: 'center',
               resizable: false,
               slot: 'action',
@@ -944,6 +966,18 @@
         });
       },
 
+      publish(row) {
+        const loading = this.$loading({ lock: true });
+        publishCategory({ categoryId: row.id })
+          .then((res) => {
+            this.$message.success(res.message || '发布成功');
+            this.reloadNew();
+          })
+          .finally(() => {
+            loading.close();
+          });
+      },
+
       /* 显示编辑 */
       openEdit(row, status) {
         console.log(status, this.currentData, 'status');

+ 1485 - 0
src/views/system/parmasManage/index-new.vue

@@ -0,0 +1,1485 @@
+<template>
+  <div class="ele-body parameter-setting-page">
+    <div class="parameter-shell">
+      <aside class="module-nav">
+        <div class="module-nav-title">参数模块</div>
+        <button
+          type="button"
+          class="module-nav-item"
+          :class="{ active: where.moduleCode === '' }"
+          @click="changeModule('')"
+        >
+          <span>全部模块</span>
+          <em>{{ paramsList.length }}</em>
+        </button>
+        <button
+          v-for="item in businessModule"
+          :key="item.value"
+          type="button"
+          class="module-nav-item"
+          :class="{ active: where.moduleCode === item.value }"
+          @click="changeModule(item.value)"
+        >
+          <span>{{ item.label }}</span>
+          <em>{{ getModuleCount(item.value) }}</em>
+        </button>
+      </aside>
+
+      <main class="parameter-content">
+        <div class="parameter-toolbar">
+          <div class="toolbar-title">
+            <strong>{{ currentModuleName }}</strong>
+            <span>{{ filteredList.length }} 项配置</span>
+          </div>
+          <el-form
+            class="parameter-search"
+            label-width="74px"
+            @submit.native.prevent
+            @keyup.enter.native="search"
+          >
+            <el-form-item label="编码:">
+              <el-input
+                v-model.trim="where.code"
+                clearable
+                placeholder="请输入编码"
+                @clear="search"
+              />
+            </el-form-item>
+            <el-form-item label="名称:">
+              <el-input
+                v-model.trim="where.name"
+                clearable
+                placeholder="请输入名称"
+                @clear="search"
+              />
+            </el-form-item>
+            <el-form-item label="模块名称:">
+              <el-select
+                v-model="where.moduleCode"
+                clearable
+                placeholder="请选择模块"
+                @change="search"
+              >
+                <el-option
+                  v-for="(item, index) in businessModule"
+                  :key="index"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+            <div class="search-actions">
+              <el-button
+                class="toolbar-btn query"
+                type="primary"
+                icon="el-icon-search"
+                :loading="loading"
+                @click="search"
+              >
+                查询
+              </el-button>
+              <el-button
+                class="toolbar-btn reset"
+                icon="el-icon-refresh"
+                @click="reset"
+              >
+                重置
+              </el-button>
+              <el-button
+                v-if="$hasPermission('sys:parameter:save')"
+                class="toolbar-btn add"
+                type="success"
+                icon="el-icon-plus"
+                @click="openEdit('add')"
+              >
+                新增参数
+              </el-button>
+            </div>
+          </el-form>
+        </div>
+
+        <el-empty
+          v-if="!loading && !filteredGroups.length"
+          description="暂无参数"
+        />
+
+        <section
+          v-for="group in filteredGroups"
+          :key="group.moduleCode"
+          class="parameter-group"
+        >
+          <div class="group-title">
+            <span>{{ group.moduleName }}</span>
+            <em>{{ group.children.length }} 项</em>
+          </div>
+          <div class="setting-panel">
+            <div class="setting-head">
+              <span>参数信息</span>
+              <span>参数值</span>
+              <span>启用状态</span>
+              <span>操作</span>
+            </div>
+            <div class="setting-grid">
+              <div
+                v-for="item in group.children"
+                :key="item.id"
+                class="setting-item"
+                :class="{
+                  disabled: item.enable === 1,
+                  changed: isChanged(item)
+                }"
+              >
+                <div class="setting-info">
+                  <el-tooltip
+                    effect="dark"
+                    :content="item.rawName"
+                    placement="top-start"
+                    :open-delay="500"
+                  >
+                    <span class="setting-label">{{ item.displayName }}</span>
+                  </el-tooltip>
+                  <div class="setting-code-row">
+                    <span class="code-label">编码</span>
+                    <span class="setting-code">{{ item.code }}</span>
+                  </div>
+                </div>
+
+                <div class="setting-control">
+                  <div class="value-block">
+                    <div class="value-editor">
+                      <div
+                        v-if="item.viewType === 'checkbox'"
+                        class="yes-no-control"
+                        :class="{ disabled: item.saving || item.enable === 1 }"
+                      >
+                        <button
+                          type="button"
+                          :class="{ active: !item.checked, no: !item.checked }"
+                          :disabled="item.saving || item.enable === 1"
+                          @click="setCheckboxValue(item, false)"
+                        >
+                          否
+                        </button>
+                        <button
+                          type="button"
+                          :class="{ active: item.checked, yes: item.checked }"
+                          :disabled="item.saving || item.enable === 1"
+                          @click="setCheckboxValue(item, true)"
+                        >
+                          是
+                        </button>
+                      </div>
+
+                      <el-select
+                        v-else-if="item.viewType === 'select'"
+                        v-model="item.editValue"
+                        :disabled="item.saving || item.enable === 1"
+                        filterable
+                        placeholder="请选择"
+                        @change="saveItem(item)"
+                      >
+                        <el-option
+                          v-for="option in item.options"
+                          :key="option.value"
+                          :label="option.label"
+                          :value="option.value"
+                        />
+                      </el-select>
+
+                      <el-input
+                        v-else-if="item.viewType === 'customInput'"
+                        v-model.trim="item.editValue"
+                        :disabled="item.saving || item.enable === 1"
+                        :placeholder="getInputPlaceholder(item)"
+                        @blur="saveItem(item)"
+                        @keyup.enter.native="saveItem(item)"
+                      >
+                        <template v-if="getInputUnit(item)" slot="append">
+                          {{ getInputUnit(item) }}
+                        </template>
+                      </el-input>
+
+                      <el-input
+                        v-else
+                        v-model.trim="item.editValue"
+                        :disabled="item.saving || item.enable === 1"
+                        placeholder="请输入"
+                        @blur="saveItem(item)"
+                        @keyup.enter.native="saveItem(item)"
+                      />
+                    </div>
+                  </div>
+
+                  <div class="state-block">
+                    <div class="state-editor">
+                      <span
+                        class="state-pill"
+                        :class="{ off: item.enable === 1 }"
+                      >
+                        <i></i>
+                        {{ item.enable === 0 ? '已启用' : '已停用' }}
+                      </span>
+                      <el-switch
+                        v-model="item.enable"
+                        class="enable-switch"
+                        :disabled="item.saving"
+                        :active-value="0"
+                        :inactive-value="1"
+                        @change="saveItem(item, { force: true })"
+                      />
+                    </div>
+                  </div>
+
+                  <i v-if="item.saving" class="el-icon-loading save-state" />
+                  <i
+                    v-else-if="item.saved"
+                    class="el-icon-check save-state success"
+                  />
+                </div>
+
+                <div class="card-actions">
+                  <el-tooltip content="编辑配置" placement="top">
+                    <button
+                      v-if="$hasPermission('sys:parameter:update')"
+                      type="button"
+                      class="action-icon primary"
+                      @click="openEdit('edit', item.id)"
+                    >
+                      <i class="el-icon-edit-outline"></i>
+                    </button>
+                  </el-tooltip>
+                  <el-tooltip content="查看详情" placement="top">
+                    <button
+                      type="button"
+                      class="action-icon info"
+                      @click="openEdit('view', item.id)"
+                    >
+                      <i class="el-icon-view"></i>
+                    </button>
+                  </el-tooltip>
+                  <el-popconfirm
+                    v-if="$hasPermission('sys:parameter:delete')"
+                    title="确定要删除当前参数吗?"
+                    @confirm="removeItem(item)"
+                  >
+                    <template v-slot:reference>
+                      <button type="button" class="action-icon danger">
+                        <i class="el-icon-delete"></i>
+                      </button>
+                    </template>
+                  </el-popconfirm>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+      </main>
+    </div>
+
+    <add-or-edit-dialog
+      v-if="addOrEditDialogFlag"
+      ref="addOrEditDialogRef"
+      :add-or-edit-dialog-flag.sync="addOrEditDialogFlag"
+      @reload="reloadAfterEdit"
+    />
+  </div>
+</template>
+
+<script>
+  import AddOrEditDialog from './addOrEditDialog.vue';
+  import {
+    parameterPageList,
+    removeParameterAPI,
+    updateParameterAPI
+  } from '@/api/system/parmasManage';
+  import { businessModule } from '@/enum/dict.js';
+
+  const CUSTOM_INPUT_CODES = [
+    'login_session_expireTime',
+    'account_password_validity',
+    'account_password_valid_period',
+    'password_validity_period',
+    'password_expireTime'
+  ];
+
+  const POSITIVE_WORDS = [
+    '是',
+    '必填',
+    '启用',
+    '需要',
+    '审批',
+    '判断',
+    '锁定',
+    '隐藏',
+    '自动',
+    '生成',
+    '允许',
+    '启用'
+  ];
+
+  const NEGATIVE_WORDS = [
+    '否',
+    '不必填',
+    '非必填',
+    '不启用',
+    '不需要',
+    '不审批',
+    '不判断',
+    '不锁定',
+    '不隐藏',
+    '不允许',
+    '可以重新',
+    '不拆解'
+  ];
+
+  export default {
+    name: 'ParameterSettingNew',
+    components: {
+      AddOrEditDialog
+    },
+    data() {
+      return {
+        loading: false,
+        addOrEditDialogFlag: false,
+        where: {
+          moduleCode: '',
+          code: '',
+          name: ''
+        },
+        paramsList: [],
+        businessModule
+      };
+    },
+    computed: {
+      isQianKun() {
+        return window.__POWERED_BY_QIANKUN__;
+      },
+      filteredList() {
+        const codeKeyword = this.where.code.trim().toLowerCase();
+        const nameKeyword = this.where.name.trim().toLowerCase();
+        return this.paramsList.filter((item) => {
+          const matchModule =
+            !this.where.moduleCode || item.moduleCode === this.where.moduleCode;
+          const matchCode =
+            !codeKeyword ||
+            String(item.code || '')
+              .toLowerCase()
+              .includes(codeKeyword);
+          const matchName =
+            !nameKeyword ||
+            String(item.rawName || '')
+              .toLowerCase()
+              .includes(nameKeyword);
+          return matchModule && matchCode && matchName;
+        });
+      },
+      filteredGroups() {
+        const result = [];
+        const groupMap = {};
+        this.filteredList.forEach((item) => {
+          const key = item.moduleCode || 'unknown';
+          if (!groupMap[key]) {
+            groupMap[key] = {
+              moduleCode: key,
+              moduleName: item.moduleName || '未分组',
+              children: []
+            };
+            result.push(groupMap[key]);
+          }
+          groupMap[key].children.push(item);
+        });
+        return result;
+      },
+      currentModuleName() {
+        if (!this.where.moduleCode) return '全部参数';
+        const current = this.businessModule.find(
+          (item) => item.value === this.where.moduleCode
+        );
+        return current ? current.label : '参数配置';
+      }
+    },
+    created() {
+      this.loadData();
+    },
+    methods: {
+      async loadData() {
+        this.loading = true;
+        try {
+          const res = await parameterPageList({
+            moduleCode: '',
+            code: '',
+            name: '',
+            pageNum: 1,
+            size: 999
+          });
+          this.paramsList = (res.list || []).map((item) =>
+            this.normalizeParam(item)
+          );
+        } finally {
+          this.loading = false;
+        }
+      },
+      normalizeParam(param) {
+        const options = this.parseOptions(param.name);
+        const viewType = this.resolveViewType(param, options);
+        const displayName = this.getDisplayName(param.name, options);
+        const checkedValue = this.getCheckedValue(param, options);
+        const uncheckedValue = this.getUncheckedValue(
+          param,
+          options,
+          checkedValue
+        );
+
+        return {
+          ...param,
+          rawName: param.name || '',
+          displayName,
+          options,
+          viewType,
+          checkedValue,
+          uncheckedValue,
+          checked: String(param.value) === String(checkedValue),
+          editValue: String(param.value == null ? '' : param.value),
+          originalValue: String(param.value == null ? '' : param.value),
+          originalEnable: param.enable,
+          saving: false,
+          saved: false
+        };
+      },
+      parseOptions(name) {
+        const text = String(name || '');
+        const blocks = [];
+        const bracketReg = /[((]([^()()]*)[))]/g;
+        let match = bracketReg.exec(text);
+        while (match) {
+          blocks.push(match[1]);
+          match = bracketReg.exec(text);
+        }
+        if (!blocks.length) {
+          blocks.push(text);
+        }
+
+        for (let i = 0; i < blocks.length; i += 1) {
+          const options = this.parseOptionBlock(blocks[i]);
+          if (options.length >= 2) {
+            return options;
+          }
+        }
+        return [];
+      },
+      parseOptionBlock(block) {
+        const text = String(block || '').trim();
+        const compactOptions = this.parseCompactOptions(text);
+        if (compactOptions.length >= 2) {
+          return compactOptions;
+        }
+        return text
+          .split(/[;;,,、]/)
+          .map((part) => part.trim())
+          .map((part) => {
+            const optionMatch = part.match(/^(\d+)\s*[::]?\s*(.+)$/);
+            if (!optionMatch) return null;
+            return {
+              value: optionMatch[1],
+              label: optionMatch[2].replace(/[;;,,。]+$/, '').trim()
+            };
+          })
+          .filter(Boolean);
+      },
+      parseCompactOptions(text) {
+        const options = [];
+        const optionReg = /(\d+)\s*[::]?\s*([^0-9]+?)(?=\s*\d+\s*[::]?|$)/g;
+        let match = optionReg.exec(text);
+        while (match) {
+          const label = match[2].replace(/[;;,,。]+$/, '').trim();
+          if (label) {
+            options.push({
+              value: match[1],
+              label
+            });
+          }
+          match = optionReg.exec(text);
+        }
+        return options;
+      },
+      resolveViewType(param, options) {
+        const code = String(param.code || '');
+        const name = String(param.name || '');
+        if (
+          CUSTOM_INPUT_CODES.includes(code) ||
+          /登录会话失效时间|账户密码有效期/.test(name)
+        ) {
+          return 'customInput';
+        }
+        if (options.length >= 3) return 'select';
+        if (options.length === 2) {
+          return this.isCheckboxParam(name, options) ? 'checkbox' : 'select';
+        }
+        return 'input';
+      },
+      isCheckboxParam(name, options) {
+        const optionText = options.map((item) => item.label).join('');
+        return (
+          /是否|只?能|启用|必填|需要|审批|锁定/.test(name) ||
+          /是|否|必填|启用|需要|审批|判断|锁定/.test(optionText)
+        );
+      },
+      getDisplayName(name, options) {
+        let text = String(name || '');
+        if (options.length) {
+          text = text.replace(/[((][^()()]*[))]/g, '');
+        }
+        return text.replace(/[::]\s*$/, '').trim();
+      },
+      getCheckedValue(param, options) {
+        if (!options.length) return '1';
+        const affirmative = options.find((item) => this.isPositiveOption(item));
+        if (affirmative) return affirmative.value;
+        const oneOption = options.find((item) => String(item.value) === '1');
+        return oneOption ? oneOption.value : options[0].value;
+      },
+      getUncheckedValue(param, options, checkedValue) {
+        const unchecked = options.find(
+          (item) => String(item.value) !== String(checkedValue)
+        );
+        return unchecked ? unchecked.value : '0';
+      },
+      isPositiveOption(option) {
+        const label = String(option.label || '');
+        if (NEGATIVE_WORDS.some((word) => label.includes(word))) return false;
+        return POSITIVE_WORDS.some((word) => label.includes(word));
+      },
+      getInputUnit(item) {
+        const name = item.rawName || '';
+        const unitMatch = name.match(/单位\s*[::]\s*([^))]+)/);
+        if (unitMatch) return unitMatch[1];
+        if (/frequency|频率/.test(item.code + name)) return '小时';
+        return '';
+      },
+      getInputPlaceholder(item) {
+        const unit = this.getInputUnit(item);
+        return unit ? `请输入${unit}数值` : '请输入参数值';
+      },
+      changeModule(moduleCode) {
+        this.where.moduleCode = moduleCode;
+      },
+      getModuleCount(moduleCode) {
+        return this.paramsList.filter((item) => item.moduleCode === moduleCode)
+          .length;
+      },
+      search() {
+        this.where.code = this.where.code.trim();
+        this.where.name = this.where.name.trim();
+      },
+      reset() {
+        this.where = {
+          moduleCode: '',
+          code: '',
+          name: ''
+        };
+      },
+      isChanged(item) {
+        return (
+          String(item.editValue) !== String(item.originalValue) ||
+          item.enable !== item.originalEnable
+        );
+      },
+      handleCheckboxChange(item) {
+        item.editValue = item.checked ? item.checkedValue : item.uncheckedValue;
+        this.saveItem(item, { force: true });
+      },
+      setCheckboxValue(item, checked) {
+        if (item.saving || item.enable === 1 || item.checked === checked)
+          return;
+        item.checked = checked;
+        this.handleCheckboxChange(item);
+      },
+      openEdit(type, id) {
+        this.addOrEditDialogFlag = true;
+        this.$nextTick(() => {
+          this.$refs.addOrEditDialogRef.init(type, id);
+        });
+      },
+      async reloadAfterEdit() {
+        await this.loadData();
+      },
+      async removeItem(item) {
+        await removeParameterAPI([item.id]);
+        this.$message.success('删除成功');
+        await this.loadData();
+        this.refreshParamsCache();
+      },
+      async saveItem(item, options = {}) {
+        if (!options.force && !this.isChanged(item)) return;
+
+        item.saving = true;
+        item.saved = false;
+        try {
+          await updateParameterAPI(this.buildSavePayload(item));
+          item.value = String(item.editValue == null ? '' : item.editValue);
+          item.originalValue = item.value;
+          item.originalEnable = item.enable;
+          item.saved = true;
+          this.refreshParamsCache();
+          window.setTimeout(() => {
+            item.saved = false;
+          }, 1400);
+          this.$message({
+            type: 'success',
+            message: '保存成功',
+            customClass: 'ele-message-border'
+          });
+        } catch (e) {
+          item.editValue = item.originalValue;
+          item.checked =
+            String(item.originalValue) === String(item.checkedValue);
+          item.enable = item.originalEnable;
+          this.$message.error(e.message || '保存失败');
+        } finally {
+          item.saving = false;
+        }
+      },
+      buildSavePayload(item) {
+        const payload = { ...item };
+        [
+          'rawName',
+          'displayName',
+          'options',
+          'viewType',
+          'checkedValue',
+          'uncheckedValue',
+          'checked',
+          'editValue',
+          'originalValue',
+          'originalEnable',
+          'saving',
+          'saved'
+        ].forEach((key) => {
+          delete payload[key];
+        });
+        return {
+          ...payload,
+          name: item.rawName,
+          value: String(item.editValue == null ? '' : item.editValue),
+          enable: item.enable
+        };
+      },
+      refreshParamsCache() {
+        const store = this.isQianKun ? this.$portalStore : this.$store;
+        if (store && store.dispatch) {
+          store.dispatch('paramsSetData/setParamsDataInfo');
+        }
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  .parameter-setting-page {
+    box-sizing: border-box;
+    height: calc(100vh - 100px);
+    min-height: 0;
+    overflow: hidden;
+    background: #f4f7fb;
+  }
+
+  .parameter-shell {
+    display: flex;
+    align-items: flex-start;
+    box-sizing: border-box;
+    height: 100%;
+    min-height: 0;
+    border: 1px solid #e5eaf2;
+    background: #fff;
+    box-shadow: 0 10px 30px rgba(21, 38, 66, 0.06);
+  }
+
+  .module-nav {
+    flex: 0 0 220px;
+    align-self: flex-start;
+    height: 100%;
+    max-height: 100%;
+    padding: 18px 12px;
+    overflow-y: auto;
+    border-right: 1px solid #e6ebf2;
+    background: #f7f9fc;
+
+    &::-webkit-scrollbar {
+      width: 6px;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      border-radius: 3px;
+      background: #cbd5e1;
+    }
+  }
+
+  .module-nav-title {
+    padding: 0 12px 12px;
+    color: #7b8794;
+    font-size: 12px;
+    font-weight: 600;
+    letter-spacing: 0;
+  }
+
+  .module-nav-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 100%;
+    height: 42px;
+    margin-bottom: 4px;
+    padding: 0 12px;
+    border: 0;
+    border-radius: 6px;
+    background: transparent;
+    color: #344054;
+    font-size: 14px;
+    text-align: left;
+    cursor: pointer;
+    outline: none;
+    transition: all 0.18s ease;
+
+    span {
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+
+    em {
+      min-width: 24px;
+      height: 20px;
+      padding: 0 7px;
+      border-radius: 10px;
+      background: #e9eef5;
+      color: #667085;
+      font-size: 12px;
+      font-style: normal;
+      line-height: 20px;
+      text-align: center;
+    }
+
+    &:hover {
+      background: #edf4ff;
+      color: #1677ff;
+    }
+
+    &.active {
+      background: #1677ff;
+      color: #fff;
+      font-weight: 600;
+      box-shadow: 0 8px 18px rgba(22, 119, 255, 0.22);
+
+      em {
+        background: rgba(255, 255, 255, 0.22);
+        color: #fff;
+      }
+    }
+  }
+
+  .parameter-content {
+    flex: 1;
+    height: 100%;
+    min-width: 0;
+    padding: 22px 28px 36px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    scrollbar-gutter: stable;
+  }
+
+  .parameter-toolbar {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 18px;
+    margin-bottom: 22px;
+    padding: 16px 18px;
+    border: 1px solid #e5eaf2;
+    border-radius: 8px;
+    background: #fff;
+  }
+
+  .toolbar-title {
+    flex: 0 0 150px;
+    width: 150px;
+    min-width: 150px;
+
+    strong {
+      display: block;
+      overflow: hidden;
+      color: #101828;
+      font-size: 18px;
+      font-weight: 700;
+      line-height: 26px;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+
+    span {
+      display: block;
+      margin-top: 3px;
+      color: #667085;
+      font-size: 12px;
+      line-height: 18px;
+    }
+  }
+
+  .parameter-search {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    flex: 1;
+    min-width: 0;
+    gap: 10px;
+    margin-bottom: 0;
+
+    ::v-deep .el-form-item {
+      width: 220px;
+      margin-bottom: 0;
+    }
+
+    ::v-deep .el-input__inner {
+      height: 38px;
+      line-height: 38px;
+      border-color: #d9e0ea;
+      border-radius: 6px;
+      background: #fbfcfe;
+
+      &:focus {
+        border-color: #1677ff;
+        background: #fff;
+      }
+    }
+
+    ::v-deep .el-select {
+      width: 100%;
+    }
+
+    ::v-deep .el-form-item__label {
+      color: #5b6b82;
+      font-weight: 600;
+    }
+  }
+
+  .search-actions {
+    display: flex;
+    flex: 0 0 auto;
+    align-items: center;
+    gap: 8px;
+
+    .el-button {
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      min-width: 78px;
+      height: 36px;
+      padding: 0 12px;
+      border-radius: 8px;
+      font-weight: 600;
+      letter-spacing: 0;
+
+      [class^='el-icon-'],
+      [class*=' el-icon-'] {
+        display: inline-flex;
+        align-items: center;
+        justify-content: center;
+        width: 18px;
+        height: 18px;
+        margin-right: 6px;
+        border-radius: 50%;
+        font-size: 13px;
+      }
+    }
+  }
+
+  .toolbar-btn.el-button {
+    border-width: 1px;
+    background: #fff;
+    box-shadow: 0 4px 12px rgba(16, 24, 40, 0.05);
+    transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease,
+      box-shadow 0.16s ease;
+
+    &:active {
+      box-shadow: inset 0 1px 2px rgba(16, 24, 40, 0.08);
+    }
+  }
+
+  .toolbar-btn.query.el-button {
+    border-color: #bdd7ff;
+    background: #f4f8ff;
+    color: #175cd3;
+
+    [class^='el-icon-'],
+    [class*=' el-icon-'] {
+      background: #2f80ed;
+      color: #fff;
+    }
+
+    &:hover {
+      border-color: #7db5ff;
+      background: #edf5ff;
+      color: #0f57c7;
+      box-shadow: 0 7px 16px rgba(47, 128, 237, 0.13);
+    }
+  }
+
+  .toolbar-btn.reset.el-button {
+    border-color: #d7e0ea;
+    background: #fbfcfe;
+    color: #344054;
+
+    [class^='el-icon-'],
+    [class*=' el-icon-'] {
+      background: #eef2f7;
+      color: #526176;
+    }
+
+    &:hover {
+      border-color: #b7c4d6;
+      background: #f6f8fb;
+      color: #1d2939;
+      box-shadow: 0 7px 16px rgba(52, 64, 84, 0.08);
+    }
+  }
+
+  .toolbar-btn.add.el-button {
+    min-width: 96px;
+    border-color: #a8dfbb;
+    background: #f2fbf5;
+    color: #16733a;
+
+    [class^='el-icon-'],
+    [class*=' el-icon-'] {
+      background: #26a65b;
+      color: #fff;
+    }
+
+    &:hover {
+      border-color: #78ca92;
+      background: #eaf8ef;
+      color: #0f6b33;
+      box-shadow: 0 7px 16px rgba(38, 166, 91, 0.13);
+    }
+  }
+
+  .parameter-group {
+    margin-top: 18px;
+  }
+
+  .group-title {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    margin-bottom: 14px;
+    padding: 0 0 0 12px;
+    border-left: 4px solid #1677ff;
+
+    span {
+      color: #101828;
+      font-size: 16px;
+      font-weight: 700;
+      line-height: 24px;
+    }
+
+    em {
+      height: 22px;
+      padding: 0 8px;
+      border-radius: 11px;
+      background: #eef4ff;
+      color: #1677ff;
+      font-size: 12px;
+      font-style: normal;
+      line-height: 22px;
+    }
+  }
+
+  .setting-grid {
+    display: grid;
+    grid-template-columns: 1fr;
+    gap: 0;
+  }
+
+  .setting-panel {
+    overflow: hidden;
+    border: 1px solid #dfe7f2;
+    border-radius: 8px;
+    background: #fff;
+    box-shadow: 0 8px 22px rgba(20, 35, 60, 0.04);
+  }
+
+  .setting-head {
+    display: grid;
+    grid-template-columns: minmax(320px, 1fr) 260px 150px 132px;
+    align-items: center;
+    gap: 20px;
+    min-height: 42px;
+    padding: 0 18px;
+    border-bottom: 1px solid #e5ebf3;
+    background: #f7faff;
+    color: #5b6b82;
+    font-size: 12px;
+    font-weight: 700;
+
+    span:nth-child(2),
+    span:nth-child(3),
+    span:nth-child(4) {
+      text-align: right;
+    }
+  }
+
+  .setting-item {
+    position: relative;
+    display: grid;
+    grid-template-columns: minmax(320px, 1fr) 260px 150px 132px;
+    align-items: center;
+    gap: 20px;
+    min-height: 76px;
+    padding: 13px 18px;
+    border-bottom: 1px solid #edf1f6;
+    border-radius: 0;
+    background: #fff;
+    color: #1f2937;
+    transition: border-color 0.18s ease, box-shadow 0.18s ease,
+      background 0.18s ease;
+
+    &:hover {
+      background: #fafdff;
+      box-shadow: inset 3px 0 0 #1677ff;
+    }
+
+    &:last-child {
+      border-bottom: 0;
+    }
+
+    &.disabled {
+      background: #f8fafc;
+      color: #98a2b3;
+    }
+
+    &.changed {
+      border-color: #8fc5ff;
+      background: #fbfdff;
+    }
+
+    &.changed .setting-label {
+      color: #1677ff;
+    }
+  }
+
+  .card-actions {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    gap: 6px;
+  }
+
+  .action-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 34px;
+    height: 34px;
+    padding: 0;
+    border: 1px solid #d9e2ef;
+    border-radius: 6px;
+    background: #fff;
+    color: #344054;
+    cursor: pointer;
+    outline: none;
+    transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease,
+      box-shadow 0.16s ease;
+
+    i {
+      font-size: 15px;
+    }
+
+    &.primary {
+      border-color: #b9d7ff;
+      background: #eef6ff;
+      color: #1677ff;
+
+      &:hover {
+        border-color: #1677ff;
+        background: #1677ff;
+        color: #fff;
+        box-shadow: 0 6px 14px rgba(22, 119, 255, 0.2);
+      }
+    }
+
+    &.info {
+      border-color: #bce7ef;
+      background: #f2fbfd;
+      color: #0b83a5;
+
+      &:hover {
+        border-color: #13a8c7;
+        background: #13a8c7;
+        color: #fff;
+        box-shadow: 0 6px 14px rgba(19, 168, 199, 0.18);
+      }
+    }
+
+    &.danger {
+      border-color: #ffb4ae;
+      background: #fff7f6;
+      color: #f04438;
+
+      &:hover {
+        border-color: #f04438;
+        background: #f04438;
+        color: #fff;
+        box-shadow: 0 6px 14px rgba(240, 68, 56, 0.18);
+      }
+    }
+
+    &.danger:hover {
+      border-color: #f04438;
+    }
+  }
+
+  .setting-info {
+    min-width: 0;
+  }
+
+  .setting-label {
+    display: block;
+    max-width: 100%;
+    overflow: hidden;
+    color: #101828;
+    font-size: 15px;
+    font-weight: 600;
+    line-height: 23px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .setting-code-row {
+    display: flex;
+    align-items: flex-start;
+    gap: 8px;
+    max-width: 100%;
+    margin-top: 8px;
+  }
+
+  .code-label {
+    flex: 0 0 auto;
+    height: 22px;
+    padding: 0 7px;
+    border-radius: 4px;
+    background: #eaf2ff;
+    color: #1677ff;
+    font-size: 12px;
+    line-height: 22px;
+  }
+
+  .setting-code {
+    display: block;
+    min-width: 0;
+    padding: 3px 8px;
+    border-radius: 4px;
+    background: #f1f5f9;
+    color: #667085;
+    font-family: Consolas, Monaco, monospace;
+    font-size: 12px;
+    line-height: 18px;
+    overflow-wrap: anywhere;
+    word-break: break-all;
+  }
+
+  .setting-control {
+    display: contents;
+  }
+
+  .value-block,
+  .state-block {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    min-width: 0;
+    gap: 10px;
+  }
+
+  .control-label {
+    display: none;
+    color: #7b8794;
+    font-size: 12px;
+    font-weight: 700;
+  }
+
+  .value-editor {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    width: 220px;
+    min-height: 40px;
+
+    ::v-deep .el-select,
+    ::v-deep .el-input {
+      width: 100%;
+    }
+
+    ::v-deep .el-input__inner {
+      height: 38px;
+      line-height: 38px;
+      border-color: #d9e0ea;
+      border-radius: 6px;
+      background: #fbfcfe;
+    }
+
+    ::v-deep .el-checkbox__inner {
+      width: 18px;
+      height: 18px;
+      border-radius: 4px;
+
+      &::after {
+        top: 2px;
+        left: 6px;
+        height: 9px;
+      }
+    }
+
+    ::v-deep .el-checkbox__label {
+      color: #344054;
+      font-weight: 600;
+    }
+  }
+
+  .yes-no-control {
+    display: inline-grid;
+    grid-template-columns: 1fr 1fr;
+    width: 116px;
+    height: 32px;
+    padding: 3px;
+    border: 1px solid #d9e4f2;
+    border-radius: 16px;
+    background: linear-gradient(180deg, #f8fbff 0%, #edf3fa 100%);
+    box-shadow: inset 0 1px 2px rgba(16, 24, 40, 0.05);
+
+    button {
+      border: 0;
+      border-radius: 13px;
+      background: transparent;
+      color: #5f6f86;
+      font-size: 13px;
+      font-weight: 600;
+      cursor: pointer;
+      outline: none;
+      transition: all 0.16s ease;
+
+      &.active {
+        color: #fff;
+      }
+
+      &.active.yes {
+        background: linear-gradient(135deg, #2f91ff 0%, #1677ff 100%);
+        box-shadow: 0 4px 10px rgba(22, 119, 255, 0.2);
+      }
+
+      &.active.no {
+        background: linear-gradient(135deg, #8b9bb0 0%, #6f8097 100%);
+        box-shadow: 0 4px 10px rgba(100, 116, 139, 0.16);
+      }
+
+      &:disabled {
+        cursor: not-allowed;
+      }
+    }
+
+    &.disabled {
+      opacity: 0.58;
+    }
+  }
+
+  .state-editor {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    width: 142px;
+    min-height: 34px;
+    color: #667085;
+    font-size: 13px;
+    white-space: nowrap;
+  }
+
+  .state-pill {
+    display: inline-flex;
+    align-items: center;
+    gap: 7px;
+    height: 26px;
+    padding: 0 8px;
+    border: 0;
+    border-radius: 4px;
+    background: transparent;
+    color: #079455;
+    font-size: 13px;
+    font-weight: 600;
+
+    i {
+      width: 7px;
+      height: 7px;
+      border-radius: 50%;
+      background: #12b76a;
+      box-shadow: 0 0 0 3px rgba(18, 183, 106, 0.13);
+    }
+
+    &.off {
+      border-color: #d8dee8;
+      background: #f4f6f9;
+      color: #667085;
+
+      i {
+        background: #98a2b3;
+        box-shadow: 0 0 0 3px rgba(152, 162, 179, 0.14);
+      }
+    }
+  }
+
+  .enable-switch {
+    flex: 0 0 auto;
+  }
+
+  .save-state {
+    position: absolute;
+    top: 50%;
+    right: 164px;
+    z-index: 1;
+    width: 18px;
+    height: 18px;
+    margin-top: -9px;
+    color: #8b96a5;
+    font-size: 16px;
+    line-height: 18px;
+    text-align: center;
+    pointer-events: none;
+
+    &.success {
+      color: #2fb344;
+    }
+  }
+
+  @media (max-width: 1500px) {
+    .setting-head,
+    .setting-item {
+      grid-template-columns: minmax(300px, 1fr) 240px 150px 132px;
+      gap: 14px;
+    }
+
+    .value-editor {
+      width: 210px;
+    }
+  }
+
+  @media (max-width: 1200px) {
+    .setting-head {
+      display: none;
+    }
+
+    .setting-item {
+      grid-template-columns: 1fr;
+      align-items: stretch;
+    }
+
+    .save-state {
+      right: 18px;
+      top: 18px;
+      margin-top: 0;
+    }
+
+    .setting-control,
+    .card-actions {
+      justify-content: flex-start;
+    }
+
+    .setting-control {
+      display: grid;
+      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+      gap: 12px;
+    }
+
+    .value-block,
+    .state-block {
+      justify-content: flex-start;
+    }
+
+    .control-label {
+      display: inline-block;
+      width: 56px;
+    }
+  }
+
+  @media (max-width: 900px) {
+    .parameter-setting-page {
+      height: auto;
+      min-height: calc(100vh - 84px);
+      overflow: visible;
+    }
+
+    .parameter-shell {
+      display: block;
+      height: auto;
+    }
+
+    .module-nav {
+      position: static;
+      display: flex;
+      height: auto;
+      max-height: none;
+      width: 100%;
+      overflow-x: auto;
+      overflow-y: hidden;
+      padding: 8px;
+    }
+
+    .module-nav-title {
+      display: none;
+    }
+
+    .module-nav-item {
+      flex: 0 0 136px;
+      margin-right: 6px;
+      margin-bottom: 0;
+
+      &.active {
+        box-shadow: none;
+      }
+    }
+
+    .parameter-content {
+      padding: 16px;
+    }
+
+    .parameter-search {
+      display: block;
+
+      ::v-deep .el-form-item {
+        width: 100%;
+        margin-bottom: 12px;
+      }
+    }
+
+    .parameter-toolbar {
+      display: block;
+    }
+
+    .setting-control {
+      grid-template-columns: 1fr;
+    }
+
+    .setting-item {
+      padding: 12px 0;
+      border-bottom: 1px solid #edf0f5;
+    }
+
+    .value-editor,
+    .state-editor {
+      width: 100%;
+      margin-top: 10px;
+      justify-content: flex-start;
+    }
+
+    .card-actions {
+      margin-top: 12px;
+      justify-content: flex-start;
+    }
+  }
+</style>

+ 7 - 1
src/views/technology/productParam/index.vue

@@ -49,7 +49,7 @@
             :underline="false"
             icon="el-icon-edit"
             @click="openEdit(row)"
-            v-if="$hasPermission('main:categoryparam:update')"
+            v-if="canEdit(row)"
           >
             修改
           </el-link>
@@ -172,6 +172,12 @@
         const obj = this.statusList.find((item) => item.value == id);
         return obj.label;
       },
+      canEdit(row) {
+        return (
+          this.$hasPermission('main:categoryparam:update') ||
+          row.isPublished == 0
+        );
+      },
       /* 表格数据源 */
       async datasource({ page, limit, where, order }) {
         const res = await parameter.list({

+ 28 - 22
src/views/technology/production/components/user-edit.vue

@@ -276,7 +276,7 @@
       <header-title title="工序配置"></header-title>
 
       <el-row>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加周转车:" label-width="200px">
             <el-radio-group v-model="form.feedNeedTurnover">
               <el-radio
@@ -289,7 +289,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="报工是否要添加周转车:" label-width="200px">
             <el-radio-group v-model="form.reportNeedTurnover">
               <el-radio
@@ -302,7 +302,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="是否需要投料再报工:" label-width="200px">
             <el-radio-group v-model="form.reportNeedFeed">
               <el-radio
@@ -316,7 +316,7 @@
         </el-col>
 
         <!-- **** -->
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加生产设备:" label-width="200px">
             <el-radio-group v-model="form.feedNeedEquipment">
               <el-radio
@@ -328,7 +328,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="报工是否要添加生产设备:" label-width="200px">
             <el-radio-group v-model="form.reportNeedEquipment">
               <el-radio
@@ -341,7 +341,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加模具:" label-width="200px">
             <el-radio-group v-model="form.feedNeedMould">
               <el-radio
@@ -353,7 +353,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加舟皿:" label-width="200px">
             <el-radio-group v-model="form.feedNeedBoat">
               <el-radio
@@ -365,7 +365,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加消耗材料:" label-width="200px">
             <el-radio-group v-model="form.feedNeedConsumableMaterial">
               <el-radio
@@ -377,7 +377,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加物料:" label-width="200px">
             <el-radio-group v-model="form.feedNeedMateriel">
               <el-radio
@@ -390,7 +390,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加产品:" label-width="200px">
             <el-radio-group v-model="form.feedNeedProduct">
               <el-radio
@@ -402,7 +402,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加半成品:" label-width="200px">
             <el-radio-group v-model="form.feedNeedSemiProduct">
               <el-radio
@@ -414,7 +414,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加废品:" label-width="200px">
             <el-radio-group v-model="form.feedNeedJunkProduct">
               <el-radio
@@ -426,7 +426,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加返工反修品:" label-width="200px">
             <el-radio-group v-model="form.feedNeedReworkProduct">
               <el-radio
@@ -439,7 +439,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加干燥区:" label-width="200px">
             <el-radio-group v-model="form.feedNeedAridRegion">
               <el-radio
@@ -451,7 +451,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加生产辅助设备:" label-width="200px">
             <el-radio-group v-model="form.feedNeedAuxiliaryEquipment">
               <el-radio
@@ -463,7 +463,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否要添加仪表计量设备:" label-width="200px">
             <el-radio-group v-model="form.feedNeedMeasuringEquipment">
               <el-radio
@@ -475,7 +475,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="投料是否需要质检:" label-width="200px">
             <el-radio-group v-model="form.feedNeedQuality">
               <el-radio
@@ -487,7 +487,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="生产质检是否需要处置再报工:" label-width="200px">
             <el-radio-group v-model="form.isReportProcessProduce">
               <el-radio
@@ -499,7 +499,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="是否产前准备后再投料:" label-width="200px">
             <el-radio-group v-model="form.isPrenatalPreProduction">
               <el-radio
@@ -511,7 +511,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="是否投料后再过程控制:" label-width="200px">
             <el-radio-group v-model="form.isFeedCheckProduction">
               <el-radio
@@ -523,7 +523,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="是否过程控制后再产后检查:" label-width="200px">
             <el-radio-group v-model="form.isPostCheckProduction">
               <el-radio
@@ -535,7 +535,7 @@
             </el-radio-group>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col v-if="showBaseProcessConfig" :span="12">
           <el-form-item label="是否产后检查后再报工:" label-width="200px">
             <el-radio-group v-model="form.isFinalCheckProduction">
               <el-radio
@@ -745,6 +745,12 @@
       // 是否开启响应式布局
       styleResponsive() {
         return this.$store.state.theme.styleResponsive;
+      },
+      clientEnvironmentId() {
+        return this.$store.state.user.info.clientEnvironmentId;
+      },
+      showBaseProcessConfig() {
+        return this.clientEnvironmentId != 9;
       }
     },
     methods: {

+ 23 - 2
src/views/technology/route/components/user-edit.vue

@@ -224,6 +224,9 @@
       // 是否开启响应式布局
       styleResponsive() {
         return this.$store.state.theme.styleResponsive;
+      },
+      clientEnvironmentId() {
+        return this.$store.state.user.info.clientEnvironmentId;
       }
     },
     methods: {
@@ -278,7 +281,7 @@
 
               // if (msg) {
               this.$message.success(res.message);
-              this.updateVisible(false);
+              this.updateVisible(false, true);
               this.$emit('done', res.data);
               // }
             })
@@ -332,7 +335,13 @@
       },
 
       /* 更新visible */
-      updateVisible(value) {
+      updateVisible(value, force = false) {
+        if (!value && !force && this.shouldTipUnsavedTask()) {
+          this.$message.warning(
+            '新添加的工序尚未保存,请点击下发[确定]按钮进行保存'
+          );
+          return;
+        }
         this.$emit('update:visible', value);
       },
 
@@ -341,6 +350,18 @@
       },
       remove(list) {
         this.removeList = list;
+      },
+      shouldTipUnsavedTask() {
+        if (this.clientEnvironmentId != 9 || this.innerIsUpdate) {
+          return false;
+        }
+        const tableData =
+          this.$refs.taskRef &&
+          this.$refs.taskRef.$refs.table &&
+          this.$refs.taskRef.$refs.table.getData
+            ? this.$refs.taskRef.$refs.table.getData()
+            : this.taskInstanceList;
+        return Array.isArray(tableData) && tableData.length > 0;
       }
     },
 

+ 2 - 2
vue.config.js

@@ -35,7 +35,7 @@ module.exports = {
         // target: 'http://192.168.1.3:18086',
         // target: 'http://192.168.1.158:18086',
         // target: 'http://192.168.1.176:18086',
-        // target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.125:18086',
         // target: 'http://192.168.1.251:51005',
         // target: 'http://192.168.1.251:18186',
         // target: 'http://192.168.1.251:18086',
@@ -47,7 +47,7 @@ module.exports = {
         // target: 'http://192.168.1.125:18086',
         // target: 'http://192.168.1.11:18086', // 开发
         // target: 'http://192.168.1.116:18086', // 赵沙金
-        target: 'http://aiot.zoomwin.com.cn:51001/api',
+        // target: 'http://aiot.zoomwin.com.cn:51001/api',
         // target: 'http://f222326r53.imwork.net',
         // target: 'http://aiot.zoomwin.com.cn:51005/api',