qushaowei
2024-07-25 52190152691bc217844d4f87b700274c297b104e
src/views/system/modules/UserModal.vue
@@ -130,7 +130,8 @@
            @back="backDepartInfo"
            :backDepart="true"
            :treeOpera="true"
          >></j-select-depart>
          >>
          </j-select-depart>
        </a-form-model-item>
        <!--车间分配-->
@@ -148,6 +149,40 @@
            :treeProductOpera="true"
          ></j-select-production>
        </a-form-model-item>
        <a-form-model-item
          label="选择设备"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          v-show="!productionDisabled"
        >
          <a-input-search
            :readOnly="true"
            v-model="model.equipmentIds"
            @search="deviceSearch"
            enter-button
            placeholder="请选择设备"
            :disabled="!model.selectedProduction"
          />
        </a-form-model-item>
        <a-form-model-item
          label="首页权限"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-radio-group
            v-model="model.userType"
            :defaultValue="0"
          >
            <a-radio :value="4">公司级</a-radio>
            <a-radio :value="3">车间级</a-radio>
            <a-radio :value="2">工段级</a-radio>
            <a-radio :value="1">操作工</a-radio>
            <a-radio :value="0">无</a-radio>
          </a-radio-group>
        </a-form-model-item>
        <a-form-model-item
          label="班组分配"
          :labelCol="labelCol"
@@ -167,12 +202,19 @@
          :wrapperCol="wrapperCol"
          prop="areaId"
        >
          <j-dict-select-tag
          <!-- <j-dict-select-tag
            v-model="model.areaId"
            :triggerChange="true"
            dictCode="mom_base_area,name,id,del_flag = 0"
            placeholder="请维护中心"
          ></j-dict-select-tag>
          ></j-dict-select-tag> -->
          <j-multi-select-tag
            :triggerChange="true"
            v-model="model.areaId"
            dictCode="mom_base_area,name,id,del_flag = 0 and type = 1"
            placeholder="请维护中心"
          >
          </j-multi-select-tag>
        </a-form-model-item>
        <a-form-model-item
          label="负责部门"
@@ -189,83 +231,82 @@
          </j-multi-select-tag>
        </a-form-model-item>
        <a-form-model-item
          label="头像"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <j-image-upload
            class="avatar-uploader"
            text="上传"
            v-model="model.avatar"
          ></j-image-upload>
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="头像"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<j-image-upload-->
        <!--class="avatar-uploader"-->
        <!--text="上传"-->
        <!--v-model="model.avatar"-->
        <!--&gt;</j-image-upload>-->
        <!--</a-form-model-item>-->
        <a-form-model-item
          label="生日"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-date-picker
            style="width: 100%"
            placeholder="请选择生日"
            v-model="model.birthday"
            :format="dateFormat"
            :getCalendarContainer="node => node.parentNode"
          />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="生日"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<a-date-picker-->
        <!--style="width: 100%"-->
        <!--placeholder="请选择生日"-->
        <!--v-model="model.birthday"-->
        <!--:format="dateFormat"-->
        <!--:getCalendarContainer="node => node.parentNode"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item
          label="性别"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-select
            v-model="model.sex"
            placeholder="请选择性别"
            :getPopupContainer="(target) => target.parentNode"
          >
            <a-select-option :value="1">男</a-select-option>
            <a-select-option :value="2">女</a-select-option>
          </a-select>
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="性别"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<a-select-->
        <!--v-model="model.sex"-->
        <!--placeholder="请选择性别"-->
        <!--:getPopupContainer="(target) => target.parentNode"-->
        <!--&gt;-->
        <!--<a-select-option :value="1">男</a-select-option>-->
        <!--<a-select-option :value="2">女</a-select-option>-->
        <!--</a-select>-->
        <!--</a-form-model-item>-->
        <a-form-model-item
          label="邮箱"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="email"
        >
          <a-input
            placeholder="请输入邮箱"
            v-model="model.email"
          />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="邮箱"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="email"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入邮箱"-->
        <!--v-model="model.email"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item
          label="手机号码"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="phone"
        >
          <a-input
            placeholder="请输入手机号码"
            v-model="model.phone"
          />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="手机号码"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="phone"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入手机号码"-->
        <!--v-model="model.phone"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item
          label="座机"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="telephone"
        >
          <a-input
            placeholder="请输入座机"
            v-model="model.telephone"
          />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="座机"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="telephone"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入座机"-->
        <!--v-model="model.telephone"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item label="工作流引擎" :labelCol="labelCol" :wrapperCol="wrapperCol">-->
        <!--<j-dict-select-tag  v-model="model.activitiSync"  placeholder="请选择是否同步工作流引擎" :type="'radio'" dictCode="activiti_sync"/>-->
        <!--</a-form-model-item>-->
@@ -289,26 +330,35 @@
        @click="handleSubmit"
        type="primary"
        :loading="confirmLoading"
      >提交</a-button>
      >提交
      </a-button>
    </div>
    <select-device-modal
      ref="selectDeviceModal"
      @selectFinished="selectOK"
      :title="'选择设备'"
    />
  </a-drawer>
</template>
<script>
import moment from 'moment'
import Vue from 'vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { getAction } from '@/api/manage'
import { addUser, editUser, queryUserRole, queryall } from '@/api/api'
import { disabledAuthFilter } from "@/utils/authFilter"
import { disabledAuthFilter } from '@/utils/authFilter'
import { duplicateCheck } from '@/api/api'
import JSelectProduction from '../../../components/jeecgbiz/JSelectProduction'
import { mapActions } from 'vuex'
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
import SelectDeviceModal from './SelectDeviceModal'
export default {
  name: "UserModal",
  name: 'UserModal',
  components: {
    SelectDeviceModal,
    JSelectProduction
  },
  data() {
@@ -320,48 +370,51 @@
      drawerWidth: 700,
      modaltoggleFlag: true,
      confirmDirty: false,
      userId: "", //保存用户id
      userId: '', //保存用户id
      disableSubmit: false,
      dateFormat: "YYYY-MM-DD",
      dateFormat: 'YYYY-MM-DD',
      validatorRules: {
        username: [{ required: true, message: '请输入用户账号!' },
        { validator: this.validateUsername, }],
        password: [{ required: true, pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/, message: '密码由8位数字、大小写字母和特殊符号组成!' },
        { validator: this.validateUsername }],
        password: [{
          required: true,
          pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
          message: '密码由8位数字、大小写字母和特殊符号组成!'
        },
        { validator: this.validateToNextPassword, trigger: 'change' }],
        confirmpassword: [{ required: true, message: '请重新输入登录密码!', },
        { validator: this.compareToFirstPassword, }],
        confirmpassword: [{ required: true, message: '请重新输入登录密码!' },
        { validator: this.compareToFirstPassword }],
        realname: [{ required: true, message: '请输入用户名称!' }],
        phone: [{ required: false, message: '请输入手机号!' }, { validator: this.validatePhone }],
        email: [{ validator: this.validateEmail }],
        roles: {},
        workNo: [{ required: true, message: '请输入工号' },
        { validator: this.validateWorkNo }],
        telephone: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' },],
        telephone: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' }],
        teamId: [{ required: false, message: '请维护班组' }]
      },
      departIdShow: false,
      title: "操作",
      title: '操作',
      visible: false,
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
        sm: { span: 16 }
      },
      uploadLoading: false,
      confirmLoading: false,
      headers: {},
      url: {
        fileUpload: window._CONFIG['domianURL'] + "sys/common/upload",
        userWithDepart: "/sys/user/userDepartList", // 引入为指定用户查看部门信息需要的url
        fileUpload: window._CONFIG['domianURL'] + 'sys/common/upload',
        userWithDepart: '/sys/user/userDepartList', // 引入为指定用户查看部门信息需要的url
        //引入为指定用户查看车间信息需要的url
        userProductionList: '/sys/user/userProductionList',
        userId: "/sys/user/generateUserId", // 引入生成添加用户情况下的url
        syncUserByUserName: "/act/process/extActProcess/doSyncUserByUserName",//同步用户到工作流
        userId: '/sys/user/generateUserId', // 引入生成添加用户情况下的url
        syncUserByUserName: '/act/process/extActProcess/doSyncUserByUserName',//同步用户到工作流
        queryTenantList: '/sys/tenant/queryList'
      },
      tenantsOptions: [],
@@ -369,7 +422,9 @@
      nextDepartOptions: [],
      nextProductionOptions: [],
      isDepartType: '',
      model: {
        selectedProduction: ''
      }
    }
  },
  watch: {
@@ -377,18 +432,29 @@
      handler(value) {
        if (value) this.initDictData('password_length')
      }
    },
    'model.selectedProduction': {
      handler(newVal, oldVal) {
        if (newVal && this.$refs.selectDeviceModal) {
          // 如果车间选择前后不一致则重置选择设备
          if ((oldVal && newVal !== oldVal)) this.model.equipmentIds = ''
          this.$refs.selectDeviceModal.queryTreeData(newVal)
        }
        // 如果清空车间值则重置选择设备
        if (newVal === '') this.model.equipmentIds = ''
      }
    }
  },
  created() {
    const token = Vue.ls.get(ACCESS_TOKEN);
    this.headers = { "X-Access-Token": token }
    const token = Vue.ls.get(ACCESS_TOKEN)
    this.headers = { 'X-Access-Token': token }
    this.initRoleList()
    this.initTenantList()
    this.queryTreeData()
  },
  computed: {
    uploadAction: function () {
      return this.url.fileUpload;
      return this.url.fileUpload
    }
  },
  methods: {
@@ -402,56 +468,61 @@
          this.$notification.warning({
            message: '消息',
            description: res.message
          });
          })
        }
      }).finally(() => {
      })
    },
    add() {
      this.refresh();
      this.edit({ activitiSync: '1', userIdentity: 1 });
      this.refresh()
      this.edit({
        activitiSync: '1',
        userType: 0,
        userIdentity: 1,
        selectedroles: '',
        selecteddeparts: '',
        selectedProduction: ''
      })
    },
    edit(record) {
      let that = this;
      that.visible = true;
      let that = this
      that.visible = true
      //根据屏幕宽度自适应抽屉宽度
      this.resetScreenSize();
      that.userId = record.id;
      that.model = Object.assign({}, { selectedroles: '', selecteddeparts: '' }, record);
      that.model = Object.assign({}, { selectedroles: '', selectedProduction: '' }, record);
      this.resetScreenSize()
      that.userId = record.id
      console.log('record', record)
      that.model = Object.assign({}, record)
      //身份为上级显示负责部门,否则不显示
      if (this.model.userIdentity == 2) {
        this.departIdShow = true;
        this.departIdShow = true
      } else {
        this.departIdShow = false;
        this.departIdShow = false
      }
      if (record.hasOwnProperty("id")) {
        that.getUserRoles(record.id);
        that.getUserDeparts(record.id);
      if (record.hasOwnProperty('id')) {
        that.getUserRoles(record.id)
        that.getUserDeparts(record.id)
      }
      console.log('that.model', that.model)
    },
    isDisabledAuth(code) {
      return disabledAuthFilter(code);
      return disabledAuthFilter(code)
    },
    //窗口最大化切换
    toggleScreen() {
      if (this.modaltoggleFlag) {
        this.modalWidth = window.innerWidth;
        this.modalWidth = window.innerWidth
      } else {
        this.modalWidth = 800;
        this.modalWidth = 800
      }
      this.modaltoggleFlag = !this.modaltoggleFlag;
      this.modaltoggleFlag = !this.modaltoggleFlag
    },
    // 根据屏幕变化,设置抽屉尺寸
    resetScreenSize() {
      let screenWidth = document.body.clientWidth;
      let screenWidth = document.body.clientWidth
      if (screenWidth < 500) {
        this.drawerWidth = screenWidth;
        this.drawerWidth = screenWidth
      } else {
        this.drawerWidth = 700;
        this.drawerWidth = 700
      }
    },
    //初始化租户字典
@@ -459,10 +530,9 @@
      getAction(this.url.queryTenantList).then(res => {
        if (res.success) {
          this.tenantsOptions = res.result.map((item, index, arr) => {
            let c = { label: item.name, value: item.id + "" }
            return c;
            let c = { label: item.name, value: item.id + '' }
            return c
          })
          console.log('this.tenantsOptions: ', this.tenantsOptions)
        }
      })
    },
@@ -472,29 +542,27 @@
        if (res.success) {
          this.rolesOptions = res.result.map((item, index, arr) => {
            let c = { label: item.roleName, value: item.id }
            return c;
            return c
          })
          console.log('this.rolesOptions: ', this.rolesOptions)
        }
      });
      })
    },
    getUserRoles(userid) {
      queryUserRole({ userid: userid }).then((res) => {
        if (res.success) {
          this.model.selectedroles = res.result.join(",");
          console.log('that.model.selectedroles=', this.model.selectedroles)
          this.$set(this.model, 'selectedroles', res.result.join(','))
        }
      });
      })
    },
    getUserDeparts(userid) {
      let that = this;
      //部门的url
      let that = this
      //部门的url 获取部门分配
      getAction(that.url.userWithDepart, { userId: userid }).then((res) => {
        if (res.success) {
          let departOptions = [];
          let departOptions = []
          let selectDepartKeys = []
          for (let i = 0; i < res.result.length; i++) {
            selectDepartKeys.push(res.result[i].key);
            selectDepartKeys.push(res.result[i].key)
            //新增负责部门选择下拉框
            departOptions.push({
              value: res.result[i].key,
@@ -502,20 +570,18 @@
            })
          }
          that.model.selecteddeparts = selectDepartKeys.join(",")
          that.model.selectedProduction = selectDepartKeys.join(",")
          that.nextDepartOptions = departOptions;
          console.log('that.nextDepartOptions=', that.nextDepartOptions)
          this.$set(this.model, 'selecteddeparts', selectDepartKeys.join(','))
          that.nextDepartOptions = departOptions
        }
      })
      // 获取车间分配
      getAction(that.url.userProductionList, { userId: userid }).then((res) => {
        if (res.success) {
          let ProductionOptions = [];
          let ProductionOptions = []
          let selectProductKeys = []
          for (let i = 0; i < res.result.length; i++) {
            selectProductKeys.push(res.result[i].key);
            selectProductKeys.push(res.result[i].key)
            //新增负责部门选择下拉框
            ProductionOptions.push({
              value: res.result[i].key,
@@ -523,75 +589,73 @@
            })
          }
          that.model.selectedProduction = selectProductKeys.join(",")
          that.nextProductionOptions = ProductionOptions;
          console.log('that.nextProductionOptions=', that.nextProductionOptions)
          this.$set(this.model, 'selectedProduction', selectProductKeys.join(','))
          that.nextProductionOptions = ProductionOptions
        }
      })
      //车间的url
    },
    backDepartInfo(info) {
      this.model.departIds = this.model.selecteddeparts;
      this.model.departIds = this.model.selecteddeparts
      this.nextDepartOptions = info.map((item, index, arr) => {
        let c = { label: item.text, value: item.value + "" }
        return c;
        let c = { label: item.text, value: item.value + '' }
        return c
      })
    },
    backProductionInfo(info) {
      this.model.productionIds = this.model.selectedProduction;
      this.model.productionIds = this.model.selectedProduction
      this.nextProductionOptions = info.map((item, index, arr) => {
        let c = { label: item.text, value: item.value + "" }
        return c;
        let c = { label: item.text, value: item.value + '' }
        return c
      })
    },
    refresh() {
      this.userId = ""
      this.nextDepartOptions = [];
      this.nextProductionOptions = [];
      this.departIdShow = false;
      this.userId = ''
      this.nextDepartOptions = []
      this.nextProductionOptions = []
      this.departIdShow = false
    },
    close() {
      this.$emit('close');
      this.visible = false;
      this.disableSubmit = false;
      this.nextDepartOptions = [];
      this.$emit('close')
      this.visible = false
      this.disableSubmit = false
      this.nextDepartOptions = []
      this.nextProductionOptions = []
      this.departIdShow = false;
      this.$refs.form.resetFields();
      this.departIdShow = false
      this.$refs.form.resetFields()
    },
    moment,
    handleSubmit() {
      const that = this;
      const that = this
      // 触发表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true;
          that.confirmLoading = true
          //如果是上级择传入departIds,否则为空
          if (this.model.userIdentity !== 2) {
            this.model.departIds = "";
            this.model.departIds = ''
          }
          let obj;
          let obj
          if (!this.model.id) {
            this.model.id = this.userId;
            obj = addUser(this.model);
            this.model.id = this.userId
            obj = addUser(this.model)
          } else {
            obj = editUser(this.model);
            obj = editUser(this.model)
          }
          obj.then((res) => {
            if (res.success) {
              that.$message.success(res.message);
              that.$emit('ok');
              that.$message.success(res.message)
              that.$emit('ok')
            } else {
              that.$message.warning(res.message);
              that.$message.warning(res.message)
            }
          }).finally(() => {
            that.confirmLoading = false;
            that.close();
            that.confirmLoading = false
            that.close()
          })
        } else {
          return false;
          return false
        }
      })
    },
@@ -599,18 +663,18 @@
      this.close()
    },
    validateToNextPassword(rule, value, callback) {
      const confirmpassword = this.model.confirmpassword;
      const confirmpassword = this.model.confirmpassword
      if (value && confirmpassword && value !== confirmpassword) {
        callback('两次输入的密码不一样!');
        callback('两次输入的密码不一样!')
      }
      if (value && this.confirmDirty) {
        this.$refs.form.validateField(['confirmpassword']);
        this.$refs.form.validateField(['confirmpassword'])
      }
      callback();
      callback()
    },
    compareToFirstPassword(rule, value, callback) {
      if (value && value !== this.model.password) {
        callback('两次输入的密码不一样!');
        callback('两次输入的密码不一样!')
      } else {
        callback()
      }
@@ -625,16 +689,16 @@
            fieldName: 'phone',
            fieldVal: value,
            dataId: this.userId
          };
          }
          duplicateCheck(params).then((res) => {
            if (res.success) {
              callback()
            } else {
              callback("手机号已存在!")
              callback('手机号已存在!')
            }
          })
        } else {
          callback("请输入正确格式的手机号码!");
          callback('请输入正确格式的手机号码!')
        }
      }
    },
@@ -648,17 +712,17 @@
            fieldName: 'email',
            fieldVal: value,
            dataId: this.userId
          };
          }
          duplicateCheck(params).then((res) => {
            console.log(res)
            if (res.success) {
              callback()
            } else {
              callback("邮箱已存在!")
              callback('邮箱已存在!')
            }
          })
        } else {
          callback("请输入正确格式的邮箱!")
          callback('请输入正确格式的邮箱!')
        }
      }
    },
@@ -668,12 +732,12 @@
        fieldName: 'username',
        fieldVal: value,
        dataId: this.userId
      };
      }
      duplicateCheck(params).then((res) => {
        if (res.success) {
          callback()
        } else {
          callback("用户名已存在!")
          callback('用户名已存在!')
        }
      })
    },
@@ -683,49 +747,65 @@
        fieldName: 'work_no',
        fieldVal: value,
        dataId: this.userId
      };
      }
      duplicateCheck(params).then((res) => {
        if (res.success) {
          callback()
        } else {
          callback("工号已存在!")
          callback('工号已存在!')
        }
      })
    },
    handleConfirmBlur(e) {
      const value = e.target.value;
      const value = e.target.value
      this.confirmDirty = this.confirmDirty || !!value
    },
    beforeUpload: function (file) {
      var fileType = file.type;
      var fileType = file.type
      if (fileType.indexOf('image') < 0) {
        this.$message.warning('请上传图片');
        return false;
        this.$message.warning('请上传图片')
        return false
      }
      //TODO 验证文件大小
    },
    identityChange(e) {
      if (e.target.value === 1) {
        this.departIdShow = false;
        this.departIdShow = false
      } else {
        this.departIdShow = true;
        this.departIdShow = true
      }
    },
    initDictData(dictCode) {
      //根据字典Code, 初始化字典数组
      ajaxGetDictItems(dictCode, null).then((res) => {
        if (res.success) {
          const regExp = new RegExp("^(?=.*[a-zA-Z])(?=.*\\\d)(?=.*[~!@#$%^&*()_+`\\-={}:\";'<>?,./]).{" + Number(res.result[0].value) + ",}$");
          const regExp = new RegExp('^(?=.*[a-zA-Z])(?=.*\\\d)(?=.*[~!@#$%^&*()_+`\\-={}:";\'<>?,./]).{' + Number(res.result[0].value) + ',}$')
          this.validatorRules.password[0] = {
            required: true,
            pattern: regExp,
            message: `密码由${res.result[0].value}位数字、大小写字母和特殊符号组成!`,
            message: `密码由${res.result[0].value}位数字、大小写字母和特殊符号组成!`
          }
        }
      })
    },
    deviceSearch() {
      this.$refs.selectDeviceModal.visible = true
      this.$refs.selectDeviceModal.selectedRowKeys = []
      this.$refs.selectDeviceModal.selectedRows = []
      this.$refs.selectDeviceModal.checkedKeys = this.model.equipmentIds ? this.model.equipmentIds.split(',') : []
    },
    /**
     * 选择已有设备后点击确定时触发
     * @param data 已选择的设备数组
     */
    selectOK(data) {
      console.log('data=', data)
      this.$set(this.model, 'equipmentIds', data.join(','))
    }
  }
}
</script>
@@ -735,6 +815,7 @@
  width: 104px;
  height: 104px;
}
.ant-upload-select-picture-card i {
  font-size: 49px;
  color: #999;